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

Reply via email to