[FFmpeg-user] Transcode with the some properties

Boris ndjoreboris at gmail.com
Mon Nov 4 11:29:10 EET 2019


Hello,
I want to transcode video with exactly the same properties of the input
video in the output video.
I use the transcoding.cc code. In the static int open_output_file(const
char *filename) function, I set  encoder parameters like this :

if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO)
                        {
                                enc_ctx->height = dec_ctx->height;
                                enc_ctx->width = dec_ctx->width;
                                enc_ctx->sample_aspect_ratio =
dec_ctx->sample_aspect_ratio;

enc_ctx->global_quality=dec_ctx->global_quality;
                                enc_ctx->gop_size=dec_ctx->gop_size;
                                enc_ctx->bit_rate=dec_ctx->bit_rate;
                                enc_ctx->time_base=dec_ctx->time_base;
                                enc_ctx->delay=dec_ctx->delay;

//**********************************************
                                enc_ctx->rc_max_rate=dec_ctx->rc_max_rate;
                                enc_ctx->rc_min_rate=dec_ctx->rc_min_rate;
                                /* take first format from list of supported
formats */
                                if (encoder->pix_fmts)
                                {
                                        enc_ctx->pix_fmt =
encoder->pix_fmts[0];
                                }
                                else
                                {
                                        enc_ctx->pix_fmt = dec_ctx->pix_fmt;
                                }
                                // video time_base can be set to whatever
is handy and supported by encoder
                                // enc_ctx->time_base =
av_inv_q(dec_ctx->framerate);
                        }
                        else
                        {
                                enc_ctx->sample_rate = dec_ctx->sample_rate;
                                enc_ctx->channel_layout =
dec_ctx->channel_layout;
                                enc_ctx->channels =
av_get_channel_layout_nb_channels(enc_ctx->channel_layout);
                                /* take first format from list of supported
formats */
                                enc_ctx->sample_fmt =
encoder->sample_fmts[0];
                                enc_ctx->time_base = (AVRational){1,
enc_ctx->sample_rate};
                        }
                        /* Third parameter can be used to pass settings to
encoder */
                        ret = avcodec_open2(enc_ctx, encoder, NULL);
                        if (ret < 0)
                        {
                                av_log(NULL, AV_LOG_ERROR, "Cannot open
video encoder for stream #%u\n", i);
                                return ret;
                        }
                        ret =
avcodec_parameters_from_context(out_stream->codecpar, enc_ctx);
                        if (ret < 0)
                        {
                                av_log(NULL, AV_LOG_ERROR, "Failed to copy
encoder parameters to output stream #%u\n", i);
                                return ret;
                        }
                        if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
                                enc_ctx->flags |=
AV_CODEC_FLAG_GLOBAL_HEADER;

                        out_stream->time_base = enc_ctx->time_base;


But when I run exiftool on output  video and on input video, some values
like video duration, encoder, bit rate,  are differente.
Can someone tells me how can I do to keep the same parameters (metada) of
the input video in the output video, please?

The entire open_output_file function is the following :

static int open_output_file(const char *filename)
{
         AVStream *out_stream;
        AVStream *in_stream;
        AVCodecContext *dec_ctx, *enc_ctx;
        AVCodec *encoder;
        int ret;
        unsigned int i;
        ofmt_ctx = NULL;
        avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, filename);
        if (!ofmt_ctx)
        {
                av_log(NULL, AV_LOG_ERROR, "Could not create output
context\n");
                return AVERROR_UNKNOWN;
        }

        for (i = 0; i < ifmt_ctx->nb_streams; i++)
        {
                out_stream = avformat_new_stream(ofmt_ctx, NULL);
                if (!out_stream)
                {
                        av_log(NULL, AV_LOG_ERROR, "Failed allocating
output stream\n");
                        return AVERROR_UNKNOWN;
                }

                in_stream = ifmt_ctx->streams[i];
                dec_ctx = stream_ctx[i].dec_ctx;

                if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO ||
dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO)
                {
                        //AVCodecID codec_id = dec_ctx->codec_type ==
AVMEDIA_TYPE_VIDEO ? AV_CODEC_ID_MPEG4:dec_ctx->codec_id;
                        /* in this example, we choose transcoding to same
codec */
                        //encoder = dec_ctx->codec_type ==
AVMEDIA_TYPE_VIDEO ?
avcodec_find_encoder(AV_CODEC_ID_H264):avcodec_find_encoder(dec_ctx->codec_id);//(AV_CODEC_ID_MPEG4):avcodec_find_encoder(dec_ctx->codec_id);
                        encoder = dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO
?
avcodec_find_encoder(AV_CODEC_ID_MPEG4):avcodec_find_encoder(dec_ctx->codec_id);
                        // if(dec_ctx->codec_type ==
AVMEDIA_TYPE_VIDEO){encoder=avcodec_find_encoder(AV_CODEC_ID_MPEG4);}else{encoder=avcodec_find_encoder(dec_ctx->codec_id);}
                        //encoder = avcodec_find_encoder(dec_ctx->codec_id);
                        if (!encoder)
                        {
                                av_log(NULL, AV_LOG_FATAL, "Necessary
encoder not found\n");
                                return AVERROR_INVALIDDATA;
                        }
                        enc_ctx = avcodec_alloc_context3(encoder);
                        if (!enc_ctx)
                        {
                                av_log(NULL, AV_LOG_FATAL, "Failed to
allocate the encoder context\n");
                                return AVERROR(ENOMEM);
 }

                        /* In this example, we transcode to same properties
(picture size,
                        * sample rate etc.). These properties can be
changed for output
                        * streams easily using filters */
                        if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO)
                        {
                                enc_ctx->height = dec_ctx->height;
                                enc_ctx->width = dec_ctx->width;
                                enc_ctx->sample_aspect_ratio =
dec_ctx->sample_aspect_ratio;

enc_ctx->global_quality=dec_ctx->global_quality;
                                enc_ctx->gop_size=dec_ctx->gop_size;
                                enc_ctx->bit_rate=dec_ctx->bit_rate;
                                enc_ctx->time_base=dec_ctx->time_base;
                                enc_ctx->delay=dec_ctx->delay;

//**********************************************
                                enc_ctx->rc_max_rate=dec_ctx->rc_max_rate;
                                enc_ctx->rc_min_rate=dec_ctx->rc_min_rate;
                                /* take first format from list of supported
formats */
                                if (encoder->pix_fmts)
                                {
                                        enc_ctx->pix_fmt =
encoder->pix_fmts[0];
                                }
                                else
                                {
                                        enc_ctx->pix_fmt = dec_ctx->pix_fmt;
                                }
                                // video time_base can be set to whatever
is handy and supported by encoder
                                // enc_ctx->time_base =
av_inv_q(dec_ctx->framerate);
                        }
                        else
                        {
                                enc_ctx->sample_rate = dec_ctx->sample_rate;
                                enc_ctx->channel_layout =
dec_ctx->channel_layout;
                                enc_ctx->channels =
av_get_channel_layout_nb_channels(enc_ctx->channel_layout);
                                /* take first format from list of supported
formats */
                                enc_ctx->sample_fmt =
encoder->sample_fmts[0];
                                enc_ctx->time_base = (AVRational){1,
enc_ctx->sample_rate};
                        }
                        /* Third parameter can be used to pass settings to
encoder */
                        ret = avcodec_open2(enc_ctx, encoder, NULL);
                        if (ret < 0)
                        {
                                av_log(NULL, AV_LOG_ERROR, "Cannot open
video encoder for stream #%u\n", i);
                                return ret;
                        }
                        ret =
avcodec_parameters_from_context(out_stream->codecpar, enc_ctx);
                        if (ret < 0)
                        {
                                av_log(NULL, AV_LOG_ERROR, "Failed to copy
encoder parameters to output stream #%u\n", i);
                                return ret;
                        }
                        if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
 enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;

                        out_stream->time_base = enc_ctx->time_base;
                        stream_ctx[i].enc_ctx = enc_ctx;
                }
                else if (dec_ctx->codec_type == AVMEDIA_TYPE_UNKNOWN)
                {
                        av_log(NULL, AV_LOG_FATAL, "Elementary stream #%d
is of unknown type, cannot proceed\n", i);
                        return AVERROR_INVALIDDATA;
                }
                else
                {
                        // if this stream must be remuxed
                        ret = avcodec_parameters_copy(out_stream->codecpar,
in_stream->codecpar);
                        //ifmt_ctx->streams[i]->codec);
                        if (ret < 0)
                        {
                                av_log(NULL, AV_LOG_ERROR, "Copying
parameters for stream #%u failed\n", i);
                                return ret;
                        }
                        out_stream->time_base = in_stream->time_base;
                }

        }
        av_dump_format(ofmt_ctx, 0, filename, 1);

        if (!(ofmt_ctx->oformat->flags & AVFMT_NOFILE))
        {
                ret = avio_open(&ofmt_ctx->pb, filename, AVIO_FLAG_WRITE);
                if (ret < 0)
                {
                        av_log(NULL, AV_LOG_ERROR, "Could not open output
file '%s'", filename);
                        return ret;
                }
        }

        /* init muxer, write output file header */
        ret = avformat_write_header(ofmt_ctx, NULL);
        if (ret < 0)
        {
                av_log(NULL, AV_LOG_ERROR, "Error occurred when opening
output file\n");
                return ret;
        }
        return 0;
}

Rgards


More information about the ffmpeg-user mailing list