Hello,
I am comparing MPEG-2 encoding speed of ffmpeg and a very simple test
program that only sets options and calls avcodec_encode_video(...) per
each frame.
I am constantly seeing ffmpeg encoding twice faster than mine.
E.g. when I am encoding a 1080p test sequence, I am getting 70 fps
fps encoding speed with ffmpeg and only 33 fps with the test program
with CBR settings.
The settings in this case are: b=16M maxrate=16M minrate=16M
bufsize=4M g=16 bf=2 threads=6 bt=1M
If I reduce these to b=16M g=16 bf=2 threads=6, I get about 90 fps
with both ffmpeg and the test program.
Has anyone seen smth like this?
Any suggestions on getting similar performance?
Thanks!
Alex.
====
Here is the test program:
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <libavcodec/opt.h>
#include <libavutil/log.h>
#include "avcodec.h"
typedef struct
{
int width;
int height;
int colorspace;
char* input_filename;
FILE* infile;
char* output_filename;
FILE* outfile;
} confopts_t;
static struct option long_options[] =
{
{ "size", required_argument, NULL, 's'},
{ "ffmpeg-arg", required_argument, NULL, 'a'},
{ "fps", required_argument, NULL, 'f'},
{ "input_filename", required_argument, NULL, 'i'},
{ "output_filename", required_argument, NULL, 'o'},
{ "interlaced", optional_argument, NULL, 0x81},
{ "help", no_argument, NULL, 'h'},
};
const char* default_out_file = "yuv_enc_output.mpg";
int interlaced = 0;
confopts_t* _process_command_line(int argc, char** argv , AVCodecContext *cnx);
int main (int argc, char** argv)
{
AVCodec* codec;
AVCodecContext* cnx;
uint8_t* output_buf;
uint8_t* yuv_frame;
int frame_count = 0;
int yuv_frame_size, w_times_h, output_buf_size, num_read, res;
AVFrame* picture;
// Initialize LAVC & set up codec context
avcodec_init();
avcodec_register_all();
codec = avcodec_find_encoder(CODEC_ID_MPEG2VIDEO);
if ( codec == NULL )
{
printf("avcodec: encoder init failed\n");
exit(1);
}
cnx = avcodec_alloc_context2(CODEC_TYPE_VIDEO);
confopts_t* copts = _process_command_line(argc, argv, cnx);
printf("width = %d \n", copts->width);
printf("height = %d \n", copts->height);
printf("file = %s \n", copts->input_filename);
w_times_h = copts->width * copts->height;
yuv_frame_size = (int)(w_times_h * 1.5); // we assume colorspace
is 4:2:0, hence 3/2 = 1.5
output_buf_size = w_times_h;
if ( avcodec_open(cnx, codec) < 0 )
{
printf("could not open codec\n");
exit(1);
}
while ( 1 )
{
yuv_frame = (uint8_t*)malloc(yuv_frame_size);
output_buf = (uint8_t*)malloc(output_buf_size);
//read yuv_frame_size bytes from input file into yuv_buf
num_read = fread(yuv_frame, sizeof(char), yuv_frame_size,
copts->infile);
if ( num_read != yuv_frame_size )
{
//done, eof
//printf("num_read = %d\n", num_read);
break;
}
//create the AVFrame from yuv_frame
picture = avcodec_alloc_frame();
picture->data[0] = yuv_frame;
picture->data[1] = picture->data[0] + w_times_h;
picture->data[2] = picture->data[1] + w_times_h / 4;
picture->linesize[0] = copts->width;
picture->linesize[1] = copts->width / 2;
picture->linesize[2] = copts->width / 2;
picture->interlaced_frame = interlaced;
res = avcodec_encode_video(cnx, output_buf, output_buf_size, picture);
if ( res == -1 )
{
printf("avcodec returned -1: video encoding failure\n");
exit( 1 );
}
else
{
if ( res > 0 )
{
printf("encoded frame %3d (size=%5d)\n", ++frame_count, res);
fwrite(output_buf, 1, res, copts->outfile );
}
}
av_free(picture);
av_free(output_buf);
av_free(yuv_frame);
}
/* get delayed frames */
output_buf = (uint8_t*)malloc(output_buf_size);
res = avcodec_encode_video(cnx, output_buf, output_buf_size, NULL);
while ( 1 )
{
res = avcodec_encode_video(cnx, output_buf, output_buf_size,
NULL);
if ( res > 0 )
{
printf("encoded frame %3d (size=%5d)\n", ++frame_count, res);
fwrite(output_buf, 1, res, copts->outfile);
}
else
{
break;
}
}
av_free(output_buf);
/* add sequence end code */
uint8_t tempbuf[4];
tempbuf[0] = 0x00;
tempbuf[1] = 0x00;
tempbuf[2] = 0x01;
tempbuf[3] = 0xb7;
fwrite(tempbuf, 1, 4, copts->outfile );
fclose( copts->infile );
fclose( copts->outfile );
printf("frame count = %d\n", frame_count );
return 0;
}
confopts_t* _process_command_line(int argc, char** argv, AVCodecContext *cnx)
{
int c;
const AVOption *opt;
const AVOption *new_opt;
cnx->time_base.num = 0;
cnx->time_base.den = 0;
cnx->pix_fmt = PIX_FMT_YUV420P;
cnx->thread_count = 1;
confopts_t* config = (confopts_t*)calloc(1,sizeof(confopts_t));
while ( 1 )
{
int long_options_index;
c = getopt_long( argc, argv, "s:a:i:o:f:h", long_options,
&long_options_index);
if ( c == -1 )
{
break;
}
switch ( c )
{
case 'i':
config->input_filename = strndup(optarg, 0x400);
break;
case 'o':
config->output_filename = strndup(optarg, 0x400);
break;
case 's':
sscanf( optarg, "%dx%d", &config->width, &config->height );
if ( ( config->width < 128 ) || ( config->width > 7680)
|| ( config->height < 96 ) || ( config->height > 4800 ) )
{
printf( "resolution %dx%d is not supported\n",
config->width, config->height);
exit( 1 );
}
cnx->width = config->width;
cnx->height = config->height;
break;
case 'f':
sscanf( optarg, "%d/%d", &cnx->time_base.den,
&cnx->time_base.num );
if ( cnx->time_base.num <= 0 ) cnx->time_base.num = 1;
printf( "frame rate %d/%d selected\n",
cnx->time_base.den, cnx->time_base.num );
if ( cnx->time_base.den <= 0 ) exit( 1 );
break;
case 'a':
{
char* option = strndupa( optarg, 0x80 );
char* key = option;
char* val = strchr( option, '=' );
*val = 0;
val++;
new_opt = av_find_opt(cnx, key, NULL,
AV_OPT_FLAG_VIDEO_PARAM, AV_OPT_FLAG_VIDEO_PARAM);
if ( new_opt != NULL )
{
if ( av_set_string3(cnx, key, val, 0, &opt) >= 0 )
{
printf("ffmpeg: %s => %s)\n",key, val);
break;
}
printf("parameter setting unsuccessful (param:
%s value: %s)\n",key, val);
}
else
{
printf("couldn't find parameter (param: %s
value: %s)\n",key, val);
}
}
break;
case 0x81:
printf("interlaced source\n");
interlaced = 1;
break;
case 'h':
default:
printf( "%s: -s size -i <infile> -o <outfile> -s
<size> -f <fps> -a < <ffmpeg option]>=<value> >\n", argv[0] );
exit( 1 );
}
}
if ( cnx->thread_count > 1 ) avcodec_thread_init(cnx, cnx->thread_count);
if ( ( config->infile = fopen(config->input_filename, "r") ) == NULL )
{
printf("error: no input \n");
exit(1);
}
if ( config->output_filename == NULL ) config->output_filename =
strdup(default_out_file);
if ( (config->outfile = fopen(config->output_filename, "w")) == NULL )
{
printf("error: cannot open file %s\n", optarg);
exit(1);
}
return config;
}
_______________________________________________
libav-user mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/libav-user