[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