Я почти уверен, что это намного проще, чем я думаю, но я искал интернет гораздо дольше, чем хочу признаться, чтобы попытаться выяснить, как фриг конвертирует эти два формата. Я могу извлечь данные Y0, Cb, Y1, Cr из потока байтов без знака (без знака), но я понятия не имею, как эти байты расположены в YV12 — подразумевается ли в этом документе, что различные значения на самом деле содержатся в разных строках?
Я буквально весь день искал такие вещи, как «c ++ convert YUY2 to YV12», и не нашел абсолютно никаких учебных пособий или примеров кода. Я бы подумал, что это будет какая-то форма документации, которую я мог бы использовать, но информации по этому конкретному вопросу, похоже, мало.
Выглядит как связанная запись на YUY2 вместе с Статья в Википедии о YV12 делает это довольно ясно:
YUY2 сохраняет каждые два соседних горизонтальных пикселя как четыре байта, [Y1, U, Y2, V]
,
YV12 хранит весь M × N кадр в непрерывном массиве M*N + 2 * (M/2 * N/2)
байт. Давайте назовем массив byte frame[M * N * 3 / 2]
, У нас есть:
frame[i]
за i
в [0, M * N)
являются Y-значения пикселей.frame[j]
за j
в [M * N, M * N * 5/4)
являются В-значения каждой плитки размером 2 × 2 пикселя.frame[j]
за k
в [M * N * 5/4, M * N * 6/4)
являются U-значения каждой плитки размером 2 × 2 пикселя.Поэтому, когда вы конвертируете из YUY2 в YV12, вы должны вдвое уменьшить U— а также В-данные, возможно, взяв среднее значение двух соседних строк.
Пример:
byte YUY2Source[M * N * 2] = /* source frame */;
byte YV12Dest[M * N * 3/2];
for (unsigned int i = 0; i != M * N; ++i)
{
YV12Dest[i] = YUY2Source[2 * i];
}
for (unsigned int j = 0; j != M * N / 4; ++j)
{
YV12Dest[M * N + j] = ( YUY2Source[N*(j / N/2 ) + 4 * j + 3]
+ YUY2Source[N*(j / N/2 + 1) + 4 * j + 3] ) / 2;
YV12Dest[M * N * 5/4 + j] = ( YUY2Source[N*(j / N/2 ) + 4 * j + 1]
+ YUY2Source[N*(j / N/2 + 1) + 4 * j + 1] ) / 2;
}
w * h
и теперь массивы U и V будут w/2 * h/2
,