Usually before you call avcodec_encode_video2()
you set the frame's timestamp, e.g.:
gFrame->pts = gFrameIndex;
gFrameIndex
is incremented by 1 each encoded frame, which should be correct in your case because your time_base
is 1/30 and each frame represents 1/30th second duration.
Then be careful here:
if (pkt.pts != AV_NOPTS_VALUE) pkt.pts = av_rescale_q(gCodecContext->coded_frame->pts, gCodecContext->time_base, gStream->time_base);
if (pkt.dts != AV_NOPTS_VALUE) pkt.dts = av_rescale_q(gFrameIndex, gCodecContext->time_base, gStream->time_base);
Are you having problems because you are using libx264
to encode? I noticed that in that case, you have to rescale the timestamps before and after calling avcodec_encode_video2()
, e.g.:
gFrame->pts = av_rescale_q(gFrameIndex, gCodecContext->time_base, gStream->codec->time_base);
[...]
avcodec_encode_video2()
[...]
pkt.pts = av_rescale_q(pkt.pts, gStream->codec->time_base, gStream->time_base);
pkt.dts = av_rescale_q(pkt.dts, gStream->codec->time_base, gStream->time_base);
It's because the ffmpeg interface with libx264
is not of very high quality.
Is your webcam dropping frames? If so then you'll need to give the frames real timestamps. Create a function that returns the elapsed time since you started the capture in milliseconds (an integer). Then set time_base
to {1,1000}
and set gFrame->pts
to the return value of your function. But be careful: you can't have a timestamp that is <= a previous timestamp. So you will need to drop frames if you get several all at once (or write another mechanism for dealing with this situation). BTW, this is all done for you in the ffmpeg
CLI program, which is why so few people try to use ffmpeg the library ...