# HG changeset patch # User reimar # Date 1298398936 0 # Node ID 674117ab7ce738f666dad958a26aae00c154af4a # Parent 702867779920801c51566968a6c81da282e48810 Move MPlayer's audio pts calculation code into mp_common.c and reuse it in mencoder. This should improve A-V sync behaviour a lot when re-encoding audio. Patch by Rudolf Polzer [divVerent alientrap org] diff -r 702867779920 -r 674117ab7ce7 mencoder.c --- a/mencoder.c Tue Feb 22 18:18:15 2011 +0000 +++ b/mencoder.c Tue Feb 22 18:22:16 2011 +0000 @@ -141,7 +141,6 @@ int benchmark=0; // A-V sync: -int delay_corrected=1; static float default_max_pts_correction=-1;//0.01f; static float max_pts_correction=0;//default_max_pts_correction; static float c_total=0; @@ -393,23 +392,13 @@ return timeleft; } -/// Returns a_pts -static float calc_a_pts(demux_stream_t *d_audio) -{ - sh_audio_t * sh_audio = d_audio ? d_audio->sh : NULL; - float a_pts = 0.; - if (sh_audio) - a_pts = d_audio->pts + (ds_tell_pts(d_audio) - sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps; - return a_pts; -} - /** \brief Seeks audio forward to pts by dumping audio packets * \return The current audio pts. */ static float forward_audio(float pts, demux_stream_t *d_audio, muxer_stream_t* mux_a) { sh_audio_t * sh_audio = d_audio ? d_audio->sh : NULL; int samplesize, avg; - float a_pts = calc_a_pts(d_audio); + float a_pts = calc_a_pts(sh_audio, d_audio); if (!sh_audio) return a_pts; @@ -421,7 +410,7 @@ // carefully checking if a_pts is truely correct by reading tiniest amount of data possible. if (pts > a_pts && a_pts == 0.0 && samplesize) { if (demux_read_data(sh_audio->ds,mux_a->buffer,samplesize) <= 0) return a_pts; // EOF - a_pts = calc_a_pts(d_audio); + a_pts = calc_a_pts(sh_audio, d_audio); } while (pts > a_pts) { @@ -436,7 +425,7 @@ len = ds_get_packet(sh_audio->ds, &crap); } if (len <= 0) break; // EOF of audio. - a_pts = calc_a_pts(d_audio); + a_pts = calc_a_pts(sh_audio, d_audio); } return a_pts; } @@ -1544,14 +1533,11 @@ ((ds_tell(d_audio)-sh_audio->a_in_buffer_len)/sh_audio->audio.dwSampleSize) : (d_audio->block_no); // <- used for VBR audio a_pts=samples*(float)sh_audio->audio.dwScale/(float)sh_audio->audio.dwRate; - delay_corrected=1; } else #endif { // PTS = (last timestamp) + (bytes after last timestamp)/(bytes per sec) - a_pts=d_audio->pts; - if(!delay_corrected) if(a_pts) delay_corrected=1; - a_pts+=(ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps; + a_pts=calc_a_pts(sh_audio, d_audio); } v_pts=sh_video ? sh_video->pts : d_video->pts; // av = compensated (with out buffering delay) A-V diff diff -r 702867779920 -r 674117ab7ce7 mpcommon.c --- a/mpcommon.c Tue Feb 22 18:18:15 2011 +0000 +++ b/mpcommon.c Tue Feb 22 18:22:16 2011 +0000 @@ -462,3 +462,37 @@ #endif return 1; } + +/// Returns a_pts +double calc_a_pts(sh_audio_t *sh_audio, demux_stream_t *d_audio) +{ + if(!sh_audio || !d_audio) + return MP_NOPTS_VALUE; + // first calculate the end pts of audio that has been output by decoder + double a_pts = sh_audio->pts; + if (a_pts != MP_NOPTS_VALUE) + // Good, decoder supports new way of calculating audio pts. + // sh_audio->pts is the timestamp of the latest input packet with + // known pts that the decoder has decoded. sh_audio->pts_bytes is + // the amount of bytes the decoder has written after that timestamp. + a_pts += sh_audio->pts_bytes / (double) sh_audio->o_bps; + else { + // Decoder doesn't support new way of calculating pts (or we're + // being called before it has decoded anything with known timestamp). + // Use the old method of audio pts calculation: take the timestamp + // of last packet with known pts the decoder has read data from, + // and add amount of bytes read after the beginning of that packet + // divided by input bps. This will be inaccurate if the input/output + // ratio is not constant for every audio packet or if it is constant + // but not accurately known in sh_audio->i_bps. + + a_pts = d_audio->pts; + // ds_tell_pts returns bytes read after last timestamp from + // demuxing layer, decoder might use sh_audio->a_in_buffer for bytes + // it has read but not decoded + if (sh_audio->i_bps) + a_pts += (ds_tell_pts(d_audio) - sh_audio->a_in_buffer_len) / + (double)sh_audio->i_bps; + } + return a_pts; +} diff -r 702867779920 -r 674117ab7ce7 mplayer.c --- a/mplayer.c Tue Feb 22 18:18:15 2011 +0000 +++ b/mplayer.c Tue Feb 22 18:22:16 2011 +0000 @@ -1717,31 +1717,7 @@ { double buffered_output; // first calculate the end pts of audio that has been output by decoder - double a_pts = sh_audio->pts; - if (a_pts != MP_NOPTS_VALUE) - // Good, decoder supports new way of calculating audio pts. - // sh_audio->pts is the timestamp of the latest input packet with - // known pts that the decoder has decoded. sh_audio->pts_bytes is - // the amount of bytes the decoder has written after that timestamp. - a_pts += sh_audio->pts_bytes / (double) sh_audio->o_bps; - else { - // Decoder doesn't support new way of calculating pts (or we're - // being called before it has decoded anything with known timestamp). - // Use the old method of audio pts calculation: take the timestamp - // of last packet with known pts the decoder has read data from, - // and add amount of bytes read after the beginning of that packet - // divided by input bps. This will be inaccurate if the input/output - // ratio is not constant for every audio packet or if it is constant - // but not accurately known in sh_audio->i_bps. - - a_pts = d_audio->pts; - // ds_tell_pts returns bytes read after last timestamp from - // demuxing layer, decoder might use sh_audio->a_in_buffer for bytes - // it has read but not decoded - if (sh_audio->i_bps) - a_pts += (ds_tell_pts(d_audio) - sh_audio->a_in_buffer_len) / - (double)sh_audio->i_bps; - } + double a_pts = calc_a_pts(sh_audio, d_audio); // Now a_pts hopefully holds the pts for end of audio from decoder. // Substract data in buffers between decoder and audio out.