changeset 15997:d565dc2ce82e

-delay for MEncoder, final step 6. TODO: make it encode silence instead of cutting video as cutting video is unreliable with -ovc copy.
author ods15
date Sun, 17 Jul 2005 19:40:05 +0000
parents 43971e7da5f0
children 2df1b4fc0c52
files DOCS/man/en/mplayer.1 cfg-common.h cfg-mplayer.h mencoder.c
diffstat 4 files changed, 48 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/DOCS/man/en/mplayer.1	Sun Jul 17 19:28:01 2005 +0000
+++ b/DOCS/man/en/mplayer.1	Sun Jul 17 19:40:05 2005 +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, this is not guaranteed 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.
--- a/cfg-common.h	Sun Jul 17 19:28:01 2005 +0000
+++ b/cfg-common.h	Sun Jul 17 19:40:05 2005 +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
--- a/cfg-mplayer.h	Sun Jul 17 19:28:01 2005 +0000
+++ b/cfg-mplayer.h	Sun Jul 17 19:40:05 2005 +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},
--- a/mencoder.c	Sun Jul 17 19:28:01 2005 +0000
+++ b/mencoder.c	Sun Jul 17 19:40:05 2005 +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.