From 537e55afc616f3e825d60616b50f39651302d002 Mon Sep 17 00:00:00 2001 From: Devaev Maxim Date: Mon, 4 Mar 2019 11:34:25 +0300 Subject: [PATCH] RGB24 --- Makefile | 2 +- src/device.c | 1 + src/device.h | 2 +- src/jpeg/encoder.c | 68 ++++++++++++++++++++++++++++++---------------- src/omx/encoder.c | 23 +++++++++++----- 5 files changed, 64 insertions(+), 32 deletions(-) diff --git a/Makefile b/Makefile index 4933483..6a3e5cd 100644 --- a/Makefile +++ b/Makefile @@ -59,5 +59,5 @@ push: clean-all: clean clean: - rm -f src/*.o src/{jpeg,omx}/*.o vgcore.* *.sock $(PROG) + rm -f src/*.o src/{jpeg,hw,omx}/*.o vgcore.* *.sock $(PROG) rm -rf pkg src/$(PROG)-* src/v*.tar.gz v*.tar.gz $(PROG)-*.pkg.tar.xz diff --git a/src/device.c b/src/device.c index 47c9401..d367c15 100644 --- a/src/device.c +++ b/src/device.c @@ -55,6 +55,7 @@ static const struct { {"YUYV", V4L2_PIX_FMT_YUYV}, {"UYVY", V4L2_PIX_FMT_UYVY}, {"RGB565", V4L2_PIX_FMT_RGB565}, + {"RGB24", V4L2_PIX_FMT_RGB24}, {"JPEG", V4L2_PIX_FMT_MJPEG}, {"JPEG", V4L2_PIX_FMT_JPEG}, }; diff --git a/src/device.h b/src/device.h index 2e10c1f..2db5e1b 100644 --- a/src/device.h +++ b/src/device.h @@ -39,7 +39,7 @@ #define STANDARDS_STR "UNKNOWN, PAL, NTSC, SECAM" #define FORMAT_UNKNOWN -1 -#define FORMATS_STR "YUYV, UYVY, RGB565, JPEG" +#define FORMATS_STR "YUYV, UYVY, RGB565, RGB24, JPEG" struct hw_buffer_t { diff --git a/src/jpeg/encoder.c b/src/jpeg/encoder.c index 2e925eb..6db9767 100644 --- a/src/jpeg/encoder.c +++ b/src/jpeg/encoder.c @@ -50,18 +50,19 @@ struct _mjpg_destination_mgr { static void _jpeg_set_dest_picture(j_compress_ptr jpeg, unsigned char *picture, unsigned long *written); static void _jpeg_write_scanlines_yuyv( - struct jpeg_compress_struct *jpeg, - unsigned char *line_buffer, const unsigned char *data, + struct jpeg_compress_struct *jpeg, const unsigned char *data, unsigned width, unsigned height); static void _jpeg_write_scanlines_uyvy( - struct jpeg_compress_struct *jpeg, - unsigned char *line_buffer, const unsigned char *data, + struct jpeg_compress_struct *jpeg, const unsigned char *data, unsigned width, unsigned height); static void _jpeg_write_scanlines_rgb565( - struct jpeg_compress_struct *jpeg, - unsigned char *line_buffer, const unsigned char *data, + struct jpeg_compress_struct *jpeg, const unsigned char *data, + unsigned width, unsigned height); + +static void _jpeg_write_scanlines_rgb24( + struct jpeg_compress_struct *jpeg, const unsigned char *data, unsigned width, unsigned height); static void _jpeg_init_destination(j_compress_ptr jpeg); @@ -74,9 +75,6 @@ void jpeg_encoder_compress_buffer(struct device_t *dev, unsigned index, unsigned struct jpeg_compress_struct jpeg; struct jpeg_error_mgr jpeg_error; - unsigned char *line_buffer; - - A_CALLOC(line_buffer, dev->run->width * 3); jpeg.err = jpeg_std_error(&jpeg_error); jpeg_create_compress(&jpeg); @@ -94,14 +92,15 @@ void jpeg_encoder_compress_buffer(struct device_t *dev, unsigned index, unsigned jpeg_start_compress(&jpeg, TRUE); -# define WRITE_SCANLINES(_func) \ - _func(&jpeg, line_buffer, dev->run->hw_buffers[index].start, dev->run->width, dev->run->height) +# define WRITE_SCANLINES(_format, _func) \ + case _format: { _func(&jpeg, dev->run->hw_buffers[index].start, dev->run->width, dev->run->height); break; } switch (dev->run->format) { // https://www.fourcc.org/yuv.php - case V4L2_PIX_FMT_YUYV: WRITE_SCANLINES(_jpeg_write_scanlines_yuyv); break; - case V4L2_PIX_FMT_UYVY: WRITE_SCANLINES(_jpeg_write_scanlines_uyvy); break; - case V4L2_PIX_FMT_RGB565: WRITE_SCANLINES(_jpeg_write_scanlines_rgb565); break; + WRITE_SCANLINES(V4L2_PIX_FMT_YUYV, _jpeg_write_scanlines_yuyv); + 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_RGB24, _jpeg_write_scanlines_rgb24); default: assert(0 && "Unsupported input format for JPEG compressor"); } @@ -111,7 +110,6 @@ void jpeg_encoder_compress_buffer(struct device_t *dev, unsigned index, unsigned // https://stackoverflow.com/questions/19857766/error-handling-in-libjpeg jpeg_finish_compress(&jpeg); jpeg_destroy_compress(&jpeg); - free(line_buffer); assert(dev->run->pictures[index].size > 0); assert(dev->run->pictures[index].size <= dev->run->max_picture_size); } @@ -136,13 +134,15 @@ static void _jpeg_set_dest_picture(j_compress_ptr jpeg, unsigned char *picture, #define NORM_COMPONENT(_x) (((_x) > 255) ? 255 : (((_x) < 0) ? 0 : (_x))) static void _jpeg_write_scanlines_yuyv( - struct jpeg_compress_struct *jpeg, - unsigned char *line_buffer, const unsigned char *data, + struct jpeg_compress_struct *jpeg, const unsigned char *data, unsigned width, unsigned height) { + unsigned char *line_buffer; JSAMPROW scanlines[1]; unsigned z = 0; + A_CALLOC(line_buffer, width * 3); + while (jpeg->next_scanline < height) { unsigned char *ptr = line_buffer; @@ -168,17 +168,21 @@ static void _jpeg_write_scanlines_yuyv( scanlines[0] = line_buffer; jpeg_write_scanlines(jpeg, scanlines, 1); } + + free(line_buffer); } static void _jpeg_write_scanlines_uyvy( - struct jpeg_compress_struct *jpeg, - unsigned char *line_buffer, const unsigned char *data, + struct jpeg_compress_struct *jpeg, const unsigned char *data, unsigned width, unsigned height) { + unsigned char *line_buffer; JSAMPROW scanlines[1]; unsigned z = 0; - while(jpeg->next_scanline < height) { + A_CALLOC(line_buffer, width * 3); + + while (jpeg->next_scanline < height) { unsigned char *ptr = line_buffer; for(unsigned x = 0; x < width; ++x) { @@ -203,18 +207,22 @@ static void _jpeg_write_scanlines_uyvy( scanlines[0] = line_buffer; jpeg_write_scanlines(jpeg, scanlines, 1); } + + free(line_buffer); } #undef NORM_COMPONENT static void _jpeg_write_scanlines_rgb565( - struct jpeg_compress_struct *jpeg, - unsigned char *line_buffer, const unsigned char *data, + struct jpeg_compress_struct *jpeg, const unsigned char *data, unsigned width, unsigned height) { + unsigned char *line_buffer; JSAMPROW scanlines[1]; - while(jpeg->next_scanline < height) { + A_CALLOC(line_buffer, width * 3); + + while (jpeg->next_scanline < height) { unsigned char *ptr = line_buffer; for(unsigned x = 0; x < width; ++x) { @@ -230,6 +238,20 @@ static void _jpeg_write_scanlines_rgb565( scanlines[0] = line_buffer; jpeg_write_scanlines(jpeg, scanlines, 1); } + + free(line_buffer); +} + +static void _jpeg_write_scanlines_rgb24( + struct jpeg_compress_struct *jpeg, const unsigned char *data, + unsigned width, unsigned height) { + + JSAMPROW scanlines[1]; + + while (jpeg->next_scanline < height) { + scanlines[0] = (unsigned char *)(data + jpeg->next_scanline * width * 3); + jpeg_write_scanlines(jpeg, scanlines, 1); + } } #define JPEG_OUTPUT_BUFFER_SIZE 4096 diff --git a/src/omx/encoder.c b/src/omx/encoder.c index 3ee86ab..198fa4c 100644 --- a/src/omx/encoder.c +++ b/src/omx/encoder.c @@ -295,23 +295,32 @@ static int _omx_setup_input(struct omx_encoder_t *omx, struct device_t *dev) { portdef.format.image.nFrameWidth = dev->run->width; portdef.format.image.nFrameHeight = dev->run->height; portdef.format.image.nStride = 0; -# define ALIGN(_x, _y) (((_x) + ((_y) - 1)) & ~((_y) - 1)) - portdef.format.image.nSliceHeight = ALIGN(dev->run->height, 16); -# undef ALIGN +# define ALIGN_HEIGHT(_x, _y) (((_x) + ((_y) - 1)) & ~((_y) - 1)) + portdef.format.image.nSliceHeight = ALIGN_HEIGHT(dev->run->height, 16); +# undef ALIGN_HEIGHT portdef.format.image.bFlagErrorConcealment = OMX_FALSE; portdef.format.image.eCompressionFormat = OMX_IMAGE_CodingUnused; portdef.nBufferSize = dev->run->max_picture_size; +# define MAP_FORMAT(_v4l2_format, _omx_format) \ + case _v4l2_format: { portdef.format.image.eColorFormat = _omx_format; break; } + switch (dev->run->format) { // https://www.fourcc.org/yuv.php // Also see comments inside OMX_IVCommon.h - case V4L2_PIX_FMT_YUYV: portdef.format.image.eColorFormat = OMX_COLOR_FormatYCbYCr; break; - case V4L2_PIX_FMT_UYVY: portdef.format.image.eColorFormat = OMX_COLOR_FormatCbYCrY; break; - case V4L2_PIX_FMT_RGB565: portdef.format.image.eColorFormat = OMX_COLOR_Format16bitRGB565; break; - // TODO: Check RGB565 + OMX. I don't have any USB devices which supports it. + MAP_FORMAT(V4L2_PIX_FMT_YUYV, OMX_COLOR_FormatYCbYCr); + MAP_FORMAT(V4L2_PIX_FMT_UYVY, OMX_COLOR_FormatCbYCrY); + MAP_FORMAT(V4L2_PIX_FMT_RGB565, OMX_COLOR_Format16bitRGB565); + MAP_FORMAT(V4L2_PIX_FMT_RGB24, OMX_COLOR_Format24bitRGB888); + // TODO: найти устройство с RGB565 и протестить его. + // FIXME: RGB24 не работает нормально, нижняя половина экрана зеленая. + // FIXME: Китайский EasyCap тоже не работает, мусор на экране. + // Вероятно обе проблемы вызваны некорректной реализацией OMX на пае. default: assert(0 && "Unsupported input format for OMX JPEG compressor"); } +# undef MAP_FORMAT + if (component_set_portdef(&omx->encoder, &portdef) < 0) { return -1; }