Re: Transcode with the some properties

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Re: Transcode with the some properties

Andrew Randrianasulu
В сообщении от Monday 04 November 2019 12:29:10 Boris написал(а):

> 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.

Hm, video duration chnage sounds like most unwelcome one ...
But are codec parameters even supposed to be the same after different encoder run over output of another encoder?
I recall term 'bit exact', but is this applicable to re-encoding with lossy codecs?


> 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
>


_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
Reply | Threaded
Open this post in threaded view
|

Re: Transcode with the some properties

Boris


Le lun. 4 nov. 2019 à 11:47, Andrew Randrianasulu <[hidden email]> a écrit :
В сообщении от Monday 04 November 2019 12:29:10 Boris написал(а):
> 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.

Hm, video duration chnage sounds like most unwelcome one ...
But are codec parameters even supposed to be the same after different encoder run over output of another encoder?  
I recall term 'bit exact', but is this applicable to re-encoding with lossy codecs?

I'm not sure but I thought it could be done. If you have things that I do not know, do not hesitate to share them with me,please.

Regards
 
Hello 
> 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
>


_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".

_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
Reply | Threaded
Open this post in threaded view
|

Re: Transcode with the some properties

Andrew Randrianasulu
В сообщении от Monday 04 November 2019 14:22:32 Boris написал(а):

> Le lun. 4 nov. 2019 à 11:47, Andrew Randrianasulu <[hidden email]>
> a écrit :
>
> > В сообщении от Monday 04 November 2019 12:29:10 Boris написал(а):
> > > 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.
> >
> > Hm, video duration chnage sounds like most unwelcome one ...
> > But are codec parameters even supposed to be the same after different
> > encoder run over output of another encoder?
>
> I recall term 'bit exact', but is this applicable to re-encoding with lossy
> > codecs?
> >
>
> I'm not sure but I thought it could be done. If you have things that I do
> not know, do not hesitate to share them with me,please.

Well, my thinking is extremely generic and might be incorrect.

But codecs usually analyze input video so they  can arrange keyframes and various types of macroblocs optimally (as far as their logic allow them).
So, while if two different codecs run over same uncompressed  video/set of images
should produce same bitsream - small artefacts from first (lossy) codec run will change behavior of second codec in chain, i think...

because codecs just do math over number of pixels, and while number of pixels will remain the same - their exact values will be slightly off after first encoding ...

May be things like ffv1 can be used without any real mathematical degradation of video, but then re-encoding basically lost any sense ...?

>
> Regards
>
> Hello
>
> > > 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
> > >
> >
> >
> > _______________________________________________
> > Libav-user mailing list
> > [hidden email]
> > https://ffmpeg.org/mailman/listinfo/libav-user
> >
> > To unsubscribe, visit link above, or email
> > [hidden email] with subject "unsubscribe".
>


_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
Reply | Threaded
Open this post in threaded view
|

Re: Transcode with the some properties

Andrew Randrianasulu
In reply to this post by Boris
В сообщении от Monday 04 November 2019 14:22:32 Boris написал(а):

> Le lun. 4 nov. 2019 à 11:47, Andrew Randrianasulu <[hidden email]>
> a écrit :
>
> > В сообщении от Monday 04 November 2019 12:29:10 Boris написал(а):
> > > 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.
> >
> > Hm, video duration chnage sounds like most unwelcome one ...
> > But are codec parameters even supposed to be the same after different
> > encoder run over output of another encoder?
>
> I recall term 'bit exact', but is this applicable to re-encoding with lossy
> > codecs?
> >
>
> I'm not sure but I thought it could be done. If you have things that I do
> not know, do not hesitate to share them with me,please.

Addition (I have those links open, may be they will be useful here for getting bigger picture ..)

https://koushtav.me/jpeg/tutorial/c++/decoder/2019/03/02/lets-write-a-simple-jpeg-library-part-2/
https://koushtav.me//jpeg/tutorial/2017/11/25/lets-write-a-simple-jpeg-library-part-1/

basically anatomy (and logic/math) behind jpeg image compression (for video  this will be motion jpeg)

