В сообщении от Monday 04 November 2019 14:22:32 Boris написал(а):
> Le lun. 4 nov. 2019 à 11:47, Andrew Randrianasulu <[email protected]>
> 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
> > [email protected]
> > https://ffmpeg.org/mailman/listinfo/libav-user
> >
> > To unsubscribe, visit link above, or email
> > [email protected] 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
[email protected]
https://ffmpeg.org/mailman/listinfo/libav-user

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

Reply via email to