Le lun. 4 nov. 2019 à 13:44, Andrew Randrianasulu <[email protected]> a écrit :
> В сообщении от 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) > 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 > > > [email protected] > > > https://ffmpeg.org/mailman/listinfo/libav-user > > > > > > To unsubscribe, visit link above, or email > > > [email protected] with subject "unsubscribe". > > > > > _______________________________________________ > 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".
_______________________________________________ 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".
