rosenbjerg / FFMpegCore

A .NET FFMpeg/FFProbe wrapper for easily integrating media analysis and conversion into your C# applications
MIT License
1.65k stars 298 forks source link

How to convert YUV420 video format input and use in media element (WPF - C#) #378

Closed kondareddy closed 1 year ago

kondareddy commented 1 year ago

We are integrating Agora in WPF (C#) - Agora SDK gives use raw video frames - which we need to render on WPF screens.

SDK Documentation Link.

https://docs-preprod.agora.io/en/video-legacy/API%20Reference/csharp/API/rtc_api_data_type.html#enum_videoframetype

We are searching for library which takes YUV420 format and give use stream, which can be used as media element source.

https://learn.microsoft.com/en-us/dotnet/desktop/wpf/graphics-multimedia/how-to-control-a-mediaelement-play-pause-stop-volume-and-speed?view=netframeworkdesktop-4.8

Below example is something related to our use case. Please help to on this.

image

caxepok commented 1 year ago

Here is function for YUV420 to RGB convertion (it is for ILGPU library to run fast, but also work`s on CPU (but slower))

private static void NV12ToBGR(Index1D i, ArrayView<byte> nv12, ArrayView<byte> rgb, int width, int height, int numPixels)
    {
        int y = i / width;
        int x = i - i / width * width;
        // Get the Y value, stored in the first block of data
        // The logical "AND 0xff" is needed to deal with the signed issue
        float Y = (float)(nv12[y * width + x] & 0xff);
        // Get U and V values, stored after Y values, one per 2x2 block
        // of pixels, interleaved. Prepare them as floats with correct range
        // ready for calculation later.
        int xby2 = x / 2;
        int yby2 = y / 2;

        // make this V for NV12/420SP
        float U = (float)(nv12[numPixels + 2 * xby2 + yby2 * width] & 0xff) - 128.0f;

        // make this U for NV12/420SP
        float V = (float)(nv12[numPixels + 2 * xby2 + 1 + yby2 * width] & 0xff) - 128.0f;

        // No need to correct Y
        // These are the coefficients proposed by @AlexCohn
        // for [0..255], as per the wikipedia page referenced
        // above
        int R = (int)(Y + 1.370705f * V);
        int G = (int)(Y - 0.698001f * V - 0.337633f * U);
        int B = (int)(Y + 1.732446f * U);

        // Clip rgb values to 0-255
        R = R < 0 ? 0 : R > 255 ? 255 : R;
        G = G < 0 ? 0 : G > 255 ? 255 : G;
        B = B < 0 ? 0 : B > 255 ? 255 : B;

        rgb[y * width * 3 + x * 3] = (byte)B;
        rgb[y * width * 3 + x * 3 + 1] = (byte)G;
        rgb[y * width * 3 + x * 3 + 2] = (byte)R;
    }
rosenbjerg commented 1 year ago

Sorry, I cannot help you with that. I suggest you try on stack overflow or similar sites :)