Index: cfg-mencoder.h =================================================================== RCS file: /cvsroot/mplayer/main/cfg-mencoder.h,v retrieving revision 1.106 diff -u -r1.106 cfg-mencoder.h --- cfg-mencoder.h 9 Jan 2006 19:35:43 -0000 1.106 +++ cfg-mencoder.h 17 Feb 2006 02:31:59 -0000 @@ -221,7 +221,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_fix, CONF_TYPE_FLOAT, CONF_MIN|CONF_GLOBAL, 0, 0, NULL}, + {"audio-delay", &audio_delay_fix, CONF_TYPE_FLOAT, 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.337 diff -u -r1.337 mencoder.c --- mencoder.c 17 Feb 2006 01:57:40 -0000 1.337 +++ mencoder.c 17 Feb 2006 02:32:00 -0000 @@ -156,6 +156,7 @@ static float audio_preload=0.5; static float audio_delay_fix=0.0; static float audio_delay=0.0; +static int ignore_start=0; static int audio_density=2; float force_fps=0; @@ -723,6 +724,8 @@ } if(out_file_format == MUXER_TYPE_MPEG) audio_preload = 0; +muxer->audio_delay_fix = audio_delay_fix; + // ============= VIDEO =============== mux_v=muxer_new_stream(muxer,MUXER_TYPE_VIDEO); @@ -864,6 +867,10 @@ mux_v->bih->biCompression, (char *)&mux_v->bih->biCompression); } +if (! ignore_start) { + muxer->audio_delay_fix -= sh_video->stream_delay; +} + //if(demuxer->file_format!=DEMUXER_TYPE_AVI) pts_from_bps=0; // it must be 0 for mpeg/asf! // ============= AUDIO =============== @@ -942,7 +949,6 @@ mux_a->h.dwSampleSize=sh_audio->audio.dwSampleSize; mux_a->h.dwScale=sh_audio->audio.dwScale; mux_a->h.dwRate=sh_audio->audio.dwRate; -// mux_a->h.dwStart=sh_audio->audio.dwStart; } else { mux_a->h.dwSampleSize=mux_a->wf->nBlockAlign; mux_a->h.dwScale=mux_a->h.dwSampleSize; @@ -958,9 +964,8 @@ if (verbose>1) print_wave_header(mux_a->wf); -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 (! ignore_start) { + muxer->audio_delay_fix += sh_audio->stream_delay; } } // if(sh_audio) @@ -1390,6 +1395,9 @@ AV_delay-=audio_delay; AV_delay /= playback_speed; AV_delay-=mux_a->timer-(mux_v->timer-(v_timer_corr+v_pts_corr)); + // adjust for encoder delays + AV_delay -= (float) mux_a->encoder_delay * mux_a->h.dwScale/mux_a->h.dwRate; + AV_delay += (float) mux_v->encoder_delay * mux_v->h.dwScale/mux_v->h.dwRate; // compensate input video timer by av: x=AV_delay*0.1f; if(x<-max_pts_correction) x=-max_pts_correction; else Index: mplayer.c =================================================================== RCS file: /cvsroot/mplayer/main/mplayer.c,v retrieving revision 1.908 diff -u -r1.908 mplayer.c --- mplayer.c 17 Feb 2006 01:57:40 -0000 1.908 +++ mplayer.c 17 Feb 2006 02:32:03 -0000 @@ -294,6 +294,7 @@ static float max_pts_correction=0;//default_max_pts_correction; static float c_total=0; float audio_delay=0; +static int ignore_start=0; static int softsleep=0; @@ -2522,8 +2523,16 @@ current_module="av_init"; -if(sh_video) sh_video->timer=0; -if(sh_audio) sh_audio->delay=-audio_delay; +if(sh_video){ + sh_video->timer=0; + if (! ignore_start) + audio_delay += sh_video->stream_delay; +} +if(sh_audio){ + if (! ignore_start) + audio_delay -= sh_audio->stream_delay; + sh_audio->delay=-audio_delay; +} if(!sh_audio){ mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_NoSound); Index: DOCS/man/en/mplayer.1 =================================================================== RCS file: /cvsroot/mplayer/main/DOCS/man/en/mplayer.1,v retrieving revision 1.1227 diff -u -r1.1227 mplayer.1 --- DOCS/man/en/mplayer.1 13 Feb 2006 11:15:24 -0000 1.1227 +++ DOCS/man/en/mplayer.1 17 Feb 2006 02:32:04 -0000 @@ -1098,9 +1098,21 @@ .br .I NOTE: When used with MEncoder, this is not guaranteed to work correctly -with \-ovc copy. +with \-ovc copy; use \-audio-delay instead. . .TP ++.B \-ignore-start +Ignore the specified starting time for streams in AVI files. +In MPlayer, this nullifies stream delays in files encoded with +the \-audio-delay option. +During encoding, this option prevents MEncoder from transferring +original stream start times to the new file; the \-audio-delay option is +not affected. +Note that MEncoder sometimes adjusts stream starting times +automatically to compensate for anticipated decoding delays, so don't +use this option for encoding without testing it first. +.TP + .B \-demuxer <[+]name> Force demuxer type. Use a '+' before the name to force it, this will skip some checks! @@ -6058,11 +6070,15 @@ .SH "GENERAL ENCODING OPTIONS (MENCODER ONLY)" . .TP -.B \-audio-delay <0.0\-...> -Sets the audio delay field in the header. -Default is 0.0, negative values do not work. -This does not delay the audio while encoding, but the player will see the -default audio delay, sparing you the use of the \-delay option. +.B \-audio-delay +Delays either audio or video by setting a delay field in the header +(default: 0.0). +This does not delay either stream while encoding, but the player will +see the delay field and compensate accordingly. +Positive values delay the audio, and negative values delay the video. +Note that this is the exact opposite of the \-delay option. +For example, if a video plays correctly with \-delay 0.2, you can +fix the video with MEncoder by using \-audio-delay -0.2. . .TP .B \-audio-density <1\-50> Index: help/help_mp-en.h =================================================================== RCS file: /cvsroot/mplayer/main/help/help_mp-en.h,v retrieving revision 1.221 diff -u -r1.221 help_mp-en.h --- help/help_mp-en.h 30 Jan 2006 19:37:17 -0000 1.221 +++ help/help_mp-en.h 17 Feb 2006 02:32:04 -0000 @@ -261,7 +261,8 @@ #define MSGTR_CBRPCMAudioSelected "CBR PCM audio selected\n" #define MSGTR_MP3AudioSelected "MP3 audio selected\n" #define MSGTR_CannotAllocateBytes "Couldn't allocate %d bytes\n" -#define MSGTR_SettingAudioDelay "Setting AUDIO DELAY to %5.3f\n" +#define MSGTR_SettingAudioDelay "Setting audio delay to %5.3fs\n" +#define MSGTR_SettingVideoDelay "Setting video delay to %5.3fs\n" #define MSGTR_SettingAudioInputGain "Setting audio input gain to %f\n" #define MSGTR_LamePresetEquals "\npreset=%s\n\n" #define MSGTR_LimitingAudioPreload "Limiting audio preload to 0.4s\n" Index: libmpcodecs/ve_lavc.c =================================================================== RCS file: /cvsroot/mplayer/main/libmpcodecs/ve_lavc.c,v retrieving revision 1.131 diff -u -r1.131 ve_lavc.c --- libmpcodecs/ve_lavc.c 31 Jan 2006 23:36:12 -0000 1.131 +++ libmpcodecs/ve_lavc.c 17 Feb 2006 02:32:05 -0000 @@ -770,6 +770,8 @@ mux_v->bih->biSize= sizeof(BITMAPINFOHEADER) + lavc_venc_context->extradata_size; } + mux_v->decoder_delay = lavc_venc_context->max_b_frames ? 1 : 0; + return 1; } @@ -854,8 +856,10 @@ out_size = avcodec_encode_video(lavc_venc_context, mux_v->buffer, mux_v->buffer_size, pic); - if(out_size == 0) + if(out_size == 0) { + ++mux_v->encoder_delay; return 0; + } muxer_write_chunk(mux_v,out_size,lavc_venc_context->coded_frame->key_frame?0x10:0, MP_NOPTS_VALUE, MP_NOPTS_VALUE); Index: libmpcodecs/ve_x264.c =================================================================== RCS file: /cvsroot/mplayer/main/libmpcodecs/ve_x264.c,v retrieving revision 1.45 diff -u -r1.45 ve_x264.c --- libmpcodecs/ve_x264.c 31 Jan 2006 23:36:12 -0000 1.45 +++ libmpcodecs/ve_x264.c 17 Feb 2006 02:32:05 -0000 @@ -435,6 +435,11 @@ return 0; } + if (mod->param.i_bframe > 1 && mod->param.b_bframe_pyramid) + mod->mux->decoder_delay = 2; + else + mod->mux->decoder_delay = mod->param.i_bframe ? 1 : 0; + return 1; } @@ -511,6 +516,8 @@ && frame_ref == 1 && !bframe); muxer_write_chunk(mod->mux, i_size, keyframe?0x10:0, MP_NOPTS_VALUE, MP_NOPTS_VALUE); } + else + ++mod->mux->encoder_delay; return i_size; } Index: libmpcodecs/ve_xvid.c =================================================================== RCS file: /cvsroot/mplayer/main/libmpcodecs/ve_xvid.c,v retrieving revision 1.31 diff -u -r1.31 ve_xvid.c --- libmpcodecs/ve_xvid.c 26 Jan 2006 19:32:06 -0000 1.31 +++ libmpcodecs/ve_xvid.c 17 Feb 2006 02:32:05 -0000 @@ -378,6 +378,10 @@ vbrInit(&fp->vbr_state); +#ifdef XVID_API_UNSTABLE + fp->mux->decoder_delay = enc_param.max_bframes ? 1 : 0; +#endif + return 1; } @@ -523,7 +527,10 @@ #endif // write output + if (fp->enc_frame.length > 0) muxer_write_chunk(fp->mux, fp->enc_frame.length, fp->enc_frame.intra==1 ? 0x10 : 0, MP_NOPTS_VALUE, MP_NOPTS_VALUE); + else + ++fp->mux->encoder_delay; // update the VBR engine vbrUpdate(&fp->vbr_state, enc_stats.quant, fp->enc_frame.intra, Index: libmpcodecs/ve_xvid4.c =================================================================== RCS file: /cvsroot/mplayer/main/libmpcodecs/ve_xvid4.c,v retrieving revision 1.23 diff -u -r1.23 ve_xvid4.c --- libmpcodecs/ve_xvid4.c 26 Jan 2006 19:32:06 -0000 1.23 +++ libmpcodecs/ve_xvid4.c 17 Feb 2006 02:32:05 -0000 @@ -504,6 +504,8 @@ /* Store the encoder instance into the private data */ mod->instance = mod->create.handle; + mod->mux->decoder_delay = mod->create.max_bframes ? 1 : 0; + return(FINE); } @@ -620,7 +622,10 @@ } /* If size is == 0, we're done with that frame */ - if(size == 0) return(FINE); + if(size == 0) { + ++mod->mux->encoder_delay; + return(FINE); + } /* xvidcore returns stats about encoded frame in an asynchronous way * accumulate these stats */ Index: libmpdemux/demux_avi.c =================================================================== RCS file: /cvsroot/mplayer/main/libmpdemux/demux_avi.c,v retrieving revision 1.73 diff -u -r1.73 demux_avi.c --- libmpdemux/demux_avi.c 17 Feb 2006 01:57:40 -0000 1.73 +++ libmpdemux/demux_avi.c 17 Feb 2006 02:32:06 -0000 @@ -612,6 +612,12 @@ mp_msg(MSGT_DEMUX,MSGL_V,"AVI video size=%d (%u) audio size=%d\n",vsize,priv->numberofframes,asize); sh_video->i_bps=(float)vsize/(sh_video->frametime*priv->numberofframes); } + + if (sh_video) + sh_video->stream_delay = (float)sh_video->video.dwStart * sh_video->video.dwScale/sh_video->video.dwRate; + if (sh_audio) + sh_audio->stream_delay = (float)sh_audio->audio.dwStart * sh_audio->audio.dwScale/sh_audio->audio.dwRate; + return demuxer; } Index: libmpdemux/muxer.h =================================================================== RCS file: /cvsroot/mplayer/main/libmpdemux/muxer.h,v retrieving revision 1.18 diff -u -r1.18 muxer.h --- libmpdemux/muxer.h 26 Jan 2006 19:32:07 -0000 1.18 +++ libmpdemux/muxer.h 17 Feb 2006 02:32:10 -0000 @@ -38,6 +38,8 @@ // stream specific: WAVEFORMATEX *wf; BITMAPINFOHEADER *bih; // in format + int encoder_delay; // in number of frames + int decoder_delay; // in number of frames // mpeg specific: size_t ipb[3]; // sizes of I/P/B frames // muxer of that stream @@ -59,6 +61,7 @@ off_t movi_start; off_t movi_end; off_t file_end; // for MPEG it's system timestamp in 1/90000 s + float audio_delay_fix; // index: AVIINDEXENTRY *idx; int idx_pos; Index: libmpdemux/muxer_avi.c =================================================================== RCS file: /cvsroot/mplayer/main/libmpdemux/muxer_avi.c,v retrieving revision 1.35 diff -u -r1.35 muxer_avi.c --- libmpdemux/muxer_avi.c 26 Jan 2006 19:32:07 -0000 1.35 +++ libmpdemux/muxer_avi.c 17 Feb 2006 02:32:10 -0000 @@ -285,6 +285,19 @@ mp_msg(MSGT_MUXER, MSGL_INFO, "ODML: vprp aspect is %d:%d.\n", aspect >> 16, aspect & 0xffff); } + /* deal with stream delays */ + for (i = 0; muxer->streams[i] && i < MUXER_MAX_STREAMS; ++i) { + muxer_stream_t *s = muxer->streams[i]; + if (s->type == MUXER_TYPE_AUDIO && muxer->audio_delay_fix > 0.0) { + s->h.dwStart = muxer->audio_delay_fix * s->h.dwRate/s->h.dwScale; + mp_msg(MSGT_MUXER, MSGL_INFO, MSGTR_SettingAudioDelay, (float)s->h.dwStart * s->h.dwScale/s->h.dwRate); + } + if (s->type == MUXER_TYPE_VIDEO && muxer->audio_delay_fix < 0.0) { + s->h.dwStart = -muxer->audio_delay_fix * s->h.dwRate/s->h.dwScale; + mp_msg(MSGT_MUXER, MSGL_INFO, MSGTR_SettingVideoDelay, (float)s->h.dwStart * s->h.dwScale/s->h.dwRate); + } + } + if (isodml) { unsigned int rifflen, movilen; int i; @@ -652,10 +665,19 @@ } } +static void avifile_fix_parameters(muxer_stream_t *s){ + /* adjust audio_delay_fix according to individual stream delay */ + if (s->type == MUXER_TYPE_AUDIO) + s->muxer->audio_delay_fix -= (float)s->decoder_delay * s->h.dwScale/s->h.dwRate; + if (s->type == MUXER_TYPE_VIDEO) + s->muxer->audio_delay_fix += (float)s->decoder_delay * s->h.dwScale/s->h.dwRate; +} + int muxer_init_muxer_avi(muxer_t *muxer){ muxer->cont_new_stream = &avifile_new_stream; muxer->cont_write_chunk = &avifile_write_chunk; muxer->cont_write_header = &avifile_write_header; muxer->cont_write_index = &avifile_write_index; + muxer->fix_stream_parameters = &avifile_fix_parameters; return 1; } Index: libmpdemux/stheader.h =================================================================== RCS file: /cvsroot/mplayer/main/libmpdemux/stheader.h,v retrieving revision 1.41 diff -u -r1.41 stheader.h --- libmpdemux/stheader.h 25 Feb 2005 11:17:43 -0000 1.41 +++ libmpdemux/stheader.h 17 Feb 2006 02:32:10 -0000 @@ -12,6 +12,7 @@ unsigned int format; int inited; float delay; // relative (to sh_video->timer) time in audio stream + float stream_delay; // number of seconds stream should be delayed (according to dwStart or similar) // output format: int sample_format; int samplerate; @@ -54,6 +55,7 @@ unsigned int format; int inited; float timer; // absolute time in video stream, since last start/seek + float stream_delay; // number of seconds stream should be delayed (according to dwStart or similar) // frame counters: float num_frames; // number of frames played int num_frames_decoded; // number of frames decoded