我们使用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-5 use 529建造的。
FFmpeg version: 2015-03-31 git-5cba529
libavutil 54. 21.100 / 54. 21.100
libavcodec 56. 32.100 / 56. 32.100发布于 2015-08-28 13:37:33
宽度/高度不能保证与AVFrame.Width/高度相同。对于任何实际用途,请使用AVFrame.width.宽度/高度。
宽度/高度是解码器当前状态的大小,它可能是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。
https://stackoverflow.com/questions/32252118
复制相似问题