changeset 32863:674117ab7ce7

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]
author reimar
date Tue, 22 Feb 2011 18:22:16 +0000
parents 702867779920
children ccdfd500453c
files mencoder.c mpcommon.c mplayer.c
diffstat 3 files changed, 39 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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;
+}
--- 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.