Преобразование YUV420p в RGB сместило значения U и V - iOS Unity3D - PullRequest
0 голосов
/ 24 августа 2018

У меня есть собственный плагин в Unity, который декодирует кадры H264 в YUV420p с помощью FFMPEG.

Чтобы отобразить выходное изображение, я переставляю значения YUV в текстуру RGBA и преобразую YUV в RGB с помощью шейдера Unity (просто, чтобы сделать его быстрее).

Ниже приведен код перестановки в моем родном плагине:

unsigned char* yStartLocation = (unsigned char*)m_pFrame->data[0];
unsigned char* uStartLocation = (unsigned char*)m_pFrame->data[1];
unsigned char* vStartLocation = (unsigned char*)m_pFrame->data[2];

for (int y = 0; y < height; y++)
{
    for (int x = 0; x < width; x++)
    {

        unsigned char* y = yStartLocation + ((y * width) + x);
        unsigned char* u = uStartLocation + ((y * (width / 4)) + (x / 2));
        unsigned char* v = vStartLocation + ((y * (width / 4)) + (x / 2));
        //REF: https://en.wikipedia.org/wiki/YUV

        // Write the texture pixel
        dst[0] = y[0]; //R
        dst[1] = u[0]; //G
        dst[2] = v[0]; //B
        dst[3] = 255;  //A

        // To next pixel
        dst += 4;

        // dst is the pointer to target texture RGBA data
    }
}

Шейдер, который конвертирует YUV в RGB, отлично работает, и я использовал его в нескольких проектах.

Теперь я использую тот же код для декодирования на платформе iOS. Но по какой-то причине значения U и V теперь смещены:

Y Текстура

enter image description here

U Текстура

enter image description here

Есть что-то, чего мне не хватает специально для iOS или OpenGL?

Любая помощь с благодарностью. Спасибо!

Обратите внимание, что я заполнил R = G = B = Y для первого снимка экрана и U для второго (если это имеет смысл)

Edit: Вот вывод, который я получаю: enter image description here

Edit2: Основываясь на некоторых исследованиях, я думаю, что это как-то связано с чересстрочной разверткой.

ref: Ссылка

На данный момент я перешел на преобразование YUV-RGB на базе процессора с использованием sws_scale, и оно работает нормально.

1 Ответ

0 голосов
/ 28 сентября 2018

Проблема была в этой строке:

uStartLocation + ((y * (width / 4)) + (x / 2));

Это должно быть

uStartLocation + (((y / 2) * (width / 2)) + (x / 2));

Поскольку округление int вызывало смещение всего кадра.Очень глупая ошибка при попытке оптимизировать вычисления.

Надеюсь, это кому-нибудь поможет.

...