@ -18,6 +18,7 @@
*/
# define HAVE_AV_CONFIG_H
# include "avformat.h"
# include "framehook.h"
# ifndef CONFIG_WIN32
# include <unistd.h>
@ -447,6 +448,46 @@ static void write_picture(AVFormatContext *s, int index, AVPicture *picture,
av_free ( buf ) ;
}
static void pre_process_video_frame ( AVInputStream * ist , AVPicture * picture , void * * bufp )
{
AVCodecContext * dec ;
AVPicture * picture2 ;
AVPicture picture_tmp ;
UINT8 * buf = 0 ;
dec = & ist - > st - > codec ;
/* deinterlace : must be done before any resize */
if ( do_deinterlace ) {
int size ;
/* create temporary picture */
size = avpicture_get_size ( dec - > pix_fmt , dec - > width , dec - > height ) ;
buf = av_malloc ( size ) ;
if ( ! buf )
return ;
picture2 = & picture_tmp ;
avpicture_fill ( picture2 , buf , dec - > pix_fmt , dec - > width , dec - > height ) ;
if ( avpicture_deinterlace ( picture2 , picture ,
dec - > pix_fmt , dec - > width , dec - > height ) < 0 ) {
/* if error, do not deinterlace */
av_free ( buf ) ;
buf = NULL ;
picture2 = picture ;
}
} else {
picture2 = picture ;
}
frame_hook_process ( picture2 , dec - > pix_fmt , dec - > width , dec - > height ) ;
if ( picture ! = picture2 )
* picture = * picture2 ;
* bufp = buf ;
}
/* we begin to correct av delay at this threshold */
# define AV_DELAY_MAX 0.100
@ -457,8 +498,8 @@ static void do_video_out(AVFormatContext *s,
int * frame_size , AVOutputStream * audio_sync )
{
int nb_frames , i , ret ;
AVPicture * picture , * picture2 , * pict ;
AVPicture picture_tmp1 , picture_tmp2 ;
AVPicture * picture , * pict ;
AVPicture picture_tmp1 ;
static UINT8 * video_buffer ;
UINT8 * buf = NULL , * buf1 = NULL ;
AVCodecContext * enc , * dec ;
@ -496,8 +537,18 @@ static void do_video_out(AVFormatContext *s,
else if ( av_delay > AV_DELAY_MAX )
nb_frames = 0 ;
}
} else {
double vdelta ;
if ( ost - > sync_ipts ! = AV_NOPTS_VALUE ) {
vdelta = ( double ) ( ost - > st - > pts . val ) * s - > pts_num / s - > pts_den - ost - > sync_ipts ;
if ( vdelta < - AV_DELAY_MAX )
nb_frames = 2 ;
else if ( vdelta > AV_DELAY_MAX )
nb_frames = 0 ;
//printf("vdelta=%f\n", vdelta);
}
}
/* XXX: also handle frame rate conversion */
if ( nb_frames < = 0 )
return ;
@ -506,30 +557,6 @@ static void do_video_out(AVFormatContext *s,
if ( ! video_buffer )
return ;
/* deinterlace : must be done before any resize */
if ( do_deinterlace ) {
int size ;
/* create temporary picture */
size = avpicture_get_size ( dec - > pix_fmt , dec - > width , dec - > height ) ;
buf1 = av_malloc ( size ) ;
if ( ! buf1 )
return ;
picture2 = & picture_tmp2 ;
avpicture_fill ( picture2 , buf1 , dec - > pix_fmt , dec - > width , dec - > height ) ;
if ( avpicture_deinterlace ( picture2 , picture1 ,
dec - > pix_fmt , dec - > width , dec - > height ) < 0 ) {
/* if error, do not deinterlace */
av_free ( buf1 ) ;
buf1 = NULL ;
picture2 = picture1 ;
}
} else {
picture2 = picture1 ;
}
/* convert pixel format if needed */
if ( enc - > pix_fmt ! = dec - > pix_fmt ) {
int size ;
@ -543,13 +570,13 @@ static void do_video_out(AVFormatContext *s,
avpicture_fill ( pict , buf , enc - > pix_fmt , dec - > width , dec - > height ) ;
if ( img_convert ( pict , enc - > pix_fmt ,
picture2 , dec - > pix_fmt ,
picture1 , dec - > pix_fmt ,
dec - > width , dec - > height ) < 0 ) {
fprintf ( stderr , " pixel format conversion not handled \n " ) ;
goto the_end ;
}
} else {
pict = picture2 ;
pict = picture1 ;
}
/* XXX: resampling could be done before raw format convertion in
@ -690,6 +717,10 @@ void print_report(AVFormatContext **output_files,
ost = ost_table [ i ] ;
os = output_files [ ost - > file_index ] ;
enc = & ost - > st - > codec ;
if ( vid & & enc - > codec_type = = CODEC_TYPE_VIDEO ) {
sprintf ( buf + strlen ( buf ) , " q=%2d " ,
enc - > quality ) ;
}
if ( ! vid & & enc - > codec_type = = CODEC_TYPE_VIDEO ) {
frame_number = ost - > frame_number ;
sprintf ( buf + strlen ( buf ) , " frame=%5d q=%2d " ,
@ -1019,8 +1050,8 @@ static int av_encode(AVFormatContext **output_files,
AVCodec * codec ;
codec = avcodec_find_decoder ( ist - > st - > codec . codec_id ) ;
if ( ! codec ) {
fprintf ( stderr , " Unsupported codec for input stream #%d.%d \n " ,
ist - > file_index , ist - > index ) ;
fprintf ( stderr , " Unsupported codec (id=%d) for input stream #%d.%d \n " ,
ist - > st - > codec . codec_id , ist - > file_index , ist - > index ) ;
exit ( 1 ) ;
}
if ( avcodec_open ( & ist - > st - > codec , codec ) < 0 ) {
@ -1075,6 +1106,7 @@ static int av_encode(AVFormatContext **output_files,
int data_size , got_picture ;
AVPicture picture ;
short samples [ AVCODEC_MAX_AUDIO_FRAME_SIZE / 2 ] ;
void * buffer_to_free ;
double pts_min ;
redo :
@ -1221,6 +1253,11 @@ static int av_encode(AVFormatContext **output_files,
ptr + = ret ;
len - = ret ;
buffer_to_free = 0 ;
if ( ist - > st - > codec . codec_type = = CODEC_TYPE_VIDEO ) {
pre_process_video_frame ( ist , & picture , & buffer_to_free ) ;
}
ist - > frame_decoded = 1 ;
#if 0
@ -1257,6 +1294,9 @@ static int av_encode(AVFormatContext **output_files,
/* 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", ipts, ost->sync_ipts, ost->sync_opts, ost->st->pts.val, pkt.pts);
} else {
//printf("pts.val=%lld\n", ost->st->pts.val);
}
if ( ost - > encoding_needed ) {
@ -1296,6 +1336,7 @@ static int av_encode(AVFormatContext **output_files,
}
}
}
av_free ( buffer_to_free ) ;
ipts = AV_NOPTS_VALUE ;
}
discard_packet :
@ -1719,6 +1760,25 @@ void opt_audio_codec(const char *arg)
}
}
void add_frame_hooker ( const char * arg )
{
int argc = 0 ;
char * argv [ 64 ] ;
int i ;
char * args = strdup ( arg ) ;
argv [ 0 ] = strtok ( args , " " ) ;
while ( argc < 62 & & ( argv [ + + argc ] = strtok ( NULL , " " ) ) ) {
}
i = frame_hook_add ( argc , argv ) ;
if ( i ! = 0 ) {
fprintf ( stderr , " Failed to add video hook function: %s \n " , arg ) ;
exit ( 1 ) ;
}
}
const char * motion_str [ ] = {
" zero " ,
" full " ,
@ -2489,6 +2549,7 @@ const OptionDef options[] = {
{ " psnr " , OPT_BOOL | OPT_EXPERT , { ( void * ) & do_psnr } , " calculate PSNR of compressed frames " } ,
{ " vstats " , OPT_BOOL | OPT_EXPERT , { ( void * ) & do_vstats } , " dump video coding statistics to file " } ,
{ " bitexact " , OPT_EXPERT , { ( void * ) opt_bitexact } , " only use bit exact algorithms (for codec testing) " } ,
{ " vhook " , HAS_ARG | OPT_EXPERT , { ( void * ) add_frame_hooker } , " insert video processing module " , " module name and parameters " } ,
{ NULL , } ,
} ;
@ -2526,8 +2587,13 @@ int main(int argc, char **argv)
exit ( 1 ) ;
}
arg = NULL ;
if ( po - > flags & HAS_ARG )
if ( po - > flags & HAS_ARG ) {
arg = argv [ optindex + + ] ;
if ( ! arg ) {
fprintf ( stderr , " %s: missing argument for option '%s' \n " , argv [ 0 ] , opt ) ;
exit ( 1 ) ;
}
}
if ( po - > flags & OPT_STRING ) {
char * str ;
str = strdup ( arg ) ;