As you hopefully see - it all just run over blocks of numbers, with some throwning away (so, this is lossy codec as opposed to lossless).

After first thrown away run you will have different bunch of numbers to play with,
so even if you configure encoder to do exactly the same - input already will be different ...

mpeg1/2/4/etc all add complexity over such basic idea ....

http://basalgangster.macgui.com/RetroMacComputing/The_Long_View/Entries/2013/11/3_Warhol.html

some bit of history explainiing (hopefully) why compression was used and still used,
and not just compression but most often lossy one:

--------
 It was hard because it required very high data throughput. The way you want video is the way it is now, full screen at 24 frames per second or better. Full screen in 1987 meant 640x480 pixels. To render that size image in 24 bits-per-pixel color took over 900,000 bytes per frame. At 24 frames per second (the standard for film) this meant 22,118,400 bytes (21.09 MBytes) per second. The video had to come from your hard disk or from CDROM. There was a lot of excitement about CDROM at that time, but the CDROM drives at that time could only hold about 30 seconds of uncompressed video at that rate, and anyway, they could only transfer 150 Kbytes per second. It would take seconds to move a single frame from a CDROM into a computer's memory. Transfer rates were nominally better for hard disks, but for the most popular personal computer at the time, the IBM-AT and its clones, the hard disk could only move about 100-200 KBytes into the computer every second. This was nominally faster than a CDROM, but a far cry from what it would take to play a digital episode of The Cosby Show on your computer screen.
------end of quotation-----

There is also question of chroma (color) subsampling and color spaces ..not directly about codec, but playing their role in making image not mathematically-exact, after few transforms (usually)

>
> Regards
>
> Hello
>
> > > 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
> > >
> >
> >
> > _______________________________________________
> > Libav-user mailing list
> > [hidden email]
> > https://ffmpeg.org/mailman/listinfo/libav-user
> >
> > To unsubscribe, visit link above, or email
> > [hidden email] with subject "unsubscribe".
>


_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
Reply | Threaded
Open this post in threaded view
|

Re: Transcode with the some properties

Boris


Le lun. 4 nov. 2019 à 13:44, Andrew Randrianasulu <[hidden email]> a écrit :
В сообщении от Monday 04 November 2019 14:22:32 Boris написал(а):
> Le lun. 4 nov. 2019 à 11:47, Andrew Randrianasulu <[hidden email]>
> a écrit :
>
> > В сообщении от Monday 04 November 2019 12:29:10 Boris написал(а):
> > > 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.
> >
> > Hm, video duration chnage sounds like most unwelcome one ...
> > But are codec parameters even supposed to be the same after different
> > encoder run over output of another encoder?
>
> I recall term 'bit exact', but is this applicable to re-encoding with lossy
> > codecs?
> >
>
> I'm not sure but I thought it could be done. If you have things that I do
> not know, do not hesitate to share them with me,please.

Addition (I have those links open, may be they will be useful here for getting bigger picture ..)

https://koushtav.me/jpeg/tutorial/c++/decoder/2019/03/02/lets-write-a-simple-jpeg-library-part-2/
https://koushtav.me//jpeg/tutorial/2017/11/25/lets-write-a-simple-jpeg-library-part-1/

basically anatomy (and logic/math) behind jpeg image compression (for video  this will be motion jpeg)

As you hopefully see - it all just run over blocks of numbers, with some throwning away (so, this is lossy codec as opposed to lossless).

After first thrown away run you will have different bunch of numbers to play with,
so even if you configure encoder to do exactly the same - input already will be different ...

mpeg1/2/4/etc all add complexity over such basic idea ....

http://basalgangster.macgui.com/RetroMacComputing/The_Long_View/Entries/2013/11/3_Warhol.html

some bit of history explainiing (hopefully) why compression was used and still used,
and not just compression but most often lossy one:

