[Libav-user] Changing time_bases for decoder(mpeg2video) when sending packets with avcodec_send_packet().
Hristo Ivanov
hivanov.ffmailing at gmail.com
Wed May 30 11:11:08 EEST 2018
Hi,
I am writing(C++) a simple transcoding program. At first I did not
understand the concept of a timebase and how to work with it, until I found
this stackoverflow response:
https://stackoverflow.com/a/40278283/3022945
The response from the above link can be summarized as:
- Copy the timebases from one object to another (the decoders timebase
should be copied from the demuxer, and the encoders timebase should be
copied from the decoder, and so on).
- When opening thise objects they can change their timebase, so
rescaling the packet/frame timestamps is necessary.
Once I understood this two concepts well, I wrote something like this (code
example for decoder).
AVCodec* dec = avcodec_find_decoder(stream->codecpar->codec_id);
if (dec == NULL)
throw new std::exception("Error avcodec_find_decoder().");
this->codec_ctx = avcodec_alloc_context3(dec);
if (this->codec_ctx == NULL)
throw new std::exception("Error avcodec_alloc_context3().");
ret = avcodec_parameters_to_context(codec_ctx, stream->codecpar);
if (ret < 0)
throw new std::exception("Error avcodec_parameters_to_context().");
codec_ctx->time_base = stream->time_base; // Copy the time_base from the
demuxer.
if (type == AVMEDIA_TYPE_VIDEO)
codec_ctx->framerate = av_guess_frame_rate(packetReader->ifmt_ctx,
stream, NULL);
ret = avcodec_open2(codec_ctx, dec, NULL);
if (ret < 0)
throw new std::exception("Error avcodec_open2().");
hasTimebaseChanged = false;
inputTimebase = stream->time_base;
if (av_cmp_q(codec_ctx->time_base, inputTimebase) != 0)
hasTimebaseChanged = true;
As it can be seen, I have a boolean variable (hasTimebaseChanged) that
later when sending a packet to decode I use as this:
if (hasTimebaseChanged == true)
av_packet_rescale_ts(packet->packet, inputTimebase, codec_ctx->time_base);
ret = avcodec_send_packet(this->codec_ctx, packet->packet);
The idea is to avoid rescaling when not needed (trying to be more
efficient). At first, when only transcoding audio everything worked as
expected.
The problem I am facing comes when decoding video(mpeg2video):
- The timebase copied from the demuxer is 1/90000.
codec_ctx->time_base = stream->time_base; // {1, 90000}
- After opening the decoder the timebase is changed to 1/25
ret = avcodec_open2(codec_ctx, dec, NULL); // {1, 25}
- Later after sending the first packet to be decoded the timebase
changes again to 1/50
ret = avcodec_send_packet(this->codec_ctx, packet->packet); // {1,
50}
What I do not understand is why the decoder changes its timebase when the
first packet is sent.
After looking at the source code I think I have found where the timebase is
changed:
https://ffmpeg.org/doxygen/trunk/decode_8c_source.html#l00542
As it can be seen the framerate is multiplied by the ticks_per_frame and
the resulting value is set as the timebase.
My question:
Is it normal for objects to change their timebase when packets/frames are
sent, or is this some temporal bugfix which will be resolved in the future?
Thanks.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://ffmpeg.org/pipermail/libav-user/attachments/20180530/3a345780/attachment.html>
More information about the Libav-user
mailing list