@ -230,9 +230,8 @@ typedef struct AVOutputStream {
int frame_number ;
int frame_number ;
/* input pts and corresponding output pts
/* input pts and corresponding output pts
for A / V sync */
for A / V sync */
double sync_ipts ;
double sync_ipts ; /* dts from the AVPacket of the demuxer in second units */
double sync_ipts_offset ;
int64_t sync_opts ; /* output frame counter, could be changed to some true timestamp */ //FIXME look at frame_number
int64_t sync_opts ;
/* video only */
/* video only */
int video_resample ; /* video_resample and video_crop are mutually exclusive */
int video_resample ; /* video_resample and video_crop are mutually exclusive */
AVFrame pict_tmp ; /* temporary image for resampling */
AVFrame pict_tmp ; /* temporary image for resampling */
@ -447,12 +446,23 @@ static void do_audio_out(AVFormatContext *s,
while ( fifo_read ( & ost - > fifo , audio_buf , frame_bytes ,
while ( fifo_read ( & ost - > fifo , audio_buf , frame_bytes ,
& ost - > fifo . rptr ) = = 0 ) {
& ost - > fifo . rptr ) = = 0 ) {
AVPacket pkt ;
av_init_packet ( & pkt ) ;
ret = avcodec_encode_audio ( enc , audio_out , audio_out_size ,
ret = avcodec_encode_audio ( enc , audio_out , audio_out_size ,
( short * ) audio_buf ) ;
( short * ) audio_buf ) ;
audio_size + = ret ;
audio_size + = ret ;
av_write_frame ( s , ost - > index , audio_out , ret ) ;
pkt . stream_index = ost - > index ;
pkt . data = audio_out ;
pkt . size = ret ;
if ( enc - > coded_frame )
pkt . pts = enc - > coded_frame - > pts ;
pkt . flags | = PKT_FLAG_KEY ;
av_write_frame ( s , & pkt ) ;
}
}
} else {
} else {
AVPacket pkt ;
av_init_packet ( & pkt ) ;
/* output a pcm frame */
/* output a pcm frame */
/* XXX: change encoding codec API to avoid this ? */
/* XXX: change encoding codec API to avoid this ? */
switch ( enc - > codec - > id ) {
switch ( enc - > codec - > id ) {
@ -468,7 +478,13 @@ static void do_audio_out(AVFormatContext *s,
ret = avcodec_encode_audio ( enc , audio_out , size_out ,
ret = avcodec_encode_audio ( enc , audio_out , size_out ,
( short * ) buftmp ) ;
( short * ) buftmp ) ;
audio_size + = ret ;
audio_size + = ret ;
av_write_frame ( s , ost - > index , audio_out , ret ) ;
pkt . stream_index = ost - > index ;
pkt . data = audio_out ;
pkt . size = ret ;
if ( enc - > coded_frame )
pkt . pts = enc - > coded_frame - > pts ;
pkt . flags | = PKT_FLAG_KEY ;
av_write_frame ( s , & pkt ) ;
}
}
}
}
@ -586,58 +602,17 @@ static void do_video_out(AVFormatContext *s,
* frame_size = 0 ;
* frame_size = 0 ;
/* NOTE: the A/V sync is always done by considering the audio is
if ( sync_method ) {
the master clock . It is suffisant for transcoding or playing ,
but not for the general case */
if ( sync_method ) {
if ( audio_sync ) {
/* compute the A-V delay and duplicate/remove frames if needed */
double adelta , vdelta , av_delay ;
adelta = audio_sync - > sync_ipts - ( ( double ) audio_sync - > sync_opts *
audio_sync - > st - > time_base . num / audio_sync - > st - > time_base . den ) ;
vdelta = ost - > sync_ipts - ( ( double ) ost - > sync_opts *
ost - > st - > time_base . num / ost - > st - > time_base . den ) ;
av_delay = adelta - vdelta ;
if ( av_delay < - AV_DELAY_MAX )
nb_frames = 2 ;
else if ( av_delay > AV_DELAY_MAX )
nb_frames = 0 ;
// printf("adelta=%f vdelta=%f delay=%f nb=%d (A)\n", adelta, vdelta, av_delay, nb_frames);
} else {
double vdelta ;
double vdelta ;
vdelta = ost - > sync_ipts * enc - > frame_rate / enc - > frame_rate_base - ost - > sync_opts ;
vdelta = ( double ) ( ost - > st - > pts . val ) * ost - > st - > time_base . num / ost - > st - > time_base . den - ( ost - > sync_ipts - ost - > sync_ipts_offset ) ;
//FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c
if ( vdelta < 100 & & vdelta > - 100 & & ost - > sync_ipts_offset ) {
if ( vdelta < - 1.1 )
if ( vdelta < - AV_DELAY_MAX )
nb_frames = 0 ;
nb_frames = 2 ;
else if ( vdelta > 1.1 )
else if ( vdelta > AV_DELAY_MAX )
nb_frames = 2 ;
nb_frames = 0 ;
//printf("vdelta:%f, ost->sync_opts:%lld, ost->sync_ipts:%f nb_frames:%d\n", vdelta, ost->sync_opts, ost->sync_ipts, nb_frames);
} else {
ost - > sync_ipts_offset - = vdelta ;
if ( ! ost - > sync_ipts_offset )
ost - > sync_ipts_offset = 0.000001 ; /* one microsecond */
}
// printf("delay=%f nb=%d (V)\n",vdelta, nb_frames);
}
}
# if defined(AVSYNC_DEBUG)
{
static char * action [ ] = { " drop frame " , " copy frame " , " dup frame " } ;
if ( audio_sync & & verbose > = 0 ) {
fprintf ( stderr , " Input APTS %12.6f, output APTS %12.6f, " ,
( double ) audio_sync - > sync_ipts ,
( double ) audio_sync - > st - > pts . val * st - > time_base . num / st - > time_base . den ) ;
fprintf ( stderr , " Input VPTS %12.6f, output VPTS %12.6f: %s \n " ,
( double ) ost - > sync_ipts ,
( double ) ost - > st - > pts . val * st - > time_base . num / st - > time_base . den ,
action [ nb_frames ] ) ;
}
}
}
# endif
ost - > sync_opts + = nb_frames ;
if ( nb_frames < = 0 )
if ( nb_frames < = 0 )
return ;
return ;
@ -779,14 +754,24 @@ static void do_video_out(AVFormatContext *s,
/* duplicates frame if needed */
/* duplicates frame if needed */
/* XXX: pb because no interleaving */
/* XXX: pb because no interleaving */
for ( i = 0 ; i < nb_frames ; i + + ) {
for ( i = 0 ; i < nb_frames ; i + + ) {
AVPacket pkt ;
av_init_packet ( & pkt ) ;
pkt . stream_index = ost - > index ;
if ( s - > oformat - > flags & AVFMT_RAWPICTURE ) {
if ( s - > oformat - > flags & AVFMT_RAWPICTURE ) {
/* raw pictures are written as AVPicture structure to
/* raw pictures are written as AVPicture structure to
avoid any copies . We support temorarily the older
avoid any copies . We support temorarily the older
method . */
method . */
AVFrame * old_frame = enc - > coded_frame ;
AVFrame * old_frame = enc - > coded_frame ;
enc - > coded_frame = dec - > coded_frame ;
enc - > coded_frame = dec - > coded_frame ; //FIXME/XXX remove this hack
av_write_frame ( s , ost - > index ,
pkt . data = ( uint8_t * ) final_picture ;
( uint8_t * ) final_picture , sizeof ( AVPicture ) ) ;
pkt . size = sizeof ( AVPicture ) ;
if ( dec - > coded_frame )
pkt . pts = dec - > coded_frame - > pts ;
if ( dec - > coded_frame & & dec - > coded_frame - > key_frame )
pkt . flags | = PKT_FLAG_KEY ;
av_write_frame ( s , & pkt ) ;
enc - > coded_frame = old_frame ;
enc - > coded_frame = old_frame ;
} else {
} else {
AVFrame big_picture ;
AVFrame big_picture ;
@ -815,14 +800,22 @@ static void do_video_out(AVFormatContext *s,
video_buffer , VIDEO_BUFFER_SIZE ,
video_buffer , VIDEO_BUFFER_SIZE ,
& big_picture ) ;
& big_picture ) ;
//enc->frame_number = enc->real_pict_num;
//enc->frame_number = enc->real_pict_num;
av_write_frame ( s , ost - > index , video_buffer , ret ) ;
if ( ret ) {
* frame_size = ret ;
pkt . data = video_buffer ;
//fprintf(stderr,"\nFrame: %3d %3d size: %5d type: %d",
pkt . size = ret ;
// enc->frame_number-1, enc->real_pict_num, ret,
if ( enc - > coded_frame )
// enc->pict_type);
pkt . pts = enc - > coded_frame - > pts ;
/* if two pass, output log */
if ( enc - > coded_frame & & enc - > coded_frame - > key_frame )
if ( ost - > logfile & & enc - > stats_out ) {
pkt . flags | = PKT_FLAG_KEY ;
fprintf ( ost - > logfile , " %s " , enc - > stats_out ) ;
av_write_frame ( s , & pkt ) ;
* frame_size = ret ;
//fprintf(stderr,"\nFrame: %3d %3d size: %5d type: %d",
// enc->frame_number-1, enc->real_pict_num, ret,
// enc->pict_type);
/* if two pass, output log */
if ( ost - > logfile & & enc - > stats_out ) {
fprintf ( ost - > logfile , " %s " , enc - > stats_out ) ;
}
}
}
}
}
ost - > frame_number + + ;
ost - > frame_number + + ;
@ -872,7 +865,7 @@ static void do_video_stats(AVFormatContext *os, AVOutputStream *ost,
fprintf ( fvstats , " f_size= %6d " , frame_size ) ;
fprintf ( fvstats , " f_size= %6d " , frame_size ) ;
/* compute pts value */
/* compute pts value */
ti1 = ( double ) ost - > st - > pts . val * ost - > st - > time_base . num / ost - > st - > time_base . den ;
ti1 = ( double ) ost - > sync_opts * enc - > frame_rate_base / enc - > frame_rate ;
if ( ti1 < 0.01 )
if ( ti1 < 0.01 )
ti1 = 0.01 ;
ti1 = 0.01 ;
@ -1003,8 +996,8 @@ static int output_packet(AVInputStream *ist, int ist_index,
short samples [ AVCODEC_MAX_AUDIO_FRAME_SIZE / 2 ] ;
short samples [ AVCODEC_MAX_AUDIO_FRAME_SIZE / 2 ] ;
void * buffer_to_free ;
void * buffer_to_free ;
if ( pkt & & pkt - > pts ! = AV_NOPTS_VALUE ) {
if ( pkt & & pkt - > pts ! = AV_NOPTS_VALUE ) { //FIXME seems redundant, as libavformat does this too
ist - > next_pts = ist - > pts = pkt - > p ts;
ist - > next_pts = ist - > pts = pkt - > d ts;
} else {
} else {
ist - > pts = ist - > next_pts ;
ist - > pts = ist - > next_pts ;
}
}
@ -1122,10 +1115,6 @@ static int output_packet(AVInputStream *ist, int ist_index,
# endif
# endif
/* set the input output pts pairs */
/* set the input output pts pairs */
ost - > sync_ipts = ( double ) ist - > pts / AV_TIME_BASE ;
ost - > sync_ipts = ( double ) ist - > pts / AV_TIME_BASE ;
/* XXX: take into account the various fifos,
in particular for audio */
ost - > sync_opts = ost - > st - > pts . val ;
//printf("ipts=%lld sync_ipts=%f sync_opts=%lld pts.val=%lld pkt->pts=%lld\n", ist->pts, ost->sync_ipts, ost->sync_opts, ost->st->pts.val, pkt->pts);
if ( ost - > encoding_needed ) {
if ( ost - > encoding_needed ) {
switch ( ost - > st - > codec . codec_type ) {
switch ( ost - > st - > codec . codec_type ) {
@ -1157,22 +1146,29 @@ static int output_packet(AVInputStream *ist, int ist_index,
av_abort ( ) ;
av_abort ( ) ;
}
}
} else {
} else {
AVFrame avframe ;
AVFrame avframe ; //FIXME/XXX remove this
AVPacket opkt ;
av_init_packet ( & opkt ) ;
/* no reencoding needed : output the packet directly */
/* no reencoding needed : output the packet directly */
/* force the input stream PTS */
/* force the input stream PTS */
avcodec_get_frame_defaults ( & avframe ) ;
avcodec_get_frame_defaults ( & avframe ) ;
ost - > st - > codec . coded_frame = & avframe ;
ost - > st - > codec . coded_frame = & avframe ;
avframe . key_frame = pkt - > flags & PKT_FLAG_KEY ;
avframe . key_frame = pkt - > flags & PKT_FLAG_KEY ;
ost - > st - > pts . val = av_rescale ( ist - > pts , ost - > st - > time_base . den , ost - > st - > time_base . num * AV_TIME_BASE ) ;
if ( ost - > st - > codec . codec_type = = CODEC_TYPE_AUDIO )
if ( ost - > st - > codec . codec_type = = CODEC_TYPE_AUDIO )
audio_size + = data_size ;
audio_size + = data_size ;
else if ( ost - > st - > codec . codec_type = = CODEC_TYPE_VIDEO )
else if ( ost - > st - > codec . codec_type = = CODEC_TYPE_VIDEO )
video_size + = data_size ;
video_size + = data_size ;
av_write_frame ( os , ost - > index , data_buf , data_size ) ;
opkt . stream_index = ost - > index ;
opkt . data = data_buf ;
opkt . size = data_size ;
opkt . pts = ist - > pts ; //FIXME dts vs. pts
opkt . flags = pkt - > flags ;
av_write_frame ( os , & opkt ) ;
ost - > st - > codec . frame_number + + ;
ost - > st - > codec . frame_number + + ;
ost - > frame_number + + ;
ost - > frame_number + + ;
}
}