Commit 1cf4b5ce authored by Max Kellermann's avatar Max Kellermann

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.
parent 1badb3b5
...@@ -62,6 +62,8 @@ struct opus_encoder { ...@@ -62,6 +62,8 @@ struct opus_encoder {
OggStream stream; OggStream stream;
int lookahead;
ogg_int64_t packetno; ogg_int64_t packetno;
ogg_int64_t granulepos; ogg_int64_t granulepos;
...@@ -192,6 +194,8 @@ opus_encoder_open(struct encoder *_encoder, ...@@ -192,6 +194,8 @@ opus_encoder_open(struct encoder *_encoder,
OPUS_SET_COMPLEXITY(encoder->complexity)); OPUS_SET_COMPLEXITY(encoder->complexity));
opus_encoder_ctl(encoder->enc, OPUS_SET_SIGNAL(encoder->signal)); 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_frames = audio_format->sample_rate / 50;
encoder->buffer_size = encoder->frame_size * encoder->buffer_frames; encoder->buffer_size = encoder->frame_size * encoder->buffer_frames;
encoder->buffer_position = 0; encoder->buffer_position = 0;
...@@ -277,6 +281,31 @@ opus_encoder_flush(struct encoder *_encoder, G_GNUC_UNUSED GError **error) ...@@ -277,6 +281,31 @@ opus_encoder_flush(struct encoder *_encoder, G_GNUC_UNUSED GError **error)
} }
static bool 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, opus_encoder_write(struct encoder *_encoder,
const void *_data, size_t length, const void *_data, size_t length,
GError **error_r) GError **error_r)
...@@ -284,6 +313,19 @@ opus_encoder_write(struct encoder *_encoder, ...@@ -284,6 +313,19 @@ opus_encoder_write(struct encoder *_encoder,
struct opus_encoder *encoder = (struct opus_encoder *)_encoder; struct opus_encoder *encoder = (struct opus_encoder *)_encoder;
const uint8_t *data = (const uint8_t *)_data; 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) { while (length > 0) {
size_t nbytes = size_t nbytes =
encoder->buffer_size - encoder->buffer_position; encoder->buffer_size - encoder->buffer_position;
...@@ -311,8 +353,7 @@ opus_encoder_generate_head(struct opus_encoder *encoder) ...@@ -311,8 +353,7 @@ opus_encoder_generate_head(struct opus_encoder *encoder)
memcpy(header, "OpusHead", 8); memcpy(header, "OpusHead", 8);
header[8] = 1; header[8] = 1;
header[9] = encoder->audio_format.channels; header[9] = encoder->audio_format.channels;
header[10] = 0; *(uint16_t *)(header + 10) = GUINT16_TO_LE(encoder->lookahead);
header[11] = 0;
*(uint32_t *)(header + 12) = *(uint32_t *)(header + 12) =
GUINT32_TO_LE(encoder->audio_format.sample_rate); GUINT32_TO_LE(encoder->audio_format.sample_rate);
header[16] = 0; header[16] = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment