From ea5ec968744b4b11839f3ab479c45ae676d6cea0 Mon Sep 17 00:00:00 2001 From: Devaev Maxim Date: Fri, 28 Sep 2018 03:51:49 +0300 Subject: [PATCH] omx: disabled exif, optional ijg tables, refactoring --- Makefile | 3 +++ src/device.c | 1 - src/device.h | 1 - src/encoder.c | 9 +++++--- src/encoder.h | 10 ++++----- src/jpeg/encoder.c | 4 ++-- src/jpeg/encoder.h | 2 +- src/main.c | 24 ++++++++++++++------ src/omx/encoder.c | 56 ++++++++++++++++++++++++++++++++++++---------- src/omx/encoder.h | 4 ++-- src/stream.c | 1 - 11 files changed, 80 insertions(+), 35 deletions(-) diff --git a/Makefile b/Makefile index ef867f5..6c0f8b7 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,8 @@ PREFIX ?= /usr/local CFLAGS ?= -O3 LDFLAGS ?= + +# ===== CC = gcc LIBS = -lm -ljpeg -pthread -levent -levent_pthreads override CFLAGS += -c -std=c99 -Wall -Wextra -D_GNU_SOURCE @@ -18,6 +20,7 @@ override CFLAGS += -DOMX_ENCODER -DOMX_SKIP64BIT -I/opt/vc/include endif +# ===== all: $(SOURCES) $(PROG) diff --git a/src/device.c b/src/device.c index 9798066..d7f0024 100644 --- a/src/device.c +++ b/src/device.c @@ -84,7 +84,6 @@ struct device_t *device_init() { dev->standard = V4L2_STD_UNKNOWN; dev->n_buffers = max_u(sysconf(_SC_NPROCESSORS_ONLN), 1) + 1; dev->n_workers = dev->n_buffers; - dev->jpeg_quality = 80; dev->timeout = 1; dev->error_timeout = 1; dev->run = run; diff --git a/src/device.h b/src/device.h index 5f4f037..963ed39 100644 --- a/src/device.h +++ b/src/device.h @@ -70,7 +70,6 @@ struct device_t { unsigned n_workers; unsigned every_frame; unsigned min_frame_size; - unsigned jpeg_quality; unsigned timeout; unsigned error_timeout; diff --git a/src/encoder.c b/src/encoder.c index c2e9069..1c1529f 100644 --- a/src/encoder.c +++ b/src/encoder.c @@ -50,6 +50,7 @@ struct encoder_t *encoder_init() { A_CALLOC(encoder, 1); encoder->type = ENCODER_TYPE_CPU; + encoder->quality = 80; return encoder; } @@ -60,6 +61,8 @@ void encoder_prepare(struct encoder_t *encoder) { LOG_DEBUG("Initializing encoder ..."); } + LOG_INFO("Using JPEG quality: %d%%", encoder->quality); + # ifdef OMX_ENCODER if (encoder->type == ENCODER_TYPE_OMX) { if ((encoder->omx = omx_encoder_init()) == NULL) { @@ -104,7 +107,7 @@ void encoder_prepare_for_device(struct encoder_t *encoder, struct device_t *dev) #pragma GCC diagnostic pop # ifdef OMX_ENCODER if (encoder->type == ENCODER_TYPE_OMX) { - if (omx_encoder_prepare_for_device(encoder->omx, dev) < 0) { + if (omx_encoder_prepare_for_device(encoder->omx, dev, encoder->quality, encoder->omx_use_ijg) < 0) { goto use_fallback; } if (dev->run->n_workers > 1) { @@ -125,11 +128,11 @@ void encoder_prepare_for_device(struct encoder_t *encoder, struct device_t *dev) # pragma GCC diagnostic pop } -int encoder_compress_buffer(struct encoder_t *encoder, struct device_t *dev, int index) { +int encoder_compress_buffer(struct encoder_t *encoder, struct device_t *dev, const unsigned index) { assert(encoder->type != ENCODER_TYPE_UNKNOWN); if (encoder->type == ENCODER_TYPE_CPU) { - jpeg_encoder_compress_buffer(dev, index); + jpeg_encoder_compress_buffer(dev, index, encoder->quality); } # ifdef OMX_ENCODER else if (encoder->type == ENCODER_TYPE_OMX) { diff --git a/src/encoder.h b/src/encoder.h index c4cb94e..4efdf7f 100644 --- a/src/encoder.h +++ b/src/encoder.h @@ -39,17 +39,17 @@ enum encoder_type_t { ENCODER_TYPE_UNKNOWN, // Only for encoder_parse_type() and main() ENCODER_TYPE_CPU, - #ifdef OMX_ENCODER ENCODER_TYPE_OMX, #endif }; struct encoder_t { - enum encoder_type_t type; - + enum encoder_type_t type; + unsigned quality; #ifdef OMX_ENCODER - struct omx_encoder_t *omx; + bool omx_use_ijg; + struct omx_encoder_t *omx; #endif }; @@ -61,4 +61,4 @@ enum encoder_type_t encoder_parse_type(const char *const str); void encoder_prepare(struct encoder_t *encoder); void encoder_prepare_for_device(struct encoder_t *encoder, struct device_t *dev); -int encoder_compress_buffer(struct encoder_t *encoder, struct device_t *dev, int index); +int encoder_compress_buffer(struct encoder_t *encoder, struct device_t *dev, const unsigned index); diff --git a/src/jpeg/encoder.c b/src/jpeg/encoder.c index 005f2ac..a70e188 100644 --- a/src/jpeg/encoder.c +++ b/src/jpeg/encoder.c @@ -68,7 +68,7 @@ static boolean _jpeg_empty_output_buffer(j_compress_ptr jpeg); static void _jpeg_term_destination(j_compress_ptr jpeg); -void jpeg_encoder_compress_buffer(struct device_t *dev, int index) { +void jpeg_encoder_compress_buffer(struct device_t *dev, const unsigned index, const unsigned quality) { // This function based on compress_image_to_jpeg() from mjpg-streamer struct jpeg_compress_struct jpeg; @@ -89,7 +89,7 @@ void jpeg_encoder_compress_buffer(struct device_t *dev, int index) { jpeg.in_color_space = JCS_RGB; jpeg_set_defaults(&jpeg); - jpeg_set_quality(&jpeg, dev->jpeg_quality, TRUE); + jpeg_set_quality(&jpeg, quality, TRUE); jpeg_start_compress(&jpeg, TRUE); diff --git a/src/jpeg/encoder.h b/src/jpeg/encoder.h index 25701d6..fa4a041 100644 --- a/src/jpeg/encoder.h +++ b/src/jpeg/encoder.h @@ -24,4 +24,4 @@ #include "../device.h" -void jpeg_encoder_compress_buffer(struct device_t *dev, int index); +void jpeg_encoder_compress_buffer(struct device_t *dev, const unsigned index, const unsigned quality); diff --git a/src/main.c b/src/main.c index f71aa92..93e4d7f 100644 --- a/src/main.c +++ b/src/main.c @@ -52,8 +52,11 @@ static const struct option _long_opts[] = { {"dv-timings", no_argument, NULL, 't'}, {"buffers", required_argument, NULL, 'b'}, {"workers", required_argument, NULL, 'w'}, - {"jpeg-quality", required_argument, NULL, 'q'}, + {"quality", required_argument, NULL, 'q'}, {"encoder", required_argument, NULL, 'c'}, +# ifdef OMX_ENCODER + {"encoder-omx-use-ijg", required_argument, NULL, 500}, +# endif {"device-timeout", required_argument, NULL, 1000}, {"device-error-timeout", required_argument, NULL, 1001}, @@ -71,7 +74,7 @@ static const struct option _long_opts[] = { {NULL, 0, NULL, 0}, }; -static void _help(struct device_t *dev, struct http_server_t *server) { +static void _help(struct device_t *dev, struct encoder_t *encoder, struct http_server_t *server) { printf("\nuStreamer - Lightweight and fast MJPG-HTTP streamer\n"); printf("===================================================\n\n"); printf("Version: %s; license: GPLv3\n", VERSION); @@ -94,9 +97,13 @@ static void _help(struct device_t *dev, struct http_server_t *server) { printf(" Each buffer may processed using an intermediate thread.\n"); printf(" Default: %d (number of CPU cores + 1)\n\n", dev->n_buffers); printf(" -w|--workers -- The number of compressing threads. Default: %d (== --buffers).\n\n", dev->n_workers); - printf(" -q|--jpeg-quality -- Set quality of JPEG encoding from 1 to 100 (best). Default: %d.\n\n", dev->jpeg_quality); + printf(" -q|--quality -- Set quality of JPEG encoding from 1 to 100 (best). Default: %d.\n\n", encoder->quality); printf(" --encoder -- Use specified encoder. It may affects to workers number.\n"); printf(" -- Available: %s; default: CPU.\n\n", ENCODER_TYPES_STR); +# ifdef OMX_ENCODER + printf(" --encoder-omx-use-ijg -- Use the standard IJG quality tables when encoding images using OMX.\n"); + printf(" Default: disabled.\n\n"); +# endif printf(" --device-timeout -- Timeout for device querying. Default: %d\n\n", dev->timeout); printf(" --device-error-timeout -- Delay before trying to connect to the device again\n"); printf(" after a timeout. Default: %d\n\n", dev->error_timeout); @@ -156,8 +163,11 @@ static int _parse_options(int argc, char *argv[], struct device_t *dev, struct e case 't': OPT_TRUE(dev->dv_timings); case 'b': OPT_UNSIGNED(dev->n_buffers, "--buffers", 1, 32); case 'w': OPT_UNSIGNED(dev->n_workers, "--workers", 1, 32); - case 'q': OPT_UNSIGNED(dev->jpeg_quality, "--jpeg-quality", 1, 100); - case 'c': OPT_PARSE(encoder->type, encoder_parse_type, ENCODER_TYPE_UNKNOWN, "encoder type") + case 'q': OPT_UNSIGNED(encoder->quality, "--quality", 1, 100); + case 'c': OPT_PARSE(encoder->type, encoder_parse_type, ENCODER_TYPE_UNKNOWN, "encoder type"); +# ifdef OMX_ENCODER + case 500: encoder->omx_use_ijg = true; break; +# endif case 1000: OPT_UNSIGNED(dev->timeout, "--timeout", 1, 60); case 1001: OPT_UNSIGNED(dev->error_timeout, "--error-timeout", 1, 60); @@ -172,7 +182,7 @@ static int _parse_options(int argc, char *argv[], struct device_t *dev, struct e case 5002: log_level = LOG_LEVEL_DEBUG; break; case 5010: OPT_UNSIGNED(log_level, "--log-level", 0, 3); case 0: break; - case 'h': default: _help(dev, server); return -1; + case 'h': default: _help(dev, encoder, server); return -1; } } @@ -245,7 +255,7 @@ int main(int argc, char *argv[]) { LOGGING_INIT; dev = device_init(); - encoder = encoder_init(ENCODER_TYPE_CPU); + encoder = encoder_init(); stream = stream_init(dev, encoder); server = http_server_init(stream); diff --git a/src/omx/encoder.c b/src/omx/encoder.c index ed42463..3a37079 100644 --- a/src/omx/encoder.c +++ b/src/omx/encoder.c @@ -19,6 +19,7 @@ *****************************************************************************/ +#include #include #include #include @@ -28,6 +29,7 @@ #include #include #include +#include #include #include "../logging.h" @@ -46,7 +48,7 @@ static int _omx_init_component(struct omx_encoder_t *omx); static int _omx_init_disable_ports(struct omx_encoder_t *omx); static int _omx_setup_input(struct omx_encoder_t *omx, struct device_t *dev); -static int _omx_setup_output(struct omx_encoder_t *omx, struct device_t *dev); +static int _omx_setup_output(struct omx_encoder_t *omx, const unsigned quality, const bool use_ijg); static int _omx_encoder_clear_ports(struct omx_encoder_t *omx); static OMX_ERRORTYPE _omx_event_handler(UNUSED OMX_HANDLETYPE encoder, @@ -134,7 +136,7 @@ void omx_encoder_destroy(struct omx_encoder_t *omx) { free(omx); } -int omx_encoder_prepare_for_device(struct omx_encoder_t *omx, struct device_t *dev) { +int omx_encoder_prepare_for_device(struct omx_encoder_t *omx, struct device_t *dev, const unsigned quality, const bool use_ijg) { if (component_set_state(&omx->encoder, OMX_StateIdle) < 0) { return -1; } @@ -144,7 +146,7 @@ int omx_encoder_prepare_for_device(struct omx_encoder_t *omx, struct device_t *d if (_omx_setup_input(omx, dev) < 0) { return -1; } - if (_omx_setup_output(omx, dev) < 0) { + if (_omx_setup_output(omx, quality, use_ijg) < 0) { return -1; } if (component_set_state(&omx->encoder, OMX_StateExecuting) < 0) { @@ -153,7 +155,7 @@ int omx_encoder_prepare_for_device(struct omx_encoder_t *omx, struct device_t *d return 0; } -int omx_encoder_compress_buffer(struct omx_encoder_t *omx, struct device_t *dev, int index) { +int omx_encoder_compress_buffer(struct omx_encoder_t *omx, struct device_t *dev, const unsigned index) { OMX_ERRORTYPE error; bool loaded = false; @@ -216,6 +218,8 @@ int omx_encoder_compress_buffer(struct omx_encoder_t *omx, struct device_t *dev, } static int _omx_init_component(struct omx_encoder_t *omx) { + // http://home.nouwen.name/RaspberryPi/documentation/ilcomponents/image_encode.html + OMX_ERRORTYPE error; OMX_CALLBACKTYPE callbacks; @@ -313,10 +317,9 @@ static int _omx_setup_input(struct omx_encoder_t *omx, struct device_t *dev) { return 0; } -static int _omx_setup_output(struct omx_encoder_t *omx, struct device_t *dev) { +static int _omx_setup_output(struct omx_encoder_t *omx, const unsigned quality, const bool use_ijg) { OMX_ERRORTYPE error; OMX_PARAM_PORTDEFINITIONTYPE portdef; - OMX_IMAGE_PARAM_QFACTORTYPE quality_factor; LOG_DEBUG("Setting up OMX JPEG output port ..."); @@ -338,13 +341,42 @@ static int _omx_setup_output(struct omx_encoder_t *omx, struct device_t *dev) { return -1; } - OMX_INIT_STRUCTURE(quality_factor); - quality_factor.nPortIndex = OUTPUT_PORT; - quality_factor.nQFactor = dev->jpeg_quality; + { + OMX_CONFIG_BOOLEANTYPE exif; - if ((error = OMX_SetParameter(omx->encoder, OMX_IndexParamQFactor, &quality_factor)) != OMX_ErrorNone) { - LOG_OMX_ERROR(error, "Can't set OMX JPEG quality"); - return -1; + OMX_INIT_STRUCTURE(exif); + exif.bEnabled = OMX_FALSE; + + if ((error = OMX_SetParameter(omx->encoder, OMX_IndexParamBrcmDisableEXIF, &exif)) != OMX_ErrorNone) { + LOG_OMX_ERROR(error, "Can't disable EXIF on OMX JPEG"); + return -1; + } + } + + if (use_ijg) { + OMX_PARAM_IJGSCALINGTYPE ijg; + + OMX_INIT_STRUCTURE(ijg); + ijg.nPortIndex = OUTPUT_PORT; + ijg.bEnabled = OMX_TRUE; + + if ((error = OMX_SetParameter(omx->encoder, OMX_IndexParamBrcmEnableIJGTableScaling, &ijg)) != OMX_ErrorNone) { + LOG_OMX_ERROR(error, "Can't set OMX JPEG IJG settings"); + return -1; + } + } + + { + OMX_IMAGE_PARAM_QFACTORTYPE qfactor; + + OMX_INIT_STRUCTURE(qfactor); + qfactor.nPortIndex = OUTPUT_PORT; + qfactor.nQFactor = quality; + + if ((error = OMX_SetParameter(omx->encoder, OMX_IndexParamQFactor, &qfactor)) != OMX_ErrorNone) { + LOG_OMX_ERROR(error, "Can't set OMX JPEG quality"); + return -1; + } } if (component_enable_port(&omx->encoder, OUTPUT_PORT) < 0) { diff --git a/src/omx/encoder.h b/src/omx/encoder.h index 6d3f2de..7731d13 100644 --- a/src/omx/encoder.h +++ b/src/omx/encoder.h @@ -49,5 +49,5 @@ struct omx_encoder_t { struct omx_encoder_t *omx_encoder_init(); void omx_encoder_destroy(struct omx_encoder_t *omx); -int omx_encoder_prepare_for_device(struct omx_encoder_t *omx, struct device_t *dev); -int omx_encoder_compress_buffer(struct omx_encoder_t *omx, struct device_t *dev, int index); +int omx_encoder_prepare_for_device(struct omx_encoder_t *omx, struct device_t *dev, const unsigned quality, const bool use_ijg); +int omx_encoder_compress_buffer(struct omx_encoder_t *omx, struct device_t *dev, const unsigned index); diff --git a/src/stream.c b/src/stream.c index d0ac3d7..155a1a6 100644 --- a/src/stream.c +++ b/src/stream.c @@ -78,7 +78,6 @@ void stream_loop(struct stream_t *stream) { pool.workers_stop = &workers_stop; LOG_INFO("Using V4L2 device: %s", stream->dev->path); - LOG_INFO("Using JPEG quality: %d%%", stream->dev->jpeg_quality); while (_stream_init_loop(stream->dev, &pool) == 0) { struct worker_t *oldest_worker = NULL;