[MPlayer-dev-eng] [PATCH] -delay for MEncoder

Oded Shimon ods15 at ods15.dyndns.org
Fri Jul 8 21:52:58 CEST 2005


Finally finished -delay for MEncoder.. It works by simply dumping the audio 
or video in the begginning of the file and after every EDL seek...

I seperated the patch to 6 "steps" to increase readability.. only 
step6.patch actually does the -delay, the rest "prepare" mencoder.c for 
it... Each step should still compile and work the same.

Since this is a big patch, I'm giving 1 week for anyone to object/comment.

Oh, also, due to video keyframes, using -ovc copy and a negative -delay is 
not garunteed to work well..

- ods15
-------------- next part --------------
Index: cfg-mencoder.h
===================================================================
RCS file: /cvsroot/mplayer/main/cfg-mencoder.h,v
retrieving revision 1.101
diff -d -u -r1.101 cfg-mencoder.h
--- cfg-mencoder.h	2 Jul 2005 19:00:12 -0000	1.101
+++ cfg-mencoder.h	8 Jul 2005 18:05:14 -0000
@@ -220,7 +220,7 @@
 
 	{"audio-density", &audio_density, CONF_TYPE_INT, CONF_RANGE|CONF_GLOBAL, 1, 50, NULL},
 	{"audio-preload", &audio_preload, CONF_TYPE_FLOAT, CONF_RANGE|CONF_GLOBAL, 0, 2, NULL},
-	{"audio-delay",   &audio_delay, CONF_TYPE_FLOAT, CONF_MIN|CONF_GLOBAL, 0, 0, NULL},
+	{"audio-delay",   &audio_delay_fix, CONF_TYPE_FLOAT, CONF_MIN|CONF_GLOBAL, 0, 0, NULL},
 
 	{"x", "-x is obsolete, use -vf scale=w:h for scaling.\n", CONF_TYPE_PRINT, CONF_NOCFG, 0, 0, NULL},
 	{"xsize", "-xsize is obsolete, use -vf crop=w:h:x:y for cropping.\n", CONF_TYPE_PRINT, CONF_NOCFG, 0, 0, NULL},
Index: mencoder.c
===================================================================
RCS file: /cvsroot/mplayer/main/mencoder.c,v
retrieving revision 1.292
diff -d -u -r1.292 mencoder.c
--- mencoder.c	3 Jul 2005 10:09:09 -0000	1.292
+++ mencoder.c	8 Jul 2005 18:05:15 -0000
@@ -146,7 +146,7 @@
 static float c_total=0;
 
 static float audio_preload=0.5;
-static float audio_delay=0.0;
+static float audio_delay_fix=0.0;
 static int audio_density=2;
 
 float force_fps=0;
@@ -898,8 +914,8 @@
 
 if (verbose>1) print_wave_header(mux_a->wf);
 
-if(audio_delay!=0.0){
-    mux_a->h.dwStart=audio_delay*mux_a->h.dwRate/mux_a->h.dwScale;
+if(audio_delay_fix!=0.0){
+    mux_a->h.dwStart=audio_delay_fix*mux_a->h.dwRate/mux_a->h.dwScale;
     mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_SettingAudioDelay,mux_a->h.dwStart*mux_a->h.dwScale/(float)mux_a->h.dwRate);
 }
 if(muxer->fix_stream_parameters)
-------------- next part --------------
--- mencoder.c	2005-07-08 21:48:33.000000000 +0300
+++ mencoder.c	2005-07-08 21:46:53.000000000 +0300
@@ -233,6 +233,13 @@
 static char * end_at_string=0;
 //static uint8_t* flip_upside_down(uint8_t* dst, const uint8_t* src, int width, int height);
 
+typedef struct {
+    unsigned char* start;
+    int in_size;
+    float frame_time;
+    int already_read;
+} s_frame_data;
+
 #ifdef USE_EDL
 #include "edl.h"
 static edl_record_ptr edl_records = NULL; ///< EDL entries memory area
@@ -240,11 +247,10 @@
 static short edl_muted; ///< Stores whether EDL is currently in muted mode.
 static short edl_seeking; ///< When non-zero, stream is seekable.
 static short edl_seek_type; ///< When non-zero, frames are discarded instead of seeking.
