Skip to content

Commit

Permalink
Added NV16 and NV24
Browse files Browse the repository at this point in the history
  • Loading branch information
Vincent056 committed Nov 15, 2023
1 parent 03b7fb8 commit 793f904
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/libs/frame.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ unsigned us_frame_get_padding(const us_frame_s *frame) {
unsigned bytes_per_pixel = 0;
switch (frame->format) {
case V4L2_PIX_FMT_NV12:
case V4L2_PIX_FMT_NV24:
case V4L2_PIX_FMT_NV16:
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_UYVY:
case V4L2_PIX_FMT_RGB565: bytes_per_pixel = 2; break;
Expand Down
2 changes: 2 additions & 0 deletions src/ustreamer/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ static const struct {
const unsigned format; // cppcheck-suppress unusedStructMember
} _FORMATS[] = {
{"NV12", V4L2_PIX_FMT_NV12},
{"NV24", V4L2_PIX_FMT_NV24},
{"NV16", V4L2_PIX_FMT_NV16},
{"YUYV", V4L2_PIX_FMT_YUYV},
{"UYVY", V4L2_PIX_FMT_UYVY},
{"RGB565", V4L2_PIX_FMT_RGB565},
Expand Down
102 changes: 102 additions & 0 deletions src/ustreamer/encoders/cpu/encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,12 @@ static void _jpeg_write_scanlines_rgb565(struct jpeg_compress_struct *jpeg, cons
static void _jpeg_write_scanlines_rgb24(struct jpeg_compress_struct *jpeg, const us_frame_s *frame);
static void _jpeg_write_scanlines_bgr24(struct jpeg_compress_struct *jpeg, const us_frame_s *frame);
static void _jpeg_write_scanlines_nv12(struct jpeg_compress_struct *jpeg, const us_frame_s *frame);
static void _jpeg_write_scanlines_nv16(struct jpeg_compress_struct *jpeg, const us_frame_s *frame);
static void _jpeg_write_scanlines_nv24(struct jpeg_compress_struct *jpeg, const us_frame_s *frame);

static void _nv12_to_rgb24(const uint8_t *in, uint8_t *out, int width, int height);
static void _nv16_to_rgb24(const uint8_t *in, uint8_t *out, int width, int height);
static void _nv24_to_rgb24(const uint8_t *in, uint8_t *out, int width, int height);

static void _jpeg_init_destination(j_compress_ptr jpeg);
static boolean _jpeg_empty_output_buffer(j_compress_ptr jpeg);
Expand Down Expand Up @@ -83,8 +87,10 @@ void us_cpu_encoder_compress(const us_frame_s *src, us_frame_s *dest, unsigned q
WRITE_SCANLINES(V4L2_PIX_FMT_UYVY, _jpeg_write_scanlines_uyvy);
WRITE_SCANLINES(V4L2_PIX_FMT_RGB565, _jpeg_write_scanlines_rgb565);
WRITE_SCANLINES(V4L2_PIX_FMT_NV12, _jpeg_write_scanlines_nv12);
WRITE_SCANLINES(V4L2_PIX_FMT_NV16, _jpeg_write_scanlines_nv16);
WRITE_SCANLINES(V4L2_PIX_FMT_BGR24, _jpeg_write_scanlines_bgr24);
WRITE_SCANLINES(V4L2_PIX_FMT_RGB24, _jpeg_write_scanlines_rgb24);
WRITE_SCANLINES(V4L2_PIX_FMT_NV24, _jpeg_write_scanlines_nv24);
default: assert(0 && "Unsupported input format for CPU encoder");
}

Expand Down Expand Up @@ -193,6 +199,54 @@ static void _jpeg_write_scanlines_uyvy(struct jpeg_compress_struct *jpeg, const
free(line_buf);
}

static void _nv16_to_rgb24(const uint8_t *in, uint8_t *out, int width, int height) {
int frame_size = width * height;
int uv_offset = frame_size;

for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int y_index = i * width + j;
int uv_index = uv_offset + (i * width) + (j & ~1); // For each pair of pixels, the same UV is used
int Y = in[y_index];
int U = in[uv_index] - 128; // Cb component
int V = in[uv_index + 1] - 128; // Cr component

// YUV to RGB conversion
int R = (298 * (Y - 16) + 409 * V + 128) >> 8;
int G = (298 * (Y - 16) - 100 * U - 208 * V + 128) >> 8;
int B = (298 * (Y - 16) + 516 * U + 128) >> 8;

// Clamp values to [0, 255]
R = R < 0 ? 0 : (R > 255 ? 255 : R);
G = G < 0 ? 0 : (G > 255 ? 255 : G);
B = B < 0 ? 0 : (B > 255 ? 255 : B);

int rgb_index = y_index * 3;
out[rgb_index] = (uint8_t)R;
out[rgb_index + 1] = (uint8_t)G;
out[rgb_index + 2] = (uint8_t)B;
}
}
}

static void _jpeg_write_scanlines_nv16(struct jpeg_compress_struct *jpeg, const us_frame_s *frame) {
const unsigned padding = us_frame_get_padding(frame);
uint8_t *rgb;
US_CALLOC(rgb, frame->width * frame->height * 3);
_nv16_to_rgb24(frame->data, rgb, frame->width, frame->height);
uint8_t *data = rgb;

while (jpeg->next_scanline < frame->height) {
JSAMPROW scanlines[1] = {data};
jpeg_write_scanlines(jpeg, scanlines, 1);

data += (frame->width * 3) + padding;
}

free(rgb);
}


static void _nv12_to_rgb24(const uint8_t *in, uint8_t *out, int width, int height) {
int frame_size = width * height;
int uv_offset = frame_size;
Expand Down Expand Up @@ -224,6 +278,37 @@ static void _nv12_to_rgb24(const uint8_t *in, uint8_t *out, int width, int heigh
}
}
}
static void _nv24_to_rgb24(const uint8_t *in, uint8_t *out, int width, int height) {
int frame_size = width * height;
int uv_offset = frame_size;

for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int y_index = i * width + j;
int uv_index = uv_offset + (2 * j) + (i * width * 2); // Adjusted for full resolution CbCr plane
int Y = in[y_index];
int U = in[uv_index] - 128; // Cb component
int V = in[uv_index + 1] - 128; // Cr component

// YUV to RGB conversion
int R = (298 * (Y - 16) + 409 * V + 128) >> 8;
int G = (298 * (Y - 16) - 100 * U - 208 * V + 128) >> 8;
int B = (298 * (Y - 16) + 516 * U + 128) >> 8;

// Clamp values to [0, 255]
R = R < 0 ? 0 : (R > 255 ? 255 : R);
G = G < 0 ? 0 : (G > 255 ? 255 : G);
B = B < 0 ? 0 : (B > 255 ? 255 : B);

int rgb_index = y_index * 3;
out[rgb_index] = (uint8_t)R;
out[rgb_index + 1] = (uint8_t)G;
out[rgb_index + 2] = (uint8_t)B;
}
}
}



static void _jpeg_write_scanlines_nv12(struct jpeg_compress_struct *jpeg, const us_frame_s *frame) {
const unsigned padding = us_frame_get_padding(frame);
Expand All @@ -242,6 +327,23 @@ static void _jpeg_write_scanlines_nv12(struct jpeg_compress_struct *jpeg, const
free(rgb);
}

static void _jpeg_write_scanlines_nv24(struct jpeg_compress_struct *jpeg, const us_frame_s *frame) {
const unsigned padding = us_frame_get_padding(frame);
uint8_t *rgb;
US_CALLOC(rgb, frame->width * frame->height * 3);
_nv24_to_rgb24(frame->data, rgb, frame->width, frame->height);
uint8_t *data = rgb;

while (jpeg->next_scanline < frame->height) {
JSAMPROW scanlines[1] = {data};
jpeg_write_scanlines(jpeg, scanlines, 1);

data += (frame->width * 3) + padding;
}

free(rgb);
}

#undef NORM_COMPONENT
#undef YUV_B
#undef YUV_G
Expand Down

0 comments on commit 793f904

Please sign in to comment.