--------
 It was hard because it required very high data throughput. The way you want video is the way it is now, full screen at 24 frames per second or better. Full screen in 1987 meant 640x480 pixels. To render that size image in 24 bits-per-pixel color took over 900,000 bytes per frame. At 24 frames per second (the standard for film) this meant 22,118,400 bytes (21.09 MBytes) per second. The video had to come from your hard disk or from CDROM. There was a lot of excitement about CDROM at that time, but the CDROM drives at that time could only hold about 30 seconds of uncompressed video at that rate, and anyway, they could only transfer 150 Kbytes per second. It would take seconds to move a single frame from a CDROM into a computer's memory. Transfer rates were nominally better for hard disks, but for the most popular personal computer at the time, the IBM-AT and its clones, the hard disk could only move about 100-200 KBytes into the computer every second. This was nominally faster than a CDROM, but a far cry from what it would take to play a digital episode of The Cosby Show on your computer screen.
------end of quotation-----

There is also question of chroma (color) subsampling and color spaces ..not directly about codec, but playing their role in making image not mathematically-exact, after few transforms (usually)

Thank you guys,

I will check the links and try to see deeply.

Regards 

>
> Regards
>
> Hello
>
> > > 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
> > >
> >
> >
> > _______________________________________________
> > Libav-user mailing list
> > [hidden email]
> > https://ffmpeg.org/mailman/listinfo/libav-user
> >
> > To unsubscribe, visit link above, or email
> > [hidden email] with subject "unsubscribe".
>


_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".

_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
Reply | Threaded
Open this post in threaded view
|

Re: Transcode with the some properties

Thomas Freudenreich
In reply to this post by Andrew Randrianasulu

В сообщении от Monday 04 November 2019 14:22:32 Boris написал(а):

> Le lun. 4 nov. 2019 à 11:47, Andrew Randrianasulu <[hidden email]>
> a écrit :
>
> > В сообщении от Monday 04 November 2019 12:29:10 Boris написал(а):
> > > 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.
> >
> > Hm, video duration chnage sounds like most unwelcome one ...
> > But are codec parameters even supposed to be the same after different
> > encoder run over output of another encoder?
>
> I recall term 'bit exact', but is this applicable to re-encoding with lossy
> > codecs?
> >
>
> I'm not sure but I thought it could be done. If you have things that I do
> not know, do not hesitate to share them with me,please.

Addition (I have those links open, may be they will be useful here for getting bigger picture ..)

https://koushtav.me/jpeg/tutorial/c++/decoder/2019/03/02/lets-write-a-simple-jpeg-library-part-2/
https://koushtav.me//jpeg/tutorial/2017/11/25/lets-write-a-simple-jpeg-library-part-1/

basically anatomy (and logic/math) behind jpeg image compression (for video  this will be motion jpeg)

As you hopefully see - it all just run over blocks of numbers, with some throwning away (so, this is lossy codec as opposed to lossless).

After first thrown away run you will have different bunch of numbers to play with,
so even if you configure encoder to do exactly the same - input already will be different ...

mpeg1/2/4/etc all add complexity over such basic idea ....

http://basalgangster.macgui.com/RetroMacComputing/The_Long_View/Entries/2013/11/3_Warhol.html

some bit of history explainiing (hopefully) why compression was used and still used,
and not just compression but most often lossy one:

--------
 It was hard because it required very high data throughput. The way you want video is the way it is now, full screen at 24 frames per second or better. Full screen in 1987 meant 640x480 pixels. To render that size image in 24 bits-per-pixel color took over 900,000 bytes per frame. At 24 frames per second (the standard for film) this meant 22,118,400 bytes (21.09 MBytes) per second. The video had to come from your hard disk or from CDROM. There was a lot of excitement about CDROM at that time, but the CDROM drives at that time could only hold about 30 seconds of uncompressed video at that rate, and anyway, they could only transfer 150 Kbytes per second. It would take seconds to move a single frame from a CDROM into a computer's memory. Transfer rates were nominally better for hard disks, but for the most popular personal computer at the time, the IBM-AT and its clones, the hard disk could only move about 100-200 KBytes into the computer every second. This was nominally faster than a CDROM, but a far cry from what it would take to play a digital episode of The Cosby Show on your computer screen.
------end of quotation-----

There is also question of chroma (color) subsampling and color spaces ..not directly about codec, but playing their role in making image not mathematically-exact, after few transforms (usually)

