
10 bit YUV to 8 bit ARGB conversion
I am looking for the exact formula that BlackMagic uses for converting bmdFormat10BitYUV to bmdFormat8BitARGB in its IDeckLinkVideoConversion
I need to implement this conversion on the GPU where the image will live thus leaving the job to the DeckLink api which runs on the CPU is not viable performance-wise.
The formula I am using results in somewhat washed Black and to a lesser extent Blue:
Apparent difference in Black and (somewhat) in Blue
static float ConvertRec709ToLinear(float Value) {
float Result{};
//BT709 OECF-Different Ranges
if(0.09f > Value)
Result = Value / 4.5f;
else
Result = pow((Value + 0.099f) / 1.099f, 2.2222222f);
return Result;
}
static glm::vec3 ConvertRec709ToLinearVector(glm::vec3 value) {
glm::vec3 result{ glm::vec3(0.0f) };
result.r = ConvertRec709ToLinear(value.r);
result.g = ConvertRec709ToLinear(value.g);
result.b = ConvertRec709ToLinear(value.b);
return result;
}
static glm::vec4 ConvertYUVtoRGBA(float Y, float Cb, float Cr, float Alpha) {
Y /= 1023.99f;
Cb /= 1023.99f;
Cr /= 1023.99f;
//Range Clipping
Y -= 0.0f;
Cb -= (512.0f / 1023.0f);
Cr -= (512.0f / 1023.0f);
glm::vec3 YCbCr{ glm::vec3(Y, Cb, Cr) };
glm::vec3 RGB{ glm::vec3(0.0f) };
RGB.r = glm::clamp(glm::dot(YCbCr, glm::vec3(1.000f, 0.0000f, 1.5748f)), 0.0f, 1.0f);
RGB.g = glm::clamp(glm::dot(YCbCr, glm::vec3(1.000f, -0.1873f, -0.4681f)), 0.0f, 1.0f);
RGB.b = glm::clamp(glm::dot(YCbCr, glm::vec3(1.000f, 1.8556f, 0.0000f)), 0.0f, 1.0f);
RGB = ConvertRec709ToLinearVector(RGB);
return glm::vec4(RGB, Alpha);
}
where ConvertYUVtoRGBA() is called with 10bit integer Y, Cb, Cr values cast to float and Alpha = 1.0f