[MPlayer-cvslog] r32520 - trunk/mencoder.c
corey
subversion at mplayerhq.hu
Thu Oct 21 09:05:30 CEST 2010
Author: corey
Date: Thu Oct 21 09:05:30 2010
New Revision: 32520
Log:
Make mencoder account for encoder delay when considering the current
time position of a muxer stream. To mencoder core, delayed frames
should be considered as "dealt with", since they'll get to the muxer
eventually. Without this compensation, mencoder will sometimes make
different frame skip/duplicate decisions on the first of a two-pass
x264 encode (since x264 buffers many more frames on the first pass),
leading to a segfault in x264 when it gets fed more frames on the
second pass.
Modified:
trunk/mencoder.c
Modified: trunk/mencoder.c
==============================================================================
--- trunk/mencoder.c Wed Oct 20 10:12:40 2010 (r32519)
+++ trunk/mencoder.c Thu Oct 21 09:05:30 2010 (r32520)
@@ -354,15 +354,28 @@ static void add_subtitles(char *filename
subdata = subd;
}
+/* Provide a timer value suitable for use in A/V sync calculations.
+ * mux->timer records the current position of the muxer stream.
+ * mux->encoder_delay is how many frames are currently buffered by the
+ * encoder. To mencoder core, encoder-buffered frames have been "dealt with"--
+ * they'll get to the muxer eventually. So, for the purposes of A/V sync,
+ * we need to add the total time length of buffered frames to the muxer stream
+ * position. */
+static double adjusted_muxer_time(muxer_stream_t *mux)
+{
+ if (! mux) return MP_NOPTS_VALUE;
+ return mux->timer + (double) mux->encoder_delay * mux->h.dwScale/mux->h.dwRate;
+}
+
/* This function returns the absolute time for which MEncoder will switch files
* or move in the file so audio can be cut correctly. -1 if there is no limit. */
static float stop_time(demuxer_t* demuxer, muxer_stream_t* mux_v)
{
float timeleft = -1;
- if (play_n_frames >= 0) timeleft = mux_v->timer + play_n_frames * (double)(mux_v->h.dwScale) / mux_v->h.dwRate;
+ if (play_n_frames >= 0) timeleft = adjusted_muxer_time(mux_v) + play_n_frames * (double)(mux_v->h.dwScale) / mux_v->h.dwRate;
if (end_at.type == END_AT_TIME && (timeleft > end_at.pos || timeleft == -1)) timeleft = end_at.pos;
if (next_edl_record && demuxer && demuxer->video) { // everything is OK to be checked
- float tmp = mux_v->timer + next_edl_record->start_sec - demuxer->video->pts;
+ float tmp = adjusted_muxer_time(mux_v) + next_edl_record->start_sec - demuxer->video->pts;
if (timeleft == -1 || timeleft > tmp) {
// There's less time in EDL than what we already know
if (next_edl_record->action == EDL_SKIP && edl_seeking) {
@@ -1225,7 +1238,7 @@ if(file_format == DEMUXER_TYPE_TV)
}
play_n_frames=play_n_frames_mf;
-if (curfile && end_at.type == END_AT_TIME) end_at.pos += mux_v->timer;
+if (curfile && end_at.type == END_AT_TIME) end_at.pos += adjusted_muxer_time(mux_v);
if (edl_records) free_edl(edl_records);
next_edl_record = edl_records = NULL;
@@ -1243,9 +1256,14 @@ while(!at_eof){
float a_pts=0;
float v_pts=0;
int skip_flag=0; // 1=skip -1=duplicate
+ double a_muxer_time;
+ double v_muxer_time;
+
+ a_muxer_time = adjusted_muxer_time(mux_a);
+ v_muxer_time = adjusted_muxer_time(mux_v);
if((end_at.type == END_AT_SIZE && end_at.pos <= stream_tell(muxer->stream)) ||
- (end_at.type == END_AT_TIME && end_at.pos < mux_v->timer))
+ (end_at.type == END_AT_TIME && end_at.pos < v_muxer_time))
break;
if(play_n_frames>=0){
@@ -1299,7 +1317,7 @@ goto_redo_edl:
if(sh_audio){
// get audio:
- while(mux_a->timer-audio_preload<mux_v->timer){
+ while(a_muxer_time-audio_preload<v_muxer_time){
float tottime;
int len=0;
@@ -1308,7 +1326,7 @@ if(sh_audio){
// or until the end of video:
tottime = stop_time(demuxer, mux_v);
if (tottime != -1) {
- tottime -= mux_a->timer;
+ tottime -= a_muxer_time;
if (tottime > 1./audio_density) tottime = 1./audio_density;
}
else tottime = 1./audio_density;
@@ -1359,7 +1377,7 @@ if(sh_audio){
mux_a->buffer_len += len;
}
}
- if (mux_v->timer == 0) mux_a->h.dwInitialFrames++;
+ if (v_muxer_time == 0) mux_a->h.dwInitialFrames++;
}
else {
if(mux_a->h.dwSampleSize){
@@ -1382,8 +1400,9 @@ if(sh_audio){
}
if(len<=0) break; // EOF?
muxer_write_chunk(mux_a,len,AVIIF_KEYFRAME, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
- if(!mux_a->h.dwSampleSize && mux_a->timer>0)
- mux_a->wf->nAvgBytesPerSec=0.5f+(double)mux_a->size/mux_a->timer; // avg bps (VBR)
+ a_muxer_time = adjusted_muxer_time(mux_a); // update after muxing
+ if(!mux_a->h.dwSampleSize && a_muxer_time>0)
+ mux_a->wf->nAvgBytesPerSec=0.5f+(double)mux_a->size/a_muxer_time; // avg bps (VBR)
if(mux_a->buffer_len>=len){
mux_a->buffer_len-=len;
fast_memcpy(mux_a->buffer,mux_a->buffer+len,mux_a->buffer_len);
@@ -1478,6 +1497,7 @@ default:
void *decoded_frame = decode_video(sh_video,frame_data.start,frame_data.in_size,
drop_frame, MP_NOPTS_VALUE, NULL);
blit_frame = decoded_frame && filter_video(sh_video, decoded_frame, MP_NOPTS_VALUE);}
+ v_muxer_time = adjusted_muxer_time(mux_v); // update after muxing
if (sh_video->vf_initialized < 0) mencoder_exit(1, NULL);
@@ -1550,10 +1570,7 @@ if(sh_audio && !demuxer2){
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));
- // 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;
+ AV_delay-=a_muxer_time-(v_muxer_time-(v_timer_corr+v_pts_corr));
// compensate input video timer by av:
x=AV_delay*0.1f;
if(x<-max_pts_correction) x=-max_pts_correction; else
@@ -1581,25 +1598,25 @@ if(sh_audio && !demuxer2){
if(!quiet) {
if( mp_msg_test(MSGT_STATUSLINE,MSGL_V) ) {
mp_msg(MSGT_STATUSLINE,MSGL_STATUS,"Pos:%6.1fs %6df (%2d%%) %3dfps Trem:%4dmin %3dmb A-V:%5.3f [%d:%d] A/Vms %d/%d D/B/S %d/%d/%d \r",
- mux_v->timer, decoded_frameno, (int)(p*100),
+ v_muxer_time, decoded_frameno, (int)(p*100),
(t>1) ? (int)(decoded_frameno/t+0.5) : 0,
(p>0.001) ? (int)((t/p-t)/60) : 0,
(p>0.001) ? (int)(stream_tell(muxer->stream)/p/1024/1024) : 0,
v_pts_corr,
- (mux_v->timer>1) ? (int)(mux_v->size/mux_v->timer/125) : 0,
- (mux_a && mux_a->timer>1) ? (int)(mux_a->size/mux_a->timer/125) : 0,
+ (v_muxer_time>1) ? (int)(mux_v->size/v_muxer_time/125) : 0,
+ (mux_a && a_muxer_time>1) ? (int)(mux_a->size/a_muxer_time/125) : 0,
audiorate/audiosamples, videorate/videosamples,
duplicatedframes, badframes, skippedframes
);
} else
mp_msg(MSGT_STATUSLINE,MSGL_STATUS,"Pos:%6.1fs %6df (%2d%%) %5.2ffps Trem:%4dmin %3dmb A-V:%5.3f [%d:%d]\r",
- mux_v->timer, decoded_frameno, (int)(p*100),
+ v_muxer_time, decoded_frameno, (int)(p*100),
(t>1) ? (float)(decoded_frameno/t) : 0,
(p>0.001) ? (int)((t/p-t)/60) : 0,
(p>0.001) ? (int)(stream_tell(muxer->stream)/p/1024/1024) : 0,
v_pts_corr,
- (mux_v->timer>1) ? (int)(mux_v->size/mux_v->timer/125) : 0,
- (mux_a && mux_a->timer>1) ? (int)(mux_a->size/mux_a->timer/125) : 0
+ (v_muxer_time>1) ? (int)(mux_v->size/v_muxer_time/125) : 0,
+ (mux_a && a_muxer_time>1) ? (int)(mux_a->size/a_muxer_time/125) : 0
);
}
}
@@ -1612,7 +1629,7 @@ if(sh_audio && !demuxer2){
int len;
while((len=ds_get_packet_sub(d_dvdsub,&packet, NULL, NULL))>0){
mp_msg(MSGT_MENCODER,MSGL_V,"\rDVD sub: len=%d v_pts=%5.3f s_pts=%5.3f \n",len,sh_video->pts,d_dvdsub->pts);
- vobsub_out_output(vobsub_writer,packet,len,mux_v->timer + d_dvdsub->pts - sh_video->pts);
+ vobsub_out_output(vobsub_writer,packet,len,v_muxer_time + d_dvdsub->pts - sh_video->pts);
}
}
else
More information about the MPlayer-cvslog
mailing list