>
> Regards
>
> Hello
>
> > > 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
> > >
> >
> >
> > _______________________________________________
> > Libav-user mailing list
> > [hidden email]
> > https://ffmpeg.org/mailman/listinfo/libav-user
> >
> > To unsubscribe, visit link above, or email
> > [hidden email] with subject "unsubscribe".
>

I'm not an expert in that but I guess also if you use multithreading the result on the same hardware, same OS, same source material will likely not produce  bit-comparable results, because different threads work on different parts of the image/stream.

_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
Reply | Threaded
Open this post in threaded view
|

Re: Transcode with the some properties

Boris


Le lun. 4 nov. 2019 à 14:42, Thomas <[hidden email]> a écrit :

В сообщении от Monday 04 November 2019 14:22:32 Boris написал(а):
> Le lun. 4 nov. 2019 à 11:47, Andrew Randrianasulu <[hidden email]>
> a écrit :
>
> > В сообщении от Monday 04 November 2019 12:29:10 Boris написал(а):
> > > 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.
> >
> > Hm, video duration chnage sounds like most unwelcome one ...
> > But are codec parameters even supposed to be the same after different
> > encoder run over output of another encoder?
>
> I recall term 'bit exact', but is this applicable to re-encoding with lossy
> > codecs?
> >
>
> I'm not sure but I thought it could be done. If you have things that I do
> not know, do not hesitate to share them with me,please.

Addition (I have those links open, may be they will be useful here for getting bigger picture ..)

https://koushtav.me/jpeg/tutorial/c++/decoder/2019/03/02/lets-write-a-simple-jpeg-library-part-2/
https://koushtav.me//jpeg/tutorial/2017/11/25/lets-write-a-simple-jpeg-library-part-1/

basically anatomy (and logic/math) behind jpeg image compression (for video  this will be motion jpeg)

As you hopefully see - it all just run over blocks of numbers, with some throwning away (so, this is lossy codec as opposed to lossless).

After first thrown away run you will have different bunch of numbers to play with,
so even if you configure encoder to do exactly the same - input already will be different ...

mpeg1/2/4/etc all add complexity over such basic idea ....

http://basalgangster.macgui.com/RetroMacComputing/The_Long_View/Entries/2013/11/3_Warhol.html

some bit of history explainiing (hopefully) why compression was used and still used,
and not just compression but most often lossy one:

--------
 It was hard because it required very high data throughput. The way you want video is the way it is now, full screen at 24 frames per second or better. Full screen in 1987 meant 640x480 pixels. To render that size image in 24 bits-per-pixel color took over 900,000 bytes per frame. At 24 frames per second (the standard for film) this meant 22,118,400 bytes (21.09 MBytes) per second. The video had to come from your hard disk or from CDROM. There was a lot of excitement about CDROM at that time, but the CDROM drives at that time could only hold about 30 seconds of uncompressed video at that rate, and anyway, they could only transfer 150 Kbytes per second. It would take seconds to move a single frame from a CDROM into a computer's memory. Transfer rates were nominally better for hard disks, but for the most popular personal computer at the time, the IBM-AT and its clones, the hard disk could only move about 100-200 KBytes into the computer every second. This was nominally faster than a CDROM, but a far cry from what it would take to play a digital episode of The Cosby Show on your computer screen.
------end of quotation-----

There is also question of chroma (color) subsampling and color spaces ..not directly about codec, but playing their role in making image not mathematically-exact, after few transforms (usually)

>
> Regards
>
> Hello
>
> > > 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
> > >
> >
> >
> > _______________________________________________
> > Libav-user mailing list
> > [hidden email]
> > https://ffmpeg.org/mailman/listinfo/libav-user
> >
> > To unsubscribe, visit link above, or email
> > [hidden email] with subject "unsubscribe".
>

I'm not an expert in that but I guess also if you use multithreading the result on the same hardware, same OS, same source material will likely not produce  bit-comparable results, because different threads work on different parts of the image/stream.

Hello Thomas,

You are probably right but I use monothreading.

Regards
 

_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".

_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".