Skip to content

Commit 128ed5a

Browse files
committed
Add Support fo YUV420 and 410 and YVU variants.
1 parent 793f24c commit 128ed5a

File tree

3 files changed

+83
-6
lines changed

3 files changed

+83
-6
lines changed

src/libs/capture.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ static const struct {
7272
{"BGR24", V4L2_PIX_FMT_BGR24},
7373
{"MJPEG", V4L2_PIX_FMT_MJPEG},
7474
{"JPEG", V4L2_PIX_FMT_JPEG},
75+
{"YU12", V4L2_PIX_FMT_YUV420},
76+
{"YV12", V4L2_PIX_FMT_YVU420},
77+
{"YVU9", V4L2_PIX_FMT_YVU410},
78+
{"YUV9", V4L2_PIX_FMT_YUV410}
7579
};
7680

7781
static const struct {
@@ -416,8 +420,10 @@ int us_capture_hwbuf_grab(us_capture_s *cap, us_capture_hwbuf_s **hw) {
416420
_v4l2_buffer_copy(&buf, &(*hw)->buf);
417421
(*hw)->raw.grab_ts = (ldf)((buf.timestamp.tv_sec * (u64)1000) + (buf.timestamp.tv_usec / 1000)) / 1000;
418422

419-
_LOG_DEBUG("Grabbed HW buffer=%u: bytesused=%u, grab_ts=%.3Lf, latency=%.3Lf, skipped=%u",
420-
buf.index, buf.bytesused, (*hw)->raw.grab_ts, us_get_now_monotonic() - (*hw)->raw.grab_ts, skipped);
423+
_LOG_DEBUG("Grabbed HW buffer=%u: bytesused=%u, length=%u, grab_ts=%.3Lf, latency=%.3Lf, skipped=%u, "
424+
"width=%u, height=%u, stride=%u",
425+
buf.index, buf.bytesused, buf.length, (*hw)->raw.grab_ts, us_get_now_monotonic() - (*hw)->raw.grab_ts, skipped,
426+
(*hw)->raw.width, (*hw)->raw.height, (*hw)->raw.stride);
421427
return buf.index;
422428
}
423429

src/libs/frame.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ bool us_frame_compare(const us_frame_s *a, const us_frame_s *b) {
8282
uint us_frame_get_padding(const us_frame_s *frame) {
8383
uint bytes_per_pixel = 0;
8484
switch (frame->format) {
85+
case V4L2_PIX_FMT_YVU410:
86+
case V4L2_PIX_FMT_YUV410:
87+
case V4L2_PIX_FMT_YVU420:
88+
case V4L2_PIX_FMT_YUV420: bytes_per_pixel = 1; break;
8589
case V4L2_PIX_FMT_YUYV:
8690
case V4L2_PIX_FMT_YVYU:
8791
case V4L2_PIX_FMT_UYVY:

src/ustreamer/encoders/cpu/encoder.c

Lines changed: 71 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727

2828
#include "encoder.h"
29-
29+
#include "../../../libs/logging.h"
3030

3131
typedef struct {
3232
struct jpeg_destination_mgr mgr; // Default manager
@@ -38,6 +38,7 @@ typedef struct {
3838
static void _jpeg_set_dest_frame(j_compress_ptr jpeg, us_frame_s *frame);
3939

4040
static void _jpeg_write_scanlines_yuv(struct jpeg_compress_struct *jpeg, const us_frame_s *frame);
41+
static void _jpeg_write_scanlines_yuv_planar(struct jpeg_compress_struct *jpeg, const us_frame_s *frame);
4142
static void _jpeg_write_scanlines_rgb565(struct jpeg_compress_struct *jpeg, const us_frame_s *frame);
4243
static void _jpeg_write_scanlines_rgb24(struct jpeg_compress_struct *jpeg, const us_frame_s *frame);
4344
#ifndef JCS_EXTENSIONS
@@ -69,9 +70,13 @@ void us_cpu_encoder_compress(const us_frame_s *src, us_frame_s *dest, unsigned q
6970
switch (src->format) {
7071
case V4L2_PIX_FMT_YUYV:
7172
case V4L2_PIX_FMT_YVYU:
72-
case V4L2_PIX_FMT_UYVY: jpeg.in_color_space = JCS_YCbCr; break;
73+
case V4L2_PIX_FMT_UYVY:
74+
case V4L2_PIX_FMT_YUV410:
75+
case V4L2_PIX_FMT_YVU410:
76+
case V4L2_PIX_FMT_YUV420:
77+
case V4L2_PIX_FMT_YVU420: jpeg.in_color_space = JCS_YCbCr; break;
7378
# ifdef JCS_EXTENSIONS
74-
case V4L2_PIX_FMT_BGR24: jpeg.in_color_space = JCS_EXT_BGR; break;
79+
case V4L2_PIX_FMT_BGR24: jpeg.in_color_space = JCS_EXT_BGR; break;
7580
# endif
7681
default: jpeg.in_color_space = JCS_RGB; break;
7782
}
@@ -85,7 +90,11 @@ void us_cpu_encoder_compress(const us_frame_s *src, us_frame_s *dest, unsigned q
8590
// https://www.fourcc.org/yuv.php
8691
case V4L2_PIX_FMT_YUYV:
8792
case V4L2_PIX_FMT_YVYU:
88-
case V4L2_PIX_FMT_UYVY: _jpeg_write_scanlines_yuv(&jpeg, src); break;
93+
case V4L2_PIX_FMT_UYVY: _jpeg_write_scanlines_yuv(&jpeg, src); break;
94+
case V4L2_PIX_FMT_YUV410:
95+
case V4L2_PIX_FMT_YVU410:
96+
case V4L2_PIX_FMT_YUV420:
97+
case V4L2_PIX_FMT_YVU420: _jpeg_write_scanlines_yuv_planar(&jpeg, src); break;
8998
case V4L2_PIX_FMT_RGB565: _jpeg_write_scanlines_rgb565(&jpeg, src); break;
9099
case V4L2_PIX_FMT_RGB24: _jpeg_write_scanlines_rgb24(&jpeg, src); break;
91100
case V4L2_PIX_FMT_BGR24:
@@ -167,6 +176,64 @@ static void _jpeg_write_scanlines_yuv(struct jpeg_compress_struct *jpeg, const u
167176
free(line_buf);
168177
}
169178

179+
static void _jpeg_write_scanlines_yuv_planar(struct jpeg_compress_struct *jpeg, const us_frame_s *frame) {
180+
uint8_t *line_buf;
181+
US_CALLOC(line_buf, frame->width * 3);
182+
183+
US_LOG_DEBUG("Using Planar Encoder");
184+
const unsigned padding = us_frame_get_padding(frame);
185+
const uint image_size = frame->width * frame->height;
186+
const uint chroma_array_size = (frame->used - image_size) / 2;
187+
const uint chroma_matrix_order = (image_size / chroma_array_size) == 16 ? 4 : 2;
188+
US_LOG_DEBUG("Planar data: Image Size %u, Chroma Array Size %u, Chroma Matrix Order %u", image_size, chroma_array_size, chroma_matrix_order);
189+
const uint8_t *data = frame->data;
190+
const uint8_t *chroma1_data = frame->data + image_size;
191+
const uint8_t *chroma2_data = frame->data + image_size + chroma_array_size;
192+
193+
while (jpeg->next_scanline < frame->height) {
194+
uint8_t *ptr = line_buf;
195+
196+
for (unsigned x = 0; x < frame->width; ++x) {
197+
// See also: https://www.kernel.org/doc/html/v4.8/media/uapi/v4l/pixfmt-yuv420.html
198+
uint8_t y = data[x], u, v;
199+
uint chroma_position = x / chroma_matrix_order;
200+
201+
switch (frame->format) {
202+
case V4L2_PIX_FMT_YUV420:
203+
case V4L2_PIX_FMT_YUV410:
204+
u = chroma1_data[chroma_position];
205+
v = chroma2_data[chroma_position];
206+
break;
207+
case V4L2_PIX_FMT_YVU420:
208+
case V4L2_PIX_FMT_YVU410:
209+
u = chroma2_data[chroma_position];
210+
v = chroma1_data[chroma_position];
211+
break;
212+
default:
213+
assert(0 && "Unsupported pixel format");
214+
return; // Makes linter happy
215+
}
216+
217+
ptr[0] = y;
218+
ptr[1] = u;
219+
ptr[2] = v;
220+
ptr += 3;
221+
}
222+
223+
data += frame->width + padding;
224+
225+
if( jpeg->next_scanline > 0 && jpeg->next_scanline % chroma_matrix_order == 0 ){
226+
chroma1_data += (frame->width + padding) / chroma_matrix_order;
227+
chroma2_data += (frame->width + padding) / chroma_matrix_order;
228+
}
229+
230+
JSAMPROW scanlines[1] = {line_buf};
231+
jpeg_write_scanlines(jpeg, scanlines, 1);
232+
}
233+
234+
free(line_buf);
235+
}
236+
170237
static void _jpeg_write_scanlines_rgb565(struct jpeg_compress_struct *jpeg, const us_frame_s *frame) {
171238
uint8_t *line_buf;
172239
US_CALLOC(line_buf, frame->width * 3);

0 commit comments

Comments
 (0)