changeset 18242:caac2ca98168

4 - Implement a better way to calculate current audio pts and use it for audio decoded with ad_libvorbis, ad_ffmpeg and ad_faad. Patch by Uoti Urpala
author rtognimp
date Mon, 24 Apr 2006 10:58:40 +0000
parents b19dada1aeeb
children 8cb434bc37e4
files libmpcodecs/ad_faad.c libmpcodecs/ad_ffmpeg.c libmpcodecs/ad_libvorbis.c libmpdemux/demuxer.c libmpdemux/demuxer.h libmpdemux/stheader.h mplayer.c
diffstat 7 files changed, 55 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/libmpcodecs/ad_faad.c	Mon Apr 24 10:36:29 2006 +0000
+++ b/libmpcodecs/ad_faad.c	Mon Apr 24 10:58:40 2006 +0000
@@ -253,8 +253,13 @@
   } else {
    // packetized (.mp4) aac stream:
     unsigned char* bufptr=NULL;
-    int buflen=ds_get_packet(sh->ds, &bufptr);
+    double pts;
+    int buflen=ds_get_packet_pts(sh->ds, &bufptr, &pts);
     if(buflen<=0) break;
+    if (pts != MP_NOPTS_VALUE) {
+	sh->pts = pts;
+	sh->pts_bytes = 0;
+    }
     faac_sample_buffer = faacDecDecode(faac_hdec, &faac_finfo, bufptr, buflen);
   }
   //for (j=0;j<faac_finfo.channels;j++) printf("%d:%d\n", j, faac_finfo.channel_position[j]);
@@ -271,6 +276,7 @@
       memcpy(buf+len,faac_sample_buffer, sh->samplesize*faac_finfo.samples);
       last_dec_len = sh->samplesize*faac_finfo.samples;
       len += last_dec_len;
+      sh->pts_bytes += last_dec_len;
     //printf("FAAD: buffer: %d bytes  consumed: %d \n", k, faac_finfo.bytesconsumed);
     }
   }
--- a/libmpcodecs/ad_ffmpeg.c	Mon Apr 24 10:36:29 2006 +0000
+++ b/libmpcodecs/ad_ffmpeg.c	Mon Apr 24 10:58:40 2006 +0000
@@ -149,8 +149,13 @@
     int y,len=-1;
     while(len<minlen){
 	int len2=0;
-	int x=ds_get_packet(sh_audio->ds,&start);
+	double pts;
+	int x=ds_get_packet_pts(sh_audio->ds,&start, &pts);
 	if(x<=0) break; // error
+	if (pts != MP_NOPTS_VALUE) {
+	    sh_audio->pts = pts;
+	    sh_audio->pts_bytes = 0;
+	}
 	y=avcodec_decode_audio(sh_audio->context,(int16_t*)buf,&len2,start,x);
 //printf("return:%d samples_out:%d bitstream_in:%d sample_sum:%d\n", y, len2, x, len); fflush(stdout);
 	if(y<0){ mp_msg(MSGT_DECAUDIO,MSGL_V,"lavc_audio: error\n");break; }
@@ -159,6 +164,7 @@
 	  //len=len2;break;
 	  if(len<0) len=len2; else len+=len2;
 	  buf+=len2;
+	  sh_audio->pts_bytes += len2;
 	}
         mp_dbg(MSGT_DECAUDIO,MSGL_DBG2,"Decoded %d -> %d  \n",y,len2);
     }
--- a/libmpcodecs/ad_libvorbis.c	Mon Apr 24 10:36:29 2006 +0000
+++ b/libmpcodecs/ad_libvorbis.c	Mon Apr 24 10:58:40 2006 +0000
@@ -229,9 +229,14 @@
 	while(len < minlen) {
 	  while((samples=vorbis_synthesis_pcmout(&ov->vd,&pcm))<=0){
 	    ogg_packet op;
+	    double pts;
 	    memset(&op,0,sizeof(op)); //op.b_o_s = op.e_o_s = 0;
-	    op.bytes = ds_get_packet(sh->ds,&op.packet);
+	    op.bytes = ds_get_packet_pts(sh->ds,&op.packet, &pts);
 	    if(op.bytes<=0) break;
+	    if (pts != MP_NOPTS_VALUE) {
+		sh->pts = pts;
+		sh->pts_bytes = 0;
+	    }
 	    if(vorbis_synthesis(&ov->vb,&op)==0) /* test for success! */
 	      vorbis_synthesis_blockin(&ov->vd,&ov->vb);
 	  }
@@ -303,6 +308,7 @@
 	    if(clipflag)
 	      mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"Clipping in frame %ld\n",(long)(ov->vd.sequence));
 	    len+=2*ov->vi.channels*bout;