-static int edl_skip; ///< -1 OR the value of in_size of an already read frame.
 /** \brief Seeks for EDL
     \return 1 for success, 0 for failure, 2 for EOF.
 */
-int edl_seek(edl_record_ptr next_edl_record, demuxer_t* demuxer, demux_stream_t *d_audio, muxer_stream_t* mux_a, float * frame_time, unsigned char ** start, int framecopy);
+static int edl_seek(edl_record_ptr next_edl_record, demuxer_t* demuxer, demux_stream_t *d_audio, muxer_stream_t* mux_a, s_frame_data * frame_data, int framecopy);
 #endif
 
 #include "cfg-mplayer-def.h"
@@ -342,6 +348,7 @@
 int file_format=DEMUXER_TYPE_UNKNOWN;
 int i=DEMUXER_TYPE_UNKNOWN;
 void *vobsub_writer=NULL;
+s_frame_data frame_data = { .start = NULL, .in_size = 0, .frame_time = 0., .already_read = 0 };
 
 uint32_t ptimer_start;
 uint32_t audiorate=0;
@@ -1023,7 +1030,6 @@
 next_edl_record = edl_records = NULL;
 edl_muted = 0;
 edl_seeking = 1;
-edl_skip = -1;
 if (edl_filename) {
     next_edl_record = edl_records = edl_parse_file();
 }
