解码的H.264提供不同的帧和上下文大小

时间:2015-08-27 14:27:42

标签: ffmpeg h.264 avcodec

我们使用avcodec解码H.264,在某些情况下,在更改分辨率后,avcodec会混淆,并为解码帧提供两种不同的大小:

if (av_init_packet_dll)
    av_init_packet_dll(&avpkt);

avpkt.data  = pBuffer;
avpkt.size  = lBuffer;

//  Make sure the output frame has NULLs for the data lines
pAVFrame->data[0]   = NULL;
pAVFrame->data[1]   = NULL;
pAVFrame->data[2]   = NULL;
pAVFrame->data[3]   = NULL;

res = avcodec_decode_video2_dll(pCodecCtx, pAVFrame, &FrameFinished, &avpkt);

DEBUG_LOG("Decoded frame: %d, %d, resulting dimensions: context: %dx%d, frame: %dx%d\n", res, FrameFinished, pCodecCtx->width, pCodecCtx->height, pAVFrame->width, pAVFrame->height);

if (pCodecCtx->width != pAVFrame->width || pCodecCtx->height != pAVFrame->height) {
    OutputDebugStringA("Size mismatch, ignoring frame!\n");
    FrameFinished = 0;
}

if (FrameFinished == 0)
    OutputDebugStringA("Unfinished frame\n");

这导致此日志(带有一些周围的行):

[5392] Decoded frame: 18690, 1, resulting dimensions: context: 640x480, frame: 640x480
[5392] Set dimensions to 640x480 in DecodeFromMap
[5392] checking size 640x480 against 640x480
[5392] Drawing 640x480, 640x480, 640x480, 0x05DB0060, 0x05DFB5C0, 0x05E0E360, 0x280, to surface 0x03198100, 1280x800
[5392] Drawing 640x480, 640x480, 640x480, 0x05DB0060, 0x05DFB5C0, 0x05E0E360, 0x280, to surface 0x03198100, 1280x800
[5392] Delayed frames seen. Reenabling low delay requires a codec flush.
[5392] Reinit context to 1280x800, pix_fmt: yuvj420p
*[5392] Decoded frame: 54363, 1, resulting dimensions: context: 1280x800, frame: 640x480
[5392] Set dimensions to 1280x800 in DecodeFromMap
[5392] checking size 1280x800 against 640x480
[5392] Found adapter NVIDIA GeForce GTX 650 ({D7B71E3E-4C86-11CF-4E68-7E291CC2C435}) on monitor 00020003
[5392] Found adapter NVIDIA GeForce GTX 650 ({D7B71E3E-4C86-11CF-4E68-7E291CC2C435}) on monitor FA650589
[5392] Creating Direct3D interface on adapter 1 at 1280x800 window 0015050C
[5392] Direct3D created using hardware vertex processing on HAL.
[5392] Creating D3D surface of 1280x800
[5392] Result 0x00000000, got surface 0x03210C40
[5392] Drawing 1280x800, 1280x800, 640x480, 0x02E3B0A0, 0x02E86600, 0x02E993A0, 0x280, to surface 0x03210C40, 1280x800

此中断的行标有*pAVFrame包含旧框架尺寸,而pCodecCtx包含新尺寸。当绘图代码尝试以1280x800图像的形式访问数据时,它会触发访问冲突。

当缩小尺寸时,avcodec会正确转换,并将FrameFinished设置为0并将pAVFrame分辨率保留为0x0。

任何人都可以想到造成这种情况的原因,为什么avcodec报告成功,但没有做任何事情,以及我能做些什么来正确解决这个问题?

目前,不匹配检查正在防范这种情况。

使用的avcodec是由Zeranoe的git-5cba529构建的。

FFmpeg version: 2015-03-31 git-5cba529
  libavutil      54. 21.100 / 54. 21.100
  libavcodec     56. 32.100 / 56. 32.100

1 个答案:

答案 0 :(得分:1)

AVCodecContext.width / height不保证与AVFrame.width / height相同。出于任何实际目的,请使用AVFrame.width / height。

AVCodecContext.width / height是解码器当前状态的大小,可以是返回给用户的AVFrame之前几帧。示例:假设您在任何MPEG样式编解码器中都有IBPBP显示序列,编码为IPBPB。我们假设存在可伸缩性,因此每个帧具有不同的大小。消耗P时,它尚未返回,但返回的是较早的帧。在该示例中,当P1被解码时,不返回任何内容,当B1被解码时,它被返回(在P1之前),并且当P2被解码时,返回P1。如果每个P具有不同的大小,这意味着当您解码P2时,P1将返回给用户,因此AVCodecContext.w / h和AVFrame.w / h是不同的(因为一个反映P2,而另一个反映P1 )。发生这种情况的另一个例子是启用了帧级多线程。

在所有情况下,依赖AVFrame.width / height,并忽略AVCodecContext.width / height。