diff --git a/src/libs/h264/unjpeg.c b/src/libs/common/unjpeg.c similarity index 80% rename from src/libs/h264/unjpeg.c rename to src/libs/common/unjpeg.c index 163070f..ba5ffde 100644 --- a/src/libs/h264/unjpeg.c +++ b/src/libs/common/unjpeg.c @@ -26,19 +26,19 @@ typedef struct { struct jpeg_error_mgr mgr; // Default manager jmp_buf jmp; + const frame_s *frame; } _jpeg_error_manager_s; static void _jpeg_error_handler(j_common_ptr jpeg); -int unjpeg(const frame_s *src, frame_s *dest) { +int unjpeg(const frame_s *src, frame_s *dest, bool decode) { volatile int retval = 0; struct jpeg_decompress_struct jpeg; jpeg_create_decompress(&jpeg); - frame_realloc_data(dest, ((src->width * src->height) << 1) * 2); frame_copy_meta(src, dest); dest->format = V4L2_PIX_FMT_RGB24; dest->used = 0; @@ -48,6 +48,7 @@ int unjpeg(const frame_s *src, frame_s *dest) { _jpeg_error_manager_s jpeg_error; jpeg.err = jpeg_std_error((struct jpeg_error_mgr *)&jpeg_error); jpeg_error.mgr.error_exit = _jpeg_error_handler; + jpeg_error.frame = src; if (setjmp(jpeg_error.jmp) < 0) { retval = -1; goto done; @@ -58,18 +59,22 @@ int unjpeg(const frame_s *src, frame_s *dest) { jpeg.out_color_space = JCS_RGB; jpeg_start_decompress(&jpeg); - const unsigned row_stride = jpeg.output_width * jpeg.output_components; - JSAMPARRAY scanlines; - scanlines = (*jpeg.mem->alloc_sarray)((j_common_ptr) &jpeg, JPOOL_IMAGE, row_stride, 1); + if (decode) { + const unsigned row_stride = jpeg.output_width * jpeg.output_components; - while (jpeg.output_scanline < jpeg.output_height) { - jpeg_read_scanlines(&jpeg, scanlines, 1); - frame_append_data(dest, scanlines[0], row_stride); + JSAMPARRAY scanlines; + scanlines = (*jpeg.mem->alloc_sarray)((j_common_ptr) &jpeg, JPOOL_IMAGE, row_stride, 1); + + frame_realloc_data(dest, ((src->width * src->height) << 1) * 2); + while (jpeg.output_scanline < jpeg.output_height) { + jpeg_read_scanlines(&jpeg, scanlines, 1); + frame_append_data(dest, scanlines[0], row_stride); + } + + jpeg_finish_decompress(&jpeg); } - jpeg_finish_decompress(&jpeg); - dest->width = jpeg.output_width; dest->height = jpeg.output_height; @@ -83,6 +88,6 @@ static void _jpeg_error_handler(j_common_ptr jpeg) { char msg[JMSG_LENGTH_MAX]; (*jpeg_error->mgr.format_message)(jpeg, msg); - LOG_ERROR("Can't decompress JPEG: %s", msg); + LOG_ERROR("Can't decompress %s JPEG: %s", jpeg_error->frame->name, msg); longjmp(jpeg_error->jmp, -1); } diff --git a/src/libs/h264/unjpeg.h b/src/libs/common/unjpeg.h similarity index 93% rename from src/libs/h264/unjpeg.h rename to src/libs/common/unjpeg.h index 8141550..5b7e686 100644 --- a/src/libs/h264/unjpeg.h +++ b/src/libs/common/unjpeg.h @@ -23,6 +23,7 @@ #pragma once #include +#include #include #include #include @@ -32,8 +33,8 @@ #include #include -#include "../common/logging.h" -#include "../common/frame.h" +#include "logging.h" +#include "frame.h" -int unjpeg(const frame_s *src, frame_s *dest); +int unjpeg(const frame_s *src, frame_s *dest, bool decode); diff --git a/src/libs/h264/encoder.c b/src/libs/h264/encoder.c index 5c85a0c..7f9103f 100644 --- a/src/libs/h264/encoder.c +++ b/src/libs/h264/encoder.c @@ -87,7 +87,7 @@ int h264_encoder_compress(h264_encoder_s *encoder, const frame_s *src, frame_s * if (src->format == V4L2_PIX_FMT_MJPEG || src->format == V4L2_PIX_FMT_JPEG) { LOG_DEBUG("Input frame format is JPEG; decoding ..."); - if (unjpeg(src, RUN(tmp)) < 0) { + if (unjpeg(src, RUN(tmp), true) < 0) { return -1; } src = RUN(tmp); diff --git a/src/libs/h264/encoder.h b/src/libs/h264/encoder.h index 28472d5..32175d1 100644 --- a/src/libs/h264/encoder.h +++ b/src/libs/h264/encoder.h @@ -38,8 +38,7 @@ #include "../common/tools.h" #include "../common/logging.h" #include "../common/frame.h" - -#include "unjpeg.h" +#include "../common/unjpeg.h" typedef struct { diff --git a/src/ustreamer/blank.c b/src/ustreamer/blank.c index da8d60e..25cc6f8 100644 --- a/src/ustreamer/blank.c +++ b/src/ustreamer/blank.c @@ -23,18 +23,9 @@ #include "blank.h" -typedef struct { - struct jpeg_error_mgr mgr; // Default manager - jmp_buf jmp; -} _jpeg_error_manager_s; - - static frame_s *_init_internal(void); static frame_s *_init_external(const char *path); -static int _jpeg_read_geometry(FILE *fp, unsigned *width, unsigned *height); -static void _jpeg_error_handler(j_common_ptr jpeg); - frame_s *blank_frame_init(const char *path) { frame_s *blank = NULL; @@ -72,15 +63,6 @@ static frame_s *_init_external(const char *path) { goto error; } - if (_jpeg_read_geometry(fp, &blank->width, &blank->height) < 0) { - goto error; - } - - if (fseek(fp, 0, SEEK_SET) < 0) { - LOG_PERROR("Can't seek to begin of the blank placeholder"); - goto error; - } - # define CHUNK_SIZE ((size_t)(100 * 1024)) while (true) { if (blank->used + CHUNK_SIZE >= blank->allocated) { @@ -92,7 +74,7 @@ static frame_s *_init_external(const char *path) { if (readed < CHUNK_SIZE) { if (feof(fp)) { - goto ok; + break; } else { LOG_PERROR("Can't read blank placeholder"); goto error; @@ -101,6 +83,17 @@ static frame_s *_init_external(const char *path) { } # undef CHUNK_SIZE + frame_s *decoded = frame_init("blank_external_decoded"); + if (unjpeg(blank, decoded, false) < 0) { + frame_destroy(decoded); + goto error; + } + blank->width = decoded->width; + blank->height = decoded->height; + frame_destroy(decoded); + + goto ok; + error: frame_destroy(blank); blank = NULL; @@ -112,36 +105,3 @@ static frame_s *_init_external(const char *path) { return blank; } - -static int _jpeg_read_geometry(FILE *fp, unsigned *width, unsigned *height) { - struct jpeg_decompress_struct jpeg; - jpeg_create_decompress(&jpeg); - - // https://stackoverflow.com/questions/19857766/error-handling-in-libjpeg - _jpeg_error_manager_s jpeg_error; - jpeg.err = jpeg_std_error((struct jpeg_error_mgr *)&jpeg_error); - jpeg_error.mgr.error_exit = _jpeg_error_handler; - if (setjmp(jpeg_error.jmp) < 0) { - jpeg_destroy_decompress(&jpeg); - return -1; - } - - jpeg_stdio_src(&jpeg, fp); - jpeg_read_header(&jpeg, TRUE); - jpeg_start_decompress(&jpeg); - - *width = jpeg.output_width; - *height = jpeg.output_height; - - jpeg_destroy_decompress(&jpeg); - return 0; -} - -static void _jpeg_error_handler(j_common_ptr jpeg) { - _jpeg_error_manager_s *jpeg_error = (_jpeg_error_manager_s *)jpeg->err; - char msg[JMSG_LENGTH_MAX]; - - (*jpeg_error->mgr.format_message)(jpeg, msg); - LOG_ERROR("Invalid blank placeholder: %s", msg); - longjmp(jpeg_error->jmp, -1); -} diff --git a/src/ustreamer/blank.h b/src/ustreamer/blank.h index d7acf3a..7108db2 100644 --- a/src/ustreamer/blank.h +++ b/src/ustreamer/blank.h @@ -24,14 +24,13 @@ #include #include -#include -#include #include #include "../libs/common/tools.h" #include "../libs/common/logging.h" #include "../libs/common/frame.h" +#include "../libs/common/unjpeg.h" #include "data/blank_jpeg.h"