CRI Sofdec  Last Updated: 2025-09-30 13:25 p
YUV-RGB色変換

YUV-RGB色変換について

CRI Manaライブラリではコーデック/プラットフォーム次第でデコード結果のフレームがYUV形式で取得されます。
この時描画を行う際にはYUV形式からRGB形式に色変換する必要がありますが、色変換の計算式はデコード結果の色空間情報によって変化するため、
フレーム情報 CriManaFrameInfo.color_conv を参照して色変換計算式を決定するようにしてください。

BT.601 Limited Range /709 Limited Rangeを切り分ける例:

if (criManaPlayer_ReferFrame(app_obj.player, &app_obj.frame_info) == CRI_TRUE) {
if (app_obj.frame_info.color_conv == CRIMANA_COLORSPACE_CONVERSION_TYPE_ITU_R_BT601_LIMITED) {
/* BT.601 Limited Rangeのシェーダーを選択 */
} else if (app_obj.frame_info.color_conv == CRIMANA_COLORSPACE_CONVERSION_TYPE_ITU_R_BT709_LIMITED){
/* BT.709 Limited Rangeのシェーダーを選択 */
}
...
}
CriBool criManaPlayer_ReferFrame(CriManaPlayerHn player, CriManaFrameInfo *frame_info)
デコード済みのフレーム情報の参照


Sofdec.Primeコーデックの場合


Sofdec.Primeコーデックの場合はI420相当のYUV 3プレーンでの形式で出力されるため、色変換式は以下のようになります。

BT.601 Limited Rangeのシェーダー色変換 (HLSL):

float4 TexY = g_texture_0.Sample( g_sampler, input.texcoord );
float4 TexU = g_texture_1.Sample( g_sampler, input.texcoord ) - float4( 128.0 / 255.0, 128.0 / 255.0, 128.0 / 255.0, 128.0 / 255.0 );
float4 TexV = g_texture_2.Sample( g_sampler, input.texcoord ) - float4( 128.0 / 255.0, 128.0 / 255.0, 128.0 / 255.0, 128.0 / 255.0 );
float4 Color = ( TexY.a - float4( 16.0 / 255.0, 16.0 / 255.0, 16.0 / 255.0, 16.0 / 255.0 ) ) * 1.164f;
Color.a = 1.0f;
Color.r += TexV.a * 1.596f;
Color.g += -TexU.a * 0.392f -TexV.a * 0.813f;
Color.b += TexU.a * 2.017f;


BT.709 Limited Rangeのシェーダー色変換 (HLSL):

float4 TexY = g_texture_0.Sample( g_sampler, input.texcoord );
float4 TexU = g_texture_1.Sample( g_sampler, input.texcoord ) - float4( 128.0 / 255.0, 128.0 / 255.0, 128.0 / 255.0, 128.0 / 255.0 );
float4 TexV = g_texture_2.Sample( g_sampler, input.texcoord ) - float4( 128.0 / 255.0, 128.0 / 255.0, 128.0 / 255.0, 128.0 / 255.0 );
float4 Color = ( TexY.a - float4( 16.0 / 255.0, 16.0 / 255.0, 16.0 / 255.0, 16.0 / 255.0 ) ) * 1.164f;
Color.a = 1.0f;
Color.r += TexV.a * 1.793f;
Color.g += -TexU.a * 0.213f -TexV.a * 0.533f;
Color.b += TexU.a * 2.112f;


H.264/VP9/AV1コーデックの場合


デコード結果はプラットフォームやデコード出力設定によって異なります。
例えばコーデックと機種の組み合わせによってはNV12形式になるため、YとUVの2プレーンに対し色変換を行う必要があります。
以下はNV12形式の場合のシェーダー色変換式です。詳細は各機種固有マニュアルをご参照ください。

BT.601 Limited Rangeのシェーダー色変換 (GLSL):

float y_Color = texture(u_textureY , v_texCoord).r;
float u_Color = texture(u_textureUV, v_texCoord).r - 128.0 / 255.0;
float v_Color = texture(u_textureUV, v_texCoord).g - 128.0 / 255.0;
vec3 tmp_Color = (vec3(y_Color, y_Color, y_Color) - vec3(16.0 / 255.0, 16.0 / 255.0, 16.0 / 255.0)) * 1.164;
tmp_Color.r += v_Color * 1.596f;
tmp_Color.g += -u_Color * 0.392f - v_Color * 0.813f;
tmp_Color.b += u_Color * 2.017f;
colorOut = vec4(tmp_Color, 1.0);


BT.709 Limited Rangeのシェーダー色変換 (GLSL):

float y_Color = texture(u_textureY , v_texCoord).r;
float u_Color = texture(u_textureUV, v_texCoord).r - 128.0 / 255.0;
float v_Color = texture(u_textureUV, v_texCoord).g - 128.0 / 255.0;
vec3 tmp_Color = (vec3(y_Color, y_Color, y_Color) - vec3(16.0 / 255.0, 16.0 / 255.0, 16.0 / 255.0)) * 1.164;
tmp_Color.r += v_Color * 1.793f;
tmp_Color.g += -u_Color * 0.213f - v_Color * 0.533f;
tmp_Color.b += u_Color * 2.112f;
colorOut = vec4(tmp_Color, 1.0);