在视频编解码中,pts和dts是保证视频能正常播放的参数。
视频为h264编码时,当只有I和P帧时,pts和dts相同,只需要按照pts进行解码播放即可。h264的Profiles为baseline时,只有I帧和P帧。
Profiles为main以上时,包含了I,P,B帧。当存在B帧时,pts和dts可能会不同。
比如当遇到如下帧序列时:
P1 P2 P3 P4
type I B P P
pts 1 2 3 4
dts 1 4 2 3
P2解码依赖P1和P3,需要先解码P3才能解出P2。
在调用ffmpeg的libcodec库avcodec_decode_video2函数时,返回值正确,但是got_picture却始终为0,即是由于av_read_frame函数是按照pts读取解码帧,遇到如上情况找不到解码参考帧时解码失败造成的。如果不处理会造成丢帧。
解决方法:
使用skipped_frame记录解码失败帧数量(即got_picture为0的次数),然后在解码完成后加上如下代码。
for (int i = skipped_frame; i > 0; i--)
{
ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
if (got_picture) {
SaveFrameToBMP("pic.bmp", pFrameRGB->data[0], pCodecCtx->width, pCodecCtx->height, 24, index++);
}
}
注意:
时间戳将每一秒分成90000份。flv的tag中的dts单位为毫秒,即把一毫秒分成90份(dts/90);ts的时间戳单位为秒(dts/90000)。如果需要做文件格式转换需要转换时间单位。
在所有的文件封装格式(包括传输协议RTMP)中,都是按照编解码顺序dts来存储帧的。参考链接问答:http://www.cppblog.com/elva/archive/2010/06/21/118355.html