[Libav-user] Transcode with the some properties
Boris
ndjoreboris at gmail.com
Mon Nov 4 15:59:00 EET 2019
Le lun. 4 nov. 2019 à 14:42, Thomas <tfreudi1 at gmx.de> a écrit :
>
> В сообщении от Monday 04 November 2019 14:22:32 Boris написал(а):
> > Le lun. 4 nov. 2019 à 11:47, Andrew Randrianasulu <
> randrianasulu at gmail.com>
> > 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
> > > Libav-user at ffmpeg.org
> > > https://ffmpeg.org/mailman/listinfo/libav-user
> > >
> > > To unsubscribe, visit link above, or email
> > > libav-user-request at ffmpeg.org 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
> Libav-user at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/libav-user
>
> To unsubscribe, visit link above, or email
> libav-user-request at ffmpeg.org with subject "unsubscribe".
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://ffmpeg.org/pipermail/libav-user/attachments/20191104/3323548c/attachment.html>
More information about the Libav-user
mailing list