+	    sh->pts_bytes += 2*ov->vi.channels*bout;
 	    mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"\n[decoded: %d / %d ]\n",bout,samples);
 	    samples-=bout;
 	    vorbis_synthesis_read(&ov->vd,bout); /* tell libvorbis how
--- a/libmpdemux/demuxer.c	Mon Apr 24 10:36:29 2006 +0000
+++ b/libmpdemux/demuxer.c	Mon Apr 24 10:58:40 2006 +0000
@@ -224,6 +224,7 @@
         sh->samplesize=2;
         sh->sample_format=AF_FORMAT_S16_NE;
         sh->audio_out_minsize=8192;/* default size, maybe not enough for Win32/ACM*/
+        sh->pts=MP_NOPTS_VALUE;
         if (!demux_aid_vid_mismatch)
           mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_ID=%d\n", id);
     }
@@ -502,6 +503,26 @@
     }
 }
 
+int ds_get_packet_pts(demux_stream_t *ds,unsigned char **start, double *pts)
+{
+    int len;
+    *pts = MP_NOPTS_VALUE;
+    if(ds->buffer_pos>=ds->buffer_size){
+	if (!ds_fill_buffer(ds)) {
+            // EOF
+            *start = NULL;
+            return -1;
+	}
+	// Should use MP_NOPTS_VALUE for "unknown pts" in the packets too
+	if (ds->current->pts)
+	    *pts = ds->current->pts;
+    }
+    len=ds->buffer_size-ds->buffer_pos;
+    *start = &ds->buffer[ds->buffer_pos];
+    ds->buffer_pos+=len;
+    return len;
+}
+
 int ds_get_packet_sub(demux_stream_t *ds,unsigned char **start){
     while(1){
         int len;
--- a/libmpdemux/demuxer.h	Mon Apr 24 10:36:29 2006 +0000
+++ b/libmpdemux/demuxer.h	Mon Apr 24 10:58:40 2006 +0000
@@ -284,6 +284,7 @@
 
 void ds_free_packs(demux_stream_t *ds);
 int ds_get_packet(demux_stream_t *ds,unsigned char **start);
+int ds_get_packet_pts(demux_stream_t *ds, unsigned char **start, double *pts);
 int ds_get_packet_sub(demux_stream_t *ds,unsigned char **start);
 float ds_get_next_pts(demux_stream_t *ds);
 
--- a/libmpdemux/stheader.h	Mon Apr 24 10:36:29 2006 +0000
+++ b/libmpdemux/stheader.h	Mon Apr 24 10:58:40 2006 +0000
@@ -47,6 +47,8 @@
   void* context; // codec-specific stuff (usually HANDLE or struct pointer)
   unsigned char* codecdata; // extra header data passed from demuxer to codec
   int codecdata_len;
+  double pts;  // last known pts value in output from decoder
+  int pts_bytes; // bytes output by decoder after last known pts
 } sh_audio_t;
 
 typedef struct {
--- a/mplayer.c	Mon Apr 24 10:36:29 2006 +0000
+++ b/mplayer.c	Mon Apr 24 10:58:40 2006 +0000
@@ -3874,6 +3874,7 @@
       delay=sh_audio->delay;
       delay+=(float)sh_audio->a_buffer_len/(float)sh_audio->o_bps;
     }
+    delay += sh_audio->a_out_buffer_len*playback_speed/(float)ao_data.bps;
 
 #if 0
     if(pts_from_bps){
@@ -3890,16 +3891,15 @@
 #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;
-#if 0
-      mp_msg(MSGT_FIXME, MSGL_FIXME, "\n#X# pts=%5.3f ds_pts=%5.3f buff=%5.3f total=%5.3f\n",
-          a_pts,
-	  ds_tell_pts(d_audio)/(float)sh_audio->i_bps,
-	  -sh_audio->a_in_buffer_len/(float)sh_audio->i_bps,
-	  a_pts+(ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps);
-#endif	  
-      a_pts+=(ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps - sh_audio->a_out_buffer_len*playback_speed/(float)ao_data.bps;
+      a_pts = sh_audio->pts;
+      if (a_pts == MP_NOPTS_VALUE) {
+	  // Decoder doesn't support tracking timestamps or demuxer doesn't
+	  // set them properly in individual packets, use old inaccurate method
+	  a_pts=d_audio->pts;
+	  a_pts+=(ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps;
+      }
+      else
+	  a_pts += sh_audio->pts_bytes / (float)sh_audio->o_bps;
     }
     v_pts=sh_video ? sh_video->pts : d_video->pts;