Skip to content

Commit

Permalink
Add Support fo YUV420 and 410 and YVU variants.
Browse files Browse the repository at this point in the history
  • Loading branch information
samlii committed Jun 7, 2024
1 parent 793f24c commit 128ed5a
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 6 deletions.
10 changes: 8 additions & 2 deletions src/libs/capture.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ static const struct {
{"BGR24", V4L2_PIX_FMT_BGR24},
{"MJPEG", V4L2_PIX_FMT_MJPEG},
{"JPEG", V4L2_PIX_FMT_JPEG},
{"YU12", V4L2_PIX_FMT_YUV420},
{"YV12", V4L2_PIX_FMT_YVU420},
{"YVU9", V4L2_PIX_FMT_YVU410},
{"YUV9", V4L2_PIX_FMT_YUV410}
};

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

_LOG_DEBUG("Grabbed HW buffer=%u: bytesused=%u, grab_ts=%.3Lf, latency=%.3Lf, skipped=%u",
buf.index, buf.bytesused, (*hw)->raw.grab_ts, us_get_now_monotonic() - (*hw)->raw.grab_ts, skipped);
_LOG_DEBUG("Grabbed HW buffer=%u: bytesused=%u, length=%u, grab_ts=%.3Lf, latency=%.3Lf, skipped=%u, "
"width=%u, height=%u, stride=%u",
buf.index, buf.bytesused, buf.length, (*hw)->raw.grab_ts, us_get_now_monotonic() - (*hw)->raw.grab_ts, skipped,
(*hw)->raw.width, (*hw)->raw.height, (*hw)->raw.stride);
return buf.index;
}

Expand Down
4 changes: 4 additions & 0 deletions src/libs/frame.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ bool us_frame_compare(const us_frame_s *a, const us_frame_s *b) {
uint us_frame_get_padding(const us_frame_s *frame) {
uint bytes_per_pixel = 0;
switch (frame->format) {
case V4L2_PIX_FMT_YVU410:
case V4L2_PIX_FMT_YUV410:
case V4L2_PIX_FMT_YVU420:
case V4L2_PIX_FMT_YUV420: bytes_per_pixel = 1; break;
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_YVYU:
case V4L2_PIX_FMT_UYVY:
Expand Down
75 changes: 71 additions & 4 deletions src/ustreamer/encoders/cpu/encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@


#include "encoder.h"

#include "../../../libs/logging.h"

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

static void _jpeg_write_scanlines_yuv(struct jpeg_compress_struct *jpeg, const us_frame_s *frame);
static void _jpeg_write_scanlines_yuv_planar(struct jpeg_compress_struct *jpeg, const us_frame_s *frame);
static void _jpeg_write_scanlines_rgb565(struct jpeg_compress_struct *jpeg, const us_frame_s *frame);
static void _jpeg_write_scanlines_rgb24(struct jpeg_compress_struct *jpeg, const us_frame_s *frame);
#ifndef JCS_EXTENSIONS
Expand Down Expand Up @@ -69,9 +70,13 @@ void us_cpu_encoder_compress(const us_frame_s *src, us_frame_s *dest, unsigned q
switch (src->format) {
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_YVYU:
case V4L2_PIX_FMT_UYVY: jpeg.in_color_space = JCS_YCbCr; break;
case V4L2_PIX_FMT_UYVY:
case V4L2_PIX_FMT_YUV410:
case V4L2_PIX_FMT_YVU410:
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420: jpeg.in_color_space = JCS_YCbCr; break;
# ifdef JCS_EXTENSIONS
case V4L2_PIX_FMT_BGR24: jpeg.in_color_space = JCS_EXT_BGR; break;
case V4L2_PIX_FMT_BGR24: jpeg.in_color_space = JCS_EXT_BGR; break;
# endif
default: jpeg.in_color_space = JCS_RGB; break;
}
Expand All @@ -85,7 +90,11 @@ void us_cpu_encoder_compress(const us_frame_s *src, us_frame_s *dest, unsigned q
// https://www.fourcc.org/yuv.php
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_YVYU:
case V4L2_PIX_FMT_UYVY: _jpeg_write_scanlines_yuv(&jpeg, src); break;
case V4L2_PIX_FMT_UYVY: _jpeg_write_scanlines_yuv(&jpeg, src); break;
case V4L2_PIX_FMT_YUV410:
case V4L2_PIX_FMT_YVU410:
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420: _jpeg_write_scanlines_yuv_planar(&jpeg, src); break;
case V4L2_PIX_FMT_RGB565: _jpeg_write_scanlines_rgb565(&jpeg, src); break;
case V4L2_PIX_FMT_RGB24: _jpeg_write_scanlines_rgb24(&jpeg, src); break;
case V4L2_PIX_FMT_BGR24:
Expand Down Expand Up @@ -167,6 +176,64 @@ static void _jpeg_write_scanlines_yuv(struct jpeg_compress_struct *jpeg, const u
free(line_buf);
}

static void _jpeg_write_scanlines_yuv_planar(struct jpeg_compress_struct *jpeg, const us_frame_s *frame) {
uint8_t *line_buf;
US_CALLOC(line_buf, frame->width * 3);

US_LOG_DEBUG("Using Planar Encoder");
const unsigned padding = us_frame_get_padding(frame);
const uint image_size = frame->width * frame->height;
const uint chroma_array_size = (frame->used - image_size) / 2;
const uint chroma_matrix_order = (image_size / chroma_array_size) == 16 ? 4 : 2;
US_LOG_DEBUG("Planar data: Image Size %u, Chroma Array Size %u, Chroma Matrix Order %u", image_size, chroma_array_size, chroma_matrix_order);
const uint8_t *data = frame->data;
const uint8_t *chroma1_data = frame->data + image_size;
const uint8_t *chroma2_data = frame->data + image_size + chroma_array_size;

while (jpeg->next_scanline < frame->height) {
uint8_t *ptr = line_buf;

for (unsigned x = 0; x < frame->width; ++x) {
// See also: https://www.kernel.org/doc/html/v4.8/media/uapi/v4l/pixfmt-yuv420.html
uint8_t y = data[x], u, v;
uint chroma_position = x / chroma_matrix_order;

switch (frame->format) {
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YUV410:
u = chroma1_data[chroma_position];
v = chroma2_data[chroma_position];
break;
case V4L2_PIX_FMT_YVU420:
case V4L2_PIX_FMT_YVU410:
u = chroma2_data[chroma_position];
v = chroma1_data[chroma_position];
break;
default:
assert(0 && "Unsupported pixel format");
return; // Makes linter happy
}

ptr[0] = y;
ptr[1] = u;
ptr[2] = v;
ptr += 3;
}

data += frame->width + padding;

if( jpeg->next_scanline > 0 && jpeg->next_scanline % chroma_matrix_order == 0 ){
chroma1_data += (frame->width + padding) / chroma_matrix_order;
chroma2_data += (frame->width + padding) / chroma_matrix_order;
}

JSAMPROW scanlines[1] = {line_buf};
jpeg_write_scanlines(jpeg, scanlines, 1);
}

free(line_buf);
}

static void _jpeg_write_scanlines_rgb565(struct jpeg_compress_struct *jpeg, const us_frame_s *frame) {
uint8_t *line_buf;
US_CALLOC(line_buf, frame->width * 3);
Expand Down

0 comments on commit 128ed5a

Please sign in to comment.