ref: 88c756eef2c0578cc10709eaec176f4bd32cd43c
parent: 0667f41555d0762721bdf78e96555dc69c9f0055
author: Mark Harris <mark.hsj@gmail.com>
date: Wed Sep 30 21:49:28 EDT 2015
opusenc: Limit end trimming to one frame Avoid writing a final packet larger than 20ms that is larger than necessary, with 20ms or more that is beyond the end of the stream.
--- a/src/opusenc.c
+++ b/src/opusenc.c
@@ -312,7 +312,6 @@
ogg_int64_t original_samples=0;
ogg_int32_t id=-1;
int last_segments=0;
- int eos=0;
OpusHeader header;
char ENCODER_string[1024];
/*Counters*/
@@ -903,7 +902,6 @@
}
/*Main encoding loop (one frame per iteration)*/
- eos=0;
nb_samples=-1;
while(!op.e_o_s){
int size_segments,cur_frame_size;
@@ -912,10 +910,7 @@
if(nb_samples<0){
nb_samples = inopt.read_samples(inopt.readdata,input,frame_size);
total_samples+=nb_samples;
- if(nb_samples<frame_size)op.e_o_s=1;
- else op.e_o_s=0;
}
- op.e_o_s|=eos;
if(start_time==0){
start_time = time(NULL);
@@ -923,8 +918,14 @@
cur_frame_size=frame_size;
- /*No fancy end padding, just fill with zeros for now.*/
- if(nb_samples<cur_frame_size)for(i=nb_samples*chan;i<cur_frame_size*chan;i++)input[i]=0;
+ if(nb_samples<cur_frame_size){
+ op.e_o_s=1;
+ /*Avoid making the final packet 20ms or more longer than needed.*/
+ cur_frame_size-=((cur_frame_size-(nb_samples>0?nb_samples:1))
+ /(coding_rate/50))*(coding_rate/50);
+ /*No fancy end padding, just fill with zeros for now.*/
+ for(i=nb_samples*chan;i<cur_frame_size*chan;i++)input[i]=0;
+ }
/*Encode current frame*/
VG_UNDEF(packet,max_frame_bytes);
@@ -982,7 +983,6 @@
if((!op.e_o_s)&&max_ogg_delay>5760){
nb_samples = inopt.read_samples(inopt.readdata,input,frame_size);
total_samples+=nb_samples;
- if(nb_samples<frame_size)eos=1;
if(nb_samples==0)op.e_o_s=1;
} else nb_samples=-1;
@@ -991,9 +991,10 @@
op.b_o_s=0;
op.granulepos=enc_granulepos;
if(op.e_o_s){
- /*We compute the final GP as ceil(len*48k/input_rate). When a resampling
- decoder does the matching floor(len*input/48k) conversion the length will
- be exactly the same as the input.*/
+ /*We compute the final GP as ceil(len*48k/input_rate)+preskip. When a
+ resampling decoder does the matching floor((len-preskip)*input_rate/48k)
+ conversion, the resulting output length will exactly equal the original
+ input length when 0<input_rate<=48000.*/
op.granulepos=((original_samples*48000+rate-1)/rate)+header.preskip;
}
op.packetno=2+id;