我的工作流程如下:
- 获取原始 YUV 帧。
- 将其传递给 Windows Media Foundation 以编码为 H.264 帧。
- 将输出转换为 FFmpeg AVPacket。
- 将带有 av_interleaved_write_frame 的数据包注入到与其他内容混合的输出文件中。
在 Windows 7 上,这很好用。在 Windows 8 上,av_interleaved_write_frame 坏了。原因是 Windows 8 在输出中引入了 B 帧,而 av_interleaved_write_frame 就是不喜欢,无论我如何设置 pts/dts。
我修改了编码器以使用 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);
帧的编码基本上是:
- MFCreateMemoryBuffer 来存储传入的 YUV 数据。
- MFCreateSample。
- 将缓冲液连接到样品上。
- 设置采样时间和持续时间。
- 过程输入
- ProcessOutput 具有适当的输出大小
- 成功后,使用示例信息构建一个 AVPacket