@@ -1031,12 +1037,9 @@
 
 while(!at_eof){
 
-    float frame_time=0;
     int blit_frame=0;
     float a_pts=0;
     float v_pts=0;
-    unsigned char* start=NULL;
-    int in_size;
     int skip_flag=0; // 1=skip  -1=duplicate
 
     if((end_at_type == END_AT_SIZE && end_at <= ftello(muxer_f))  ||
@@ -1057,7 +1060,7 @@
             mp_msg(MSGT_CPLAYER, MSGL_DBG4, "EDL_SKIP: start [%f], stop [%f], length [%f]\n",
                    next_edl_record->start_sec, next_edl_record->stop_sec, next_edl_record->length_sec);
 
-            result = edl_seek(next_edl_record, demuxer, d_audio, mux_a, &frame_time, &start, mux_v->codec==VCODEC_COPY);
+            result = edl_seek(next_edl_record, demuxer, d_audio, mux_a, &frame_data, mux_v->codec==VCODEC_COPY);
 
             if (result == 2) { at_eof=1; break; } // EOF
             else if (result == 0) edl_seeking = 0; // no seeking
@@ -1190,16 +1193,15 @@
 
     // get video frame!
 
-#ifdef USE_EDL
-    if (edl_skip != -1) { in_size = edl_skip; edl_skip = -1; }
-    else
-#endif
-    in_size=video_read_frame(sh_video,&frame_time,&start,force_fps);
-    if(in_size<0){ at_eof=1; break; }
-    sh_video->timer+=frame_time; ++decoded_frameno;
-    frame_time /= playback_speed;
+    if (!frame_data.already_read) {
+        frame_data.in_size=video_read_frame(sh_video,&frame_data.frame_time,&frame_data.start,force_fps);
+        sh_video->timer+=frame_data.frame_time;
+    }
+    frame_data.frame_time /= playback_speed;
+    if(frame_data.in_size<0){ at_eof=1; break; }
+    ++decoded_frameno;
 
-    v_timer_corr-=frame_time-(float)mux_v->h.dwScale/mux_v->h.dwRate;
+    v_timer_corr-=frame_data.frame_time-(float)mux_v->h.dwScale/mux_v->h.dwRate;
 
 if(demuxer2){	// 3-pass encoding, read control file (frameno.avi)
     // find our frame:
@@ -1258,8 +1260,8 @@
 
 switch(mux_v->codec){
 case VCODEC_COPY:
-    mux_v->buffer=start;
-    if(skip_flag<=0) muxer_write_chunk(mux_v,in_size,(sh_video->ds->flags&1)?0x10:0);
+    mux_v->buffer=frame_data.start;
+    if(skip_flag<=0) muxer_write_chunk(mux_v,frame_data.in_size,(sh_video->ds->flags&1)?0x10:0);
     break;
 case VCODEC_FRAMENO:
     mux_v->buffer=(unsigned char *)&decoded_frameno; // tricky
@@ -1267,7 +1269,7 @@
     break;
 default:
     // decode_video will callback down to ve_*.c encoders, through the video filters
-    blit_frame=decode_video(sh_video,start,in_size,
+    blit_frame=decode_video(sh_video,frame_data.start,frame_data.in_size,
       skip_flag>0 && (!sh_video->vfilter || ((vf_instance_t *)sh_video->vfilter)->control(sh_video->vfilter, VFCTRL_SKIP_NEXT_FRAME, 0) != CONTROL_TRUE));
     
     if (sh_video->vf_inited < 0) mencoder_exit(1, NULL);
@@ -1441,6 +1443,8 @@
  }
 #endif
 
+ frame_data = (s_frame_data){ .start = NULL, .in_size = 0, .frame_time = 0., .already_read = 0 };
+
  if(ferror(muxer_f)) {
      mp_msg(MSGT_MENCODER,MSGL_FATAL,MSGTR_ErrorWritingFile, out_filename);
      mencoder_exit(1, NULL);
@@ -1604,7 +1608,7 @@
 }
 
 #ifdef USE_EDL
-int edl_seek(edl_record_ptr next_edl_record, demuxer_t* demuxer, demux_stream_t *d_audio, muxer_stream_t* mux_a, float * frame_time, unsigned char ** start, int framecopy) {
+static int edl_seek(edl_record_ptr next_edl_record, demuxer_t* demuxer, demux_stream_t *d_audio, muxer_stream_t* mux_a, s_frame_data * frame_data, int framecopy) {
     sh_audio_t * sh_audio = d_audio->sh;
     sh_video_t * sh_video = demuxer->video ? demuxer->video->sh : NULL;
     vf_instance_t * vfilter = sh_video ? sh_video->vfilter : NULL;
@@ -1634,18 +1638,17 @@
 
     while (!interrupted) {
         float a_pts = 0.;
-        int in_size;
 
-        in_size = video_read_frame(sh_video, frame_time, start, force_fps);
-        if(in_size<0) return 2;
-        sh_video->timer += *frame_time;
+        frame_data->in_size = video_read_frame(sh_video, &frame_data->frame_time, &frame_data->start, force_fps);
+        if(frame_data->in_size<0) return 2;
+        sh_video->timer += frame_data->frame_time;
 
         if (sh_audio) {
             a_pts = d_audio->pts + (ds_tell_pts(d_audio) - sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps;
-            while (sh_video->pts - *frame_time > a_pts) {
+            while (sh_video->pts - frame_data->frame_time > a_pts) {
                 int len;
                 if (samplesize) {
-                    len = avg * (sh_video->pts - a_pts - *frame_time);
+                    len = avg * (sh_video->pts - frame_data->frame_time - a_pts);
                     len/= samplesize; if(len<1) len=1;
                     len*= samplesize;
                     len = demux_read_data(sh_audio->ds,mux_a->buffer,len);
@@ -1659,14 +1662,14 @@
         }
 
         if (done) {
-            edl_skip = in_size;
+            frame_data->already_read = 1;
             if (!framecopy || (sh_video->ds->flags & 1)) return 1;
         }
         if (sh_video->pts >= next_edl_record->stop_sec) done = 1;
 
         if (vfilter) {
             int softskip = (vfilter->control(vfilter, VFCTRL_SKIP_NEXT_FRAME, 0) == CONTROL_TRUE);
-            decode_video(sh_video, *start, in_size, !softskip);
+            decode_video(sh_video, frame_data->start, frame_data->in_size, !softskip);
         }
 
         mp_msg(MSGT_MENCODER, MSGL_STATUS,
-------------- next part --------------
--- mencoder.c	2005-07-08 21:46:53.000000000 +0300
+++ mencoder.c	2005-07-08 22:07:24.000000000 +0300
@@ -240,6 +240,9 @@
     int already_read;
 } s_frame_data;
 
+/// Returns a_pts
+static float calc_a_pts(demux_stream_t *d_audio);
+
 #ifdef USE_EDL
 #include "edl.h"
 static edl_record_ptr edl_records = NULL; ///< EDL entries memory area
@@ -1607,6 +1610,14 @@
 	return timeleft;
 }
 
+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;
+}
+
 #ifdef USE_EDL
 static int edl_seek(edl_record_ptr next_edl_record, demuxer_t* demuxer, demux_stream_t *d_audio, muxer_stream_t* mux_a, s_frame_data * frame_data, int framecopy) {
     sh_audio_t * sh_audio = d_audio->sh;
@@ -1644,7 +1655,7 @@
         sh_video->timer += frame_data->frame_time;
 
         if (sh_audio) {
-            a_pts = d_audio->pts + (ds_tell_pts(d_audio) - sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps;
+            a_pts = calc_a_pts(d_audio);
             while (sh_video->pts - frame_data->frame_time > a_pts) {
                 int len;
                 if (samplesize) {
@@ -1657,7 +1668,7 @@
                     len = ds_get_packet(sh_audio->ds, &crap);
                 }
                 if (len <= 0) break; // EOF of audio.
-                a_pts = d_audio->pts + (ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps;
+                a_pts = calc_a_pts(d_audio);
             }
         }
 
-------------- next part --------------
--- mencoder.c	2005-07-08 22:07:24.000000000 +0300
+++ mencoder.c	2005-07-08 22:07:39.000000000 +0300
@@ -242,6 +242,10 @@
 
 /// Returns a_pts
 static float calc_a_pts(demux_stream_t *d_audio);
+/** \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);
 
 #ifdef USE_EDL
 #include "edl.h"
@@ -1618,13 +1622,39 @@
     return a_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);
+
+    if (!sh_audio) return a_pts;
+
+    if (sh_audio->audio.dwScale) samplesize = sh_audio->audio.dwSampleSize;
+    else samplesize = (sh_audio->wf ? sh_audio->wf->nBlockAlign : 1);
+    avg = (sh_audio->wf ? sh_audio->wf->nAvgBytesPerSec : sh_audio->i_bps);
+
+    while (pts > a_pts) {
+        int len;
+        if (samplesize) {
+            len = avg * (pts - a_pts > 0.5 ? 0.5 : pts - a_pts);
+            len/= samplesize; if(len<1) len=1;
+            len*= samplesize;
+            len = demux_read_data(sh_audio->ds,mux_a->buffer,len);
+        } else {
+            unsigned char * crap;
+            len = ds_get_packet(sh_audio->ds, &crap);
+        }
+        if (len <= 0) break; // EOF of audio.
+        a_pts = calc_a_pts(d_audio);
+    }
+    return a_pts;
+}
+
 #ifdef USE_EDL
 static int edl_seek(edl_record_ptr next_edl_record, demuxer_t* demuxer, demux_stream_t *d_audio, muxer_stream_t* mux_a, s_frame_data * frame_data, int framecopy) {
-    sh_audio_t * sh_audio = d_audio->sh;
     sh_video_t * sh_video = demuxer->video ? demuxer->video->sh : NULL;
     vf_instance_t * vfilter = sh_video ? sh_video->vfilter : NULL;
     int done = 0;
-    int samplesize, avg;
 
     if (!sh_video) return 0;
     if (sh_video->pts >= next_edl_record->stop_sec) return 1; // nothing to do...
@@ -1643,10 +1673,6 @@
 
     // slow seek, read every frame.
 
-    if (sh_audio->audio.dwScale) samplesize = sh_audio->audio.dwSampleSize;
-    else samplesize = (sh_audio->wf ? sh_audio->wf->nBlockAlign : 1);
-    avg = (sh_audio->wf ? sh_audio->wf->nAvgBytesPerSec : sh_audio->i_bps);
-
     while (!interrupted) {
         float a_pts = 0.;
 
@@ -1654,23 +1680,7 @@
         if(frame_data->in_size<0) return 2;
         sh_video->timer += frame_data->frame_time;
 
-        if (sh_audio) {
-            a_pts = calc_a_pts(d_audio);
-            while (sh_video->pts - frame_data->frame_time > a_pts) {
-                int len;
-                if (samplesize) {
-                    len = avg * (sh_video->pts - frame_data->frame_time - a_pts);
-                    len/= samplesize; if(len<1) len=1;
-                    len*= samplesize;
-                    len = demux_read_data(sh_audio->ds,mux_a->buffer,len);
-                } else {
-                    unsigned char * crap;
-                    len = ds_get_packet(sh_audio->ds, &crap);
-                }
-                if (len <= 0) break; // EOF of audio.
-                a_pts = calc_a_pts(d_audio);
-            }
-        }
+        a_pts = forward_audio(sh_video->pts - frame_data->frame_time, d_audio, mux_a);
 
         if (done) {
             frame_data->already_read = 1;
-------------- next part --------------
--- mencoder.c	2005-07-08 22:07:39.000000000 +0300
+++ mencoder.c	2005-07-08 22:07:49.000000000 +0300
@@ -246,6 +246,10 @@
     \return The current audio pts.
 */
 static float forward_audio(float pts, demux_stream_t *d_audio, muxer_stream_t* mux_a);
+/** \brief Seeks slowly by dumping frames.
+    \return 1 for success, 2 for EOF.
+*/
+static int slowseek(float end_pts, demux_stream_t *d_video, demux_stream_t *d_audio, muxer_stream_t* mux_a, s_frame_data * frame_data, int framecopy, int print_info);
 
 #ifdef USE_EDL
 #include "edl.h"
@@ -1650,29 +1654,11 @@
     return a_pts;
 }
 
-#ifdef USE_EDL
-static int edl_seek(edl_record_ptr next_edl_record, demuxer_t* demuxer, demux_stream_t *d_audio, muxer_stream_t* mux_a, s_frame_data * frame_data, int framecopy) {
-    sh_video_t * sh_video = demuxer->video ? demuxer->video->sh : NULL;
+static int slowseek(float end_pts, demux_stream_t *d_video, demux_stream_t *d_audio, muxer_stream_t* mux_a, s_frame_data * frame_data, int framecopy, int print_info) {
+    sh_video_t * sh_video = d_video->sh;
     vf_instance_t * vfilter = sh_video ? sh_video->vfilter : NULL;
     int done = 0;
 
-    if (!sh_video) return 0;
-    if (sh_video->pts >= next_edl_record->stop_sec) return 1; // nothing to do...
-
-    if (!edl_seek_type) {
-        if(demux_seek(demuxer, next_edl_record->stop_sec - sh_video->pts, 0)){
-            sh_video->pts = demuxer->video->pts;
-            //if (vo_vobsub) vobsub_seek(vo_vobsub,sh_video->pts);
-            resync_video_stream(sh_video);
-            //if(vo_spudec) spudec_reset(vo_spudec);
-            return 1;
-        }
-        // non-seekable stream.
-        return 0;
-    }
-
-    // slow seek, read every frame.
-
     while (!interrupted) {
         float a_pts = 0.;
 
@@ -1686,14 +1672,14 @@
             frame_data->already_read = 1;
             if (!framecopy || (sh_video->ds->flags & 1)) return 1;
         }
-        if (sh_video->pts >= next_edl_record->stop_sec) done = 1;
+        if (sh_video->pts >= end_pts) done = 1;
 
         if (vfilter) {
             int softskip = (vfilter->control(vfilter, VFCTRL_SKIP_NEXT_FRAME, 0) == CONTROL_TRUE);
             decode_video(sh_video, frame_data->start, frame_data->in_size, !softskip);
         }
 
-        mp_msg(MSGT_MENCODER, MSGL_STATUS,
+        if (print_info) mp_msg(MSGT_MENCODER, MSGL_STATUS,
                "EDL SKIP: Start: %.2f  End: %.2lf   Current: V: %.2f  A: %.2f     \r",
                next_edl_record->start_sec, next_edl_record->stop_sec,
                sh_video->pts, a_pts);
@@ -1701,4 +1687,28 @@
     if (interrupted) return 2;
     return 1;
 }
+
+#ifdef USE_EDL
+static int edl_seek(edl_record_ptr next_edl_record, demuxer_t* demuxer, demux_stream_t *d_audio, muxer_stream_t* mux_a, s_frame_data * frame_data, int framecopy) {
+    sh_video_t * sh_video = demuxer->video ? demuxer->video->sh : NULL;
+
+    if (!sh_video) return 0;
+    if (sh_video->pts >= next_edl_record->stop_sec) return 1; // nothing to do...
+
+    if (!edl_seek_type) {
+        if(demux_seek(demuxer, next_edl_record->stop_sec - sh_video->pts, 0)){
+            sh_video->pts = demuxer->video->pts;
+            //if (vo_vobsub) vobsub_seek(vo_vobsub,sh_video->pts);
+            resync_video_stream(sh_video);
+            //if(vo_spudec) spudec_reset(vo_spudec);
+            return 1;
+        }
+        // non-seekable stream.
+        return 0;
+    }
+
+    // slow seek, read every frame.
+
+    return slowseek(next_edl_record->stop_sec, demuxer->video, d_audio, mux_a, frame_data, framecopy, 1);
+}
 #endif
-------------- next part --------------
Index: cfg-mplayer.h
===================================================================
RCS file: /cvsroot/mplayer/main/cfg-mplayer.h,v
retrieving revision 1.249
diff -d -u -r1.249 cfg-mplayer.h
--- cfg-mplayer.h	18 Jun 2005 20:27:50 -0000	1.249
+++ cfg-mplayer.h	8 Jul 2005 18:00:05 -0000
@@ -318,9 +318,6 @@
 
 	{"sstep", &step_sec, CONF_TYPE_INT, CONF_MIN, 0, 0, NULL},
 
-	// set a-v distance, should be moved to -common and supported in MEncoder
-	{"delay", &audio_delay, CONF_TYPE_FLOAT, CONF_RANGE, -100.0, 100.0, NULL},
-
 	{"framedrop", &frame_dropping, CONF_TYPE_FLAG, 0, 0, 1, NULL},
 	{"hardframedrop", &frame_dropping, CONF_TYPE_FLAG, 0, 0, 2, NULL},
 	{"noframedrop", &frame_dropping, CONF_TYPE_FLAG, 0, 1, 0, NULL},
Index: cfg-common.h
===================================================================
RCS file: /cvsroot/mplayer/main/cfg-common.h,v
retrieving revision 1.145
diff -d -u -r1.145 cfg-common.h
--- cfg-common.h	13 May 2005 14:45:28 -0000	1.145
+++ cfg-common.h	8 Jul 2005 18:00:05 -0000
@@ -146,6 +146,9 @@
 	{"format", &audio_output_format, CONF_TYPE_AFMT, 0, 0, 0, NULL},
 	{"speed", &playback_speed, CONF_TYPE_FLOAT, CONF_RANGE, 0.01, 100.0, NULL},
 
+	// set a-v distance
+	{"delay", &audio_delay, CONF_TYPE_FLOAT, CONF_RANGE, -100.0, 100.0, NULL},
+
 #ifdef USE_LIBA52
         {"a52drc", &a52_drc_level, CONF_TYPE_FLOAT, CONF_RANGE, 0, 1, NULL},
 #endif
Index: mencoder.c
===================================================================
RCS file: /cvsroot/mplayer/main/mencoder.c,v
retrieving revision 1.292
diff -d -u -r1.292 mencoder.c
--- mencoder.c	3 Jul 2005 10:09:09 -0000	1.292
+++ mencoder.c	8 Jul 2005 18:00:06 -0000
@@ -147,6 +147,7 @@
 
 static float audio_preload=0.5;
 static float audio_delay_fix=0.0;
+static float audio_delay=0.0;
 static int audio_density=2;
 
 float force_fps=0;
@@ -250,6 +251,8 @@
     \return 1 for success, 2 for EOF.
 */
 static int slowseek(float end_pts, demux_stream_t *d_video, demux_stream_t *d_audio, muxer_stream_t* mux_a, s_frame_data * frame_data, int framecopy, int print_info);
+/// Deletes audio or video as told by -delay to sync
+static void fixdelay(demux_stream_t *d_video, demux_stream_t *d_audio, muxer_stream_t* mux_a, s_frame_data * frame_data, int framecopy);
 
 #ifdef USE_EDL
 #include "edl.h"
@@ -1046,6 +1049,8 @@
 }
 #endif
 
+if (sh_audio && audio_delay != 0.) fixdelay(d_video, d_audio, mux_a, &frame_data, mux_v->codec==VCODEC_COPY);
+
 while(!at_eof){
 
     int blit_frame=0;
@@ -1346,6 +1351,7 @@
     v_pts=sh_video ? sh_video->pts : d_video->pts;
     // av = compensated (with out buffering delay) A-V diff
     AV_delay=(a_pts-v_pts);
+    AV_delay-=audio_delay;
     AV_delay /= playback_speed;
     AV_delay-=mux_a->timer-(mux_v->timer-(v_timer_corr+v_pts_corr));
 	// compensate input video timer by av:
@@ -1637,6 +1643,13 @@
     else samplesize = (sh_audio->wf ? sh_audio->wf->nBlockAlign : 1);
     avg = (sh_audio->wf ? sh_audio->wf->nAvgBytesPerSec : sh_audio->i_bps);
 
+    // after a demux_seek, a_pts will be zero until you read some audio.
+    // 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);
+    }
+
     while (pts > a_pts) {
         int len;
         if (samplesize) {
@@ -1666,7 +1679,7 @@
         if(frame_data->in_size<0) return 2;
         sh_video->timer += frame_data->frame_time;
 
-        a_pts = forward_audio(sh_video->pts - frame_data->frame_time, d_audio, mux_a);
+        a_pts = forward_audio(sh_video->pts - frame_data->frame_time + audio_delay, d_audio, mux_a);
 
         if (done) {
             frame_data->already_read = 1;
@@ -1688,6 +1701,29 @@
     return 1;
 }
 
+static void fixdelay(demux_stream_t *d_video, demux_stream_t *d_audio, muxer_stream_t* mux_a, s_frame_data * frame_data, int framecopy) {
+    // TODO: Find a way to encode silence instead of deleting video
+    sh_video_t * sh_video = d_video->sh;
+    vf_instance_t * vfilter = sh_video ? sh_video->vfilter : NULL;
+    int done = 0;
+    float a_pts;
+
+    // demux_seek has a weirdness that sh_video->pts is meaningless,
+    // until a single frame is read... Same for audio actually too.
+    // Reading one frame, and keeping it.
+    frame_data->in_size = video_read_frame(sh_video, &frame_data->frame_time, &frame_data->start, force_fps);
+    if(frame_data->in_size<0) return;
+    sh_video->timer += frame_data->frame_time;
+    frame_data->already_read = 1;
+
+    a_pts = forward_audio(sh_video->pts - frame_data->frame_time + audio_delay, d_audio, mux_a);
+
+    if (audio_delay > 0) return;
+    else if (sh_video->pts - frame_data->frame_time + audio_delay >= a_pts) return;
+
+    slowseek(a_pts - audio_delay, d_video, d_audio, mux_a, frame_data, framecopy, 0);
+}
+
 #ifdef USE_EDL
 static int edl_seek(edl_record_ptr next_edl_record, demuxer_t* demuxer, demux_stream_t *d_audio, muxer_stream_t* mux_a, s_frame_data * frame_data, int framecopy) {
     sh_video_t * sh_video = demuxer->video ? demuxer->video->sh : NULL;
@@ -1701,6 +1737,7 @@
             //if (vo_vobsub) vobsub_seek(vo_vobsub,sh_video->pts);
             resync_video_stream(sh_video);
             //if(vo_spudec) spudec_reset(vo_spudec);
+            if (audio_delay != 0.0) fixdelay(demuxer->video, d_audio, mux_a, frame_data, framecopy);
             return 1;
         }
         // non-seekable stream.
-------------- next part --------------
Index: DOCS/man/en/mplayer.1
===================================================================
RCS file: /cvsroot/mplayer/main/DOCS/man/en/mplayer.1,v
retrieving revision 1.1028
diff -u -r1.1028 mplayer.1
--- DOCS/man/en/mplayer.1	7 Jul 2005 20:26:56 -0000	1.1028
+++ DOCS/man/en/mplayer.1	8 Jul 2005 19:52:03 -0000
@@ -910,6 +910,13 @@
 The file is assumed to be in Netscape format.
 .
 .TP
+.B \-delay <sec>
+Audio delay in seconds (positive or negative float value).
+.I NOTE:
+When used with MEncoder, not garunteed to work correctly with
+\-ovc copy.
+.
+.TP
 .B \-demuxer <number>
 Force demuxer type.
 Give the demuxer ID as defined in libmpdemux/\:demuxer.h.
@@ -1747,10 +1754,6 @@
 Override audio driver/\:card buffer size detection.
 .
 .TP
-.B \-delay <sec>
-Audio delay in seconds (positive or negative float value).
-.
-.TP
 .B \-format <format> (also see the format audio filter)
 Select the sample format used for output from the audio filter
 layer to the sound card.


More information about the MPlayer-dev-eng mailing list