Enhanced Video Renderer renders 8 bit YUY2 but not 10 bit Y210

Aaron Marcus 1 Reputation point
2021-03-22T14:06:57.013+00:00

I have written a standalone implementation of the Media Foundation Enhanced Video Renderer based on Aaron Clauson's samples. I am feeding it Y210 10 bit YUV 4:2:2 video (extracted from a SMPTE 2110-20 RTP stream) but it only renders a black screen with no errors - either from the HRESULTS or whilst using MFTRACE. As described here, I have placed the 10 bit values into a 16 bit WORD with the lower 6 bits set to 0 as padding.

int x = 0;  
for (int i = 0; i < intermediateByteBuffer.size(); i += 5) //intermediateBYTEBuffer is a vector of uint8_t that holds 5 byte "pGroups". Each 10 bits is moved into a new WORD array element and padded   
{ //WORD buffer order is 1,0,3,2 to convert samples from Cb, Y0, Cr, Y1 to Y0, Cb, Y1, Cr as specified in Y210 and YUY2   
    intermediateWORDBuffer[1 + x] = (((uint16_t)intermediateByteBuffer[0 + i] & 0b11111111u) << (0 + 8)) | (((uint16_t)intermediateByteBuffer[1 + i] & 0b11000000u) << 0);   
    intermediateWORDBuffer[0 + x] = (((uint16_t)intermediateByteBuffer[1 + i] & 0b00111111u) << (2 + 8)) | (((uint16_t)intermediateByteBuffer[2 + i] & 0b11110000u) << 2);   
    intermediateWORDBuffer[3 + x] = (((uint16_t)intermediateByteBuffer[2 + i] & 0b00001111u) << (4 + 8)) | (((uint16_t)intermediateByteBuffer[3 + i] & 0b11111100u) << 4);   
    intermediateWORDBuffer[2 + x] = (((uint16_t)intermediateByteBuffer[3 + i] & 0b00000011u) << (6 + 8)) | (((uint16_t)intermediateByteBuffer[4 + i] & 0b11111111u << 6);   
    x += 4;  
}   

I can convert the 10 bit data to 8 bit YUY2 by right-shifting each WORD by 8 (>> 6 to account for padding and >> 2 for the logical conversion from 10 to 8 bit) and the renderer will display the video frame with no problem.

for (int i = 0; i < intermediateWORDBuffer.size(); i += 8)   
{   
    renderBuffer[i + 0] = (intermediateWORDBuffer[i + 0] >> 8); //renderBuffer is a uint8_t vector   
    renderBuffer[i + 1] = (intermediateWORDBuffer[i + 1] >> 8);   
    renderBuffer[i + 2] = (intermediateWORDBuffer[i + 2] >> 8);   
    renderBuffer[i + 3] = (intermediateWORDBuffer[i + 3] >> 8);   
    renderBuffer[i + 4] = (intermediateWORDBuffer[i + 4] >> 8);   
    renderBuffer[i + 5] = (intermediateWORDBuffer[i + 5] >> 8);   
    renderBuffer[i + 6] = (intermediateWORDBuffer[i + 6] >> 8);   
    renderBuffer[i + 7] = (intermediateWORDBuffer[i + 7] >> 8);   
}   

This leads me to question why the renderer will accept 8 bit not 10 bit (16 including padding) as for the conversion to work it needs valid 10 bit data from the start. I have also tried swapping the order of the pixel samples, but this does not work either.

Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,427 questions
{count} votes