【发布时间】:2018-09-21 01:59:58
【问题描述】:
我正在开发一个使用媒体基础 h264 编码器对视频进行编码的应用。 Sink writer crashes on Windows 7 在 VRAM 中使用 RGB 输入,说“0x8876086C D3DERR_INVALIDCALL”,所以我在 GPU 上实现了自己的 RGB->NV12 转换,节省了 60% 以上的 PCI express 带宽。
这是我的媒体类型中的内容,包括输入 (NV12) 和输出 (h264):
mt->SetUINT32( MF_MT_VIDEO_CHROMA_SITING, MFVideoChromaSubsampling_MPEG2 ); // Specifies the chroma encoding scheme for MPEG-2 video. Chroma samples are aligned horizontally with the luma samples, but are not aligned vertically. The U and V planes are aligned vertically.
mt->SetUINT32( MF_MT_YUV_MATRIX, MFVideoTransferMatrix_BT709 ); // ITU-R BT.709 transfer matrix.
mt->SetUINT32( MF_MT_VIDEO_NOMINAL_RANGE, MFNominalRange_0_255 ); // The normalized range [0...1] maps to [0...255] for 8-bit samples or [0...1023] for 10-bit samples.
mt->SetUINT32( MF_MT_TRANSFER_FUNCTION, MFVideoTransFunc_10 ); // Linear RGB (gamma = 1.0).
到目前为止我用这个公式得到的最好结果:
inline float3 yuvFromRgb(float3 rgba)
{
float3 res;
res.x = dot( rgba, float3( 0.182585880, 0.614230573, 0.0620070584 ) );
res.y = dot( rgba, float3( -0.121760942, -0.409611613, 0.531372547 ) );
res.z = dot( rgba, float3( 0.531372547, -0.482648790, -0.0487237722 ) );
res += float3( 0.0627451017, 0.500000000, 0.500000000 );
return saturate( res );
}
让我担心的是这个公式与我在互联网上阅读的所有内容、代码示例和 ITU 官方规范相矛盾。
对于 Y 的公式很好,我采用了 BT.709 系数,并将它们线性缩放,以将 [0..255] 映射到 [16..235] 中,如规范中所述。亮度还可以。
规范说我必须缩放 U 和 V 以从 [0..255] 映射到 [16..240]。然而,我的眼睛告诉我它是不饱和的。为了获得正确的颜色,我必须以另一种方式缩放 U 和 V,从 [0..255] 到 [-8, 255 + 8] 之类的东西。
为什么我需要在 h264 编码和解码后以其他方式缩放以获得正确的颜色?此代码可以在其他人的计算机上运行吗?
【问题讨论】:
标签: c++ windows h.264 hlsl ms-media-foundation