[mythtv] YV12 problem

Jean-Yves Avenard jyavenard at gmail.com
Thu Dec 13 10:22:59 UTC 2018

On Thu, 13 Dec 2018 at 04:28, David Engel <david at istwok.net> wrote:

> I'm confused again.  I thought we were talking about yv12 but you're
> talking mostly about nv12.  I know there are a plethora of pixel
> formats but it's still mostly Greek alphabet soup to me until I get
> further up to speed.  If the hardware decoders generate nv12, how does
> yv12 fit in?  Is it a format that has to be converted to on the way to
> output or something else?

the only difference between NV12 and YUV420/YV12 is that U and V are
interleaved for NV12.

So YV12 is stored as:

and NV12 is:

that's it.
information is identical just stored differently.

YV12 fits in because all FFmpeg decoder outputs that format.
If you have no hardware decoder you will get YV12 out
If you use a hardware decoder you get NV12 out (with the buffer
actually in GPU memory)

> I think that's kind of what I figured.  The pixel format is already
> known for the textures and handled appropriately, right?  The
> algorithm of which pixels from which lines/testures to mix with other
> pixels remains the same.

You do need to tell the GPU what textures you are you are feeding it.
So with OpenGL, for YV12 you pass 3 textures buffer
NV12 you pass 2 textures buffer.

To show the difference on what the shader would be to access the YV12 pixel:
float3 yuv = float3(
tY.Sample(sSampler, aTexCoords).r,
tCb.Sample(sSampler, aTexCoords).r,
tCr.Sample(sSampler, aTexCoords).r);
return CalculateYCbCrColor(yuv * vCoefficient);

That's for nv12
float y = tY.Sample(sSampler, aTexCoords).r;
float2 cbcr = tCb.Sample(sSampler, aTexCoords).rg;
return CalculateYCbCrColor(float3(y, cbcr) * vCoefficient);

That's a D3D11 shader for Firefox OpenGL compositor (everything gets
converted to RGB before being composited)

You can see that for YV12 you access the data for U/V separately, and
for NV12, together. that's it. 1 line change.

If you were to do that in C, it would be:
Yvalue = Y[x] + y * strideY;
Uvalue = U[x/2] + y * strideU;
Vvalue = V[x/2] + y * strideV;

With strideU=strideV=strideY/2

For NV12:
Yvalue = Y[x] + y * strideY;
Uvalue = UV[int(x/2)*2] + y * strideUV;
Vvalue = VV[int(x/2)*2+1] + y * strideUV;

with strideUV = strideY

More information about the mythtv-dev mailing list