0

H.264 をデコードするために avcodec を使用しています。状況によっては、解像度を変更した後、avcodec が混乱し、デコードされたフレームに 2 つの異なるサイズが表示されます。

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 は正しく遷移し、FrameFinished0 に設定され、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
4

1 に答える 1

1

AVCodecContext.width/height は、AVFrame.width/height と同一であるとは限りません。実際には、AVFrame.width/height を使用してください。

AVCodecContext.width/height は、デコーダーの現在の状態のサイズであり、AVFrame がユーザーに返される数フレーム前になる場合があります。例: IPBPB としてコード化された MPEG スタイルのコーデックで IBPBP の表示シーケンスがあると仮定しましょう。スケーラビリティがあったと仮定して、各フレームのサイズが異なります。P が消費されると、まだ返されませんが、代わりに以前のフレームが返されます。この例では、P1 がデコードされた場合は何も返されず、B1 がデコードされた場合は (P1 の前に) B1 が返され、P2 がデコードされた場合は P1 が返されます。各 P のサイズが異なる場合、これは、P2 をデコードしているときに P1 がユーザーに返され、AVCodecContext.w/h と AVFrame.w/h が異なることを意味します (一方は P2 を反映し、他方は P1 を反映するため)。 )。

すべての場合において、AVFrame.width/height に依存し、AVCodecContext.width/height を無視します。

于 2015-08-28T13:37:33.867 に答える