ref: 1f4bc1dcc6039e786c721adbfd82e7033cd667f5
parent: cfd5d0f362a24fc1e30f1aaad68cc1a043907071
author: Jean-Marc Valin <[email protected]>
date: Mon May 1 12:08:39 EDT 2017
enforcing Ogg delay constraint
--- a/src/opusenc.c
+++ b/src/opusenc.c
@@ -83,8 +83,10 @@
SpeexResamplerState *re;
int frame_size;
int decision_delay;
+ int max_ogg_delay;
ogg_int64_t curr_granule;
ogg_int64_t end_granule;
+ ogg_int64_t last_page_granule;
OpusEncCallbacks callbacks;
void *user_data;
OpusHeader header;
@@ -171,6 +173,7 @@
enc->channels = channels;
enc->frame_size = 960;
enc->decision_delay = 96000;
+ enc->max_ogg_delay = 48000;
enc->header.channels=channels;
enc->header.channel_mapping=family;
enc->header.input_sample_rate=rate;
@@ -200,6 +203,7 @@
}
enc->curr_granule = 0;
enc->end_granule = 0;
+ enc->last_page_granule = 0;
comment_init(&enc->comment, &enc->comment_length, opus_get_version_string());
{
char encoder_string[1024];
@@ -280,6 +284,7 @@
/* Round up when converting the granule pos because the decoder will round down. */
ogg_int64_t end_granule48k = (enc->end_granule*48000 + enc->rate - 1)/enc->rate + enc->header.preskip;
while (enc->buffer_end-enc->buffer_start > enc->frame_size + enc->decision_delay) {
+ int flush_needed;
ogg_packet op;
ogg_page og;
int nbBytes;
@@ -292,27 +297,29 @@
op.packet=packet;
op.bytes=nbBytes;
op.b_o_s=0;
- op.e_o_s=0;
op.packetno=enc->packetno++;
op.granulepos=enc->curr_granule;
- if (enc->curr_granule >= end_granule48k) {
- op.granulepos=end_granule48k;
- op.e_o_s=1;
- ogg_stream_packetin(&enc->os, &op);
+ op.e_o_s=enc->curr_granule >= end_granule48k;
+ if (op.e_o_s) op.granulepos=end_granule48k;
+ ogg_stream_packetin(&enc->os, &op);
+ /* FIXME: Also flush on too many segments. */
+ flush_needed = op.e_o_s || enc->curr_granule - enc->last_page_granule > enc->max_ogg_delay;
+ if (flush_needed) {
while (ogg_stream_flush_fill(&enc->os, &og, 255*255)) {
+ if (ogg_page_packets(&og) != 0) enc->last_page_granule = ogg_page_granulepos(&og);
int ret = oe_write_page(&og, &enc->callbacks, enc->user_data);
/* FIXME: what do we do if this fails? */
assert(ret != -1);
- return;
}
+ } else {
+ while (ogg_stream_pageout_fill(&enc->os, &og, 255*255)) {
+ if (ogg_page_packets(&og) != 0) enc->last_page_granule = ogg_page_granulepos(&og);
+ int ret = oe_write_page(&og, &enc->callbacks, enc->user_data);
+ /* FIXME: what do we do if this fails? */
+ assert(ret != -1);
+ }
}
- ogg_stream_packetin(&enc->os, &op);
- /* FIXME: Use flush to enforce latency constraint. */
- while (ogg_stream_pageout_fill(&enc->os, &og, 255*255)) {
- int ret = oe_write_page(&og, &enc->callbacks, enc->user_data);
- /* FIXME: what do we do if this fails? */
- assert(ret != -1);
- }
+ if (op.e_o_s) return;
enc->buffer_start += enc->frame_size;
}
/* If we've reached the end of the buffer, move everything back to the front. */