次のようなワークフローがあります。
- 生の YUV フレームを取得します。
- Windows Media Foundation に渡して、H.264 フレームにエンコードします。
- 出力を FFmpeg AVPacket に変換します。
- av_interleaved_write_frame を含むパケットを、他のものと混合された出力ファイルに挿入します。
Windows 7では、これはうまく機能しました。Windows 8 では、av_interleaved_write_frame が壊れていました。この理由は、Windows 8 が出力に B フレームを導入したためです。これは、pts/dts をどのように設定しても、av_interleaved_write_frame が気に入らなかったためです。
0 B フレームを使用するようにエンコーダーを変更したところ、必要な出力が得られました。しかし...
エンコードされたフレームの約 10 ~ 15 秒後、ビデオはほぼ完全なものから非常にブロック状で非常に低いフレーム レートに劣化します。Windows 8 で利用可能なほとんどの設定を変更してエンコーダーを変更しようとしましたが、何も役に立たないようです。
影響を与えた唯一のことは、エンコーダーのビットレートを変更することでした. エンコーダーのビットレートを上げれば上げるほど、ビデオが劣化し始めるまでの時間が長くなります。
Windows 7 と Windows 8 の間で何が変更され、これが発生した可能性があるかについてのアイデアはありますか?
エンコーダーのセットアップから成功チェックを差し引いたもの (すべて成功)
IMFMediaType * mInputType = NULL;
MFCreateMediaType(&mOutputType);
mOutputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
mOutputType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264);
mOutputType->SetUINT32(MF_MT_AVG_BITRATE, 10000000);
MFSetAttributeSize(mOutputType, MF_MT_FRAME_SIZE, frameWidth, frameHeight);
MFSetAttributeSize(mOutputType, MF_MT_FRAME_RATE, 30, 1);
MFSetAttributeSize(mOutputType, MF_MT_FRAME_RATE_RANGE_MAX, 30, 1);
MFSetAttributeSize(mOutputType, MF_MT_FRAME_RATE_RANGE_MIN, 15, 1);
mOutputType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
mOutputType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1);
mOutputType->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, 1);
mOutputType->SetUINT32(MF_MT_SAMPLE_SIZE, frameWidth * frameHeight * 2);
mOutputType->SetUINT32(MF_MT_MPEG2_PROFILE, eAVEncH264VProfile_Main);
mOutputType->SetUINT32(CODECAPI_AVEncCommonRateControlMode, eAVEncCommonRateControlMode_Quality);
mOutputType->SetUINT32(CODECAPI_AVEncCommonQuality, 80);
フレームのエンコードは基本的に次のとおりです。
- 受信 YUV データを格納するための MFCreateMemoryBuffer。
- MFCreateSample.
- バッファーをサンプルにアタッチします。
- サンプル時間と期間を設定します。
- プロセス入力
- 適切な出力サイズの ProcessOutput
- 成功したら、サンプルの情報を使用して AVPacket をビルドします