diff options
author | Max Kellermann <max@duempel.org> | 2012-10-02 09:42:03 +0200 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2012-10-02 09:42:03 +0200 |
commit | 1cf4b5ce47f93a056e2e7e934aa6f0fac1337bfc (patch) | |
tree | ae85159bc9c399a1c509cedfc3ed67c90b47afaa /src/encoder/OpusEncoderPlugin.cxx | |
parent | 1badb3b5d5d095815a07116c491240db44abb344 (diff) | |
download | mpd-1cf4b5ce47f93a056e2e7e934aa6f0fac1337bfc.tar.gz mpd-1cf4b5ce47f93a056e2e7e934aa6f0fac1337bfc.tar.xz mpd-1cf4b5ce47f93a056e2e7e934aa6f0fac1337bfc.zip |
encoder/opus: implement lookahead
The "opusinfo" program complained about preskip value that was too
small. This commit uses OPUS_GET_LOOKAHEAD to obtain the number of
frames that shall be silence at the beginning.
Diffstat (limited to '')
-rw-r--r-- | src/encoder/OpusEncoderPlugin.cxx | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/src/encoder/OpusEncoderPlugin.cxx b/src/encoder/OpusEncoderPlugin.cxx index 043a9e767..9f46e8681 100644 --- a/src/encoder/OpusEncoderPlugin.cxx +++ b/src/encoder/OpusEncoderPlugin.cxx @@ -62,6 +62,8 @@ struct opus_encoder { OggStream stream; + int lookahead; + ogg_int64_t packetno; ogg_int64_t granulepos; @@ -192,6 +194,8 @@ opus_encoder_open(struct encoder *_encoder, OPUS_SET_COMPLEXITY(encoder->complexity)); opus_encoder_ctl(encoder->enc, OPUS_SET_SIGNAL(encoder->signal)); + opus_encoder_ctl(encoder->enc, OPUS_GET_LOOKAHEAD(&encoder->lookahead)); + encoder->buffer_frames = audio_format->sample_rate / 50; encoder->buffer_size = encoder->frame_size * encoder->buffer_frames; encoder->buffer_position = 0; @@ -277,6 +281,31 @@ opus_encoder_flush(struct encoder *_encoder, G_GNUC_UNUSED GError **error) } static bool +opus_encoder_write_silence(struct opus_encoder *encoder, unsigned fill_frames, + GError **error_r) +{ + size_t fill_bytes = fill_frames * encoder->frame_size; + + while (fill_bytes > 0) { + size_t nbytes = + encoder->buffer_size - encoder->buffer_position; + if (nbytes > fill_bytes) + nbytes = fill_bytes; + + memset(encoder->buffer + encoder->buffer_position, + 0, nbytes); + encoder->buffer_position += nbytes; + fill_bytes -= nbytes; + + if (encoder->buffer_position == encoder->buffer_size && + !opus_encoder_do_encode(encoder, false, error_r)) + return false; + } + + return true; +} + +static bool opus_encoder_write(struct encoder *_encoder, const void *_data, size_t length, GError **error_r) @@ -284,6 +313,19 @@ opus_encoder_write(struct encoder *_encoder, struct opus_encoder *encoder = (struct opus_encoder *)_encoder; const uint8_t *data = (const uint8_t *)_data; + if (encoder->lookahead > 0) { + /* generate some silence at the beginning of the + stream */ + + assert(encoder->buffer_position == 0); + + if (!opus_encoder_write_silence(encoder, encoder->lookahead, + error_r)) + return false; + + encoder->lookahead = 0; + } + while (length > 0) { size_t nbytes = encoder->buffer_size - encoder->buffer_position; @@ -311,8 +353,7 @@ opus_encoder_generate_head(struct opus_encoder *encoder) memcpy(header, "OpusHead", 8); header[8] = 1; header[9] = encoder->audio_format.channels; - header[10] = 0; - header[11] = 0; + *(uint16_t *)(header + 10) = GUINT16_TO_LE(encoder->lookahead); *(uint32_t *)(header + 12) = GUINT32_TO_LE(encoder->audio_format.sample_rate); header[16] = 0; |