Skip to content

Commit b627c27

Browse files
authored
Merge pull request #90 from sparrowwallet/convert-yu12
Add YU12 to RGB conversion on Linux
2 parents 6a9e5ff + d1d5b00 commit b627c27

File tree

3 files changed

+64
-1
lines changed

3 files changed

+64
-1
lines changed

linux/platformstream.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,15 @@ void PlatformStream::threadSubmitBuffer(void *ptr, size_t bytes)
556556
m_frames++;
557557
m_bufferMutex.unlock();
558558
break;
559+
case V4L2_PIX_FMT_YUV420:
560+
// YU12 to RGB conversion
561+
// YU12 has 1.5 bytes per pixel (12 bits), RGB has 3 bytes per pixel
562+
m_bufferMutex.lock();
563+
YU122RGB((const uint8_t*)ptr, &m_frameBuffer[0], m_width, m_height);
564+
m_newFrame = true;
565+
m_frames++;
566+
m_bufferMutex.unlock();
567+
break;
559568
case 0x47504A4D: // MJPG
560569
#ifdef FRAMEDUMP
561570
{

linux/yuvconverters.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,56 @@ void NV122RGB(const uint8_t *nv12, uint8_t *rgb, uint32_t width, uint32_t height
123123
}
124124
}
125125
}
126+
127+
/*
128+
YU12 (I420) format has three planes:
129+
- Y plane: Full resolution luminance samples
130+
- U plane: 2x2 subsampled U (Cb) samples
131+
- V plane: 2x2 subsampled V (Cr) samples
132+
133+
Memory layout:
134+
YYYYYYYY
135+
YYYYYYYY
136+
YYYYYYYY
137+
YYYYYYYY
138+
UUUU
139+
UUUU
140+
VVVV
141+
VVVV
142+
143+
Each 2x2 Y block shares one U and one V value.
144+
*/
145+
void YU122RGB(const uint8_t *yu12, uint8_t *rgb, uint32_t width, uint32_t height)
146+
{
147+
const uint8_t *y_plane = yu12;
148+
const uint8_t *u_plane = yu12 + (width * height);
149+
const uint8_t *v_plane = u_plane + (width * height / 4);
150+
151+
for (uint32_t row = 0; row < height; row++)
152+
{
153+
for (uint32_t col = 0; col < width; col++)
154+
{
155+
// Get Y value for current pixel
156+
int16_t y = y_plane[row * width + col];
157+
158+
// Get U,V values (shared by 2x2 pixel blocks)
159+
uint32_t uv_row = row / 2;
160+
uint32_t uv_col = col / 2;
161+
uint32_t uv_index = uv_row * (width / 2) + uv_col;
162+
163+
int16_t u = u_plane[uv_index]; // Cb
164+
int16_t v = v_plane[uv_index]; // Cr
165+
166+
// Convert YUV to RGB using the same coefficients as YUYV
167+
int16_t yy = 19 * (y - 16);
168+
169+
// Calculate RGB index
170+
uint32_t rgb_index = (row * width + col) * 3;
171+
172+
// R, G, B order (RGB24)
173+
rgb[rgb_index] = clamp((yy + 26 * (v - 128)) >> 4);
174+
rgb[rgb_index + 1] = clamp((yy - 13 * (v - 128) - 6 * (u - 128)) >> 4);
175+
rgb[rgb_index + 2] = clamp((yy + 32 * (u - 128)) >> 4);
176+
}
177+
}
178+
}

linux/yuvconverters.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,6 @@
3535

3636
void YUYV2RGB(const uint8_t *yuv, uint8_t *rgb, uint32_t bytes);
3737
void NV122RGB(const uint8_t *nv12, uint8_t *rgb, uint32_t width, uint32_t height);
38-
38+
void YU122RGB(const uint8_t *yu12, uint8_t *rgb, uint32_t width, uint32_t height);
39+
3940
#endif

0 commit comments

Comments
 (0)