mirror of
https://github.com/pikvm/ustreamer.git
synced 2026-03-13 19:13:41 +00:00
reused unjpeg
This commit is contained in:
@@ -26,19 +26,19 @@
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
struct jpeg_error_mgr mgr; // Default manager
|
struct jpeg_error_mgr mgr; // Default manager
|
||||||
jmp_buf jmp;
|
jmp_buf jmp;
|
||||||
|
const frame_s *frame;
|
||||||
} _jpeg_error_manager_s;
|
} _jpeg_error_manager_s;
|
||||||
|
|
||||||
|
|
||||||
static void _jpeg_error_handler(j_common_ptr jpeg);
|
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;
|
volatile int retval = 0;
|
||||||
|
|
||||||
struct jpeg_decompress_struct jpeg;
|
struct jpeg_decompress_struct jpeg;
|
||||||
jpeg_create_decompress(&jpeg);
|
jpeg_create_decompress(&jpeg);
|
||||||
|
|
||||||
frame_realloc_data(dest, ((src->width * src->height) << 1) * 2);
|
|
||||||
frame_copy_meta(src, dest);
|
frame_copy_meta(src, dest);
|
||||||
dest->format = V4L2_PIX_FMT_RGB24;
|
dest->format = V4L2_PIX_FMT_RGB24;
|
||||||
dest->used = 0;
|
dest->used = 0;
|
||||||
@@ -48,6 +48,7 @@ int unjpeg(const frame_s *src, frame_s *dest) {
|
|||||||
_jpeg_error_manager_s jpeg_error;
|
_jpeg_error_manager_s jpeg_error;
|
||||||
jpeg.err = jpeg_std_error((struct jpeg_error_mgr *)&jpeg_error);
|
jpeg.err = jpeg_std_error((struct jpeg_error_mgr *)&jpeg_error);
|
||||||
jpeg_error.mgr.error_exit = _jpeg_error_handler;
|
jpeg_error.mgr.error_exit = _jpeg_error_handler;
|
||||||
|
jpeg_error.frame = src;
|
||||||
if (setjmp(jpeg_error.jmp) < 0) {
|
if (setjmp(jpeg_error.jmp) < 0) {
|
||||||
retval = -1;
|
retval = -1;
|
||||||
goto done;
|
goto done;
|
||||||
@@ -58,18 +59,22 @@ int unjpeg(const frame_s *src, frame_s *dest) {
|
|||||||
jpeg.out_color_space = JCS_RGB;
|
jpeg.out_color_space = JCS_RGB;
|
||||||
|
|
||||||
jpeg_start_decompress(&jpeg);
|
jpeg_start_decompress(&jpeg);
|
||||||
const unsigned row_stride = jpeg.output_width * jpeg.output_components;
|
|
||||||
|
|
||||||
JSAMPARRAY scanlines;
|
if (decode) {
|
||||||
scanlines = (*jpeg.mem->alloc_sarray)((j_common_ptr) &jpeg, JPOOL_IMAGE, row_stride, 1);
|
const unsigned row_stride = jpeg.output_width * jpeg.output_components;
|
||||||
|
|
||||||
while (jpeg.output_scanline < jpeg.output_height) {
|
JSAMPARRAY scanlines;
|
||||||
jpeg_read_scanlines(&jpeg, scanlines, 1);
|
scanlines = (*jpeg.mem->alloc_sarray)((j_common_ptr) &jpeg, JPOOL_IMAGE, row_stride, 1);
|
||||||
frame_append_data(dest, scanlines[0], row_stride);
|
|
||||||
|
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->width = jpeg.output_width;
|
||||||
dest->height = jpeg.output_height;
|
dest->height = jpeg.output_height;
|
||||||
|
|
||||||
@@ -83,6 +88,6 @@ static void _jpeg_error_handler(j_common_ptr jpeg) {
|
|||||||
char msg[JMSG_LENGTH_MAX];
|
char msg[JMSG_LENGTH_MAX];
|
||||||
|
|
||||||
(*jpeg_error->mgr.format_message)(jpeg, msg);
|
(*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);
|
longjmp(jpeg_error->jmp, -1);
|
||||||
}
|
}
|
||||||
@@ -23,6 +23,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@@ -32,8 +33,8 @@
|
|||||||
#include <jpeglib.h>
|
#include <jpeglib.h>
|
||||||
#include <linux/videodev2.h>
|
#include <linux/videodev2.h>
|
||||||
|
|
||||||
#include "../common/logging.h"
|
#include "logging.h"
|
||||||
#include "../common/frame.h"
|
#include "frame.h"
|
||||||
|
|
||||||
|
|
||||||
int unjpeg(const frame_s *src, frame_s *dest);
|
int unjpeg(const frame_s *src, frame_s *dest, bool decode);
|
||||||
@@ -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) {
|
if (src->format == V4L2_PIX_FMT_MJPEG || src->format == V4L2_PIX_FMT_JPEG) {
|
||||||
LOG_DEBUG("Input frame format is JPEG; decoding ...");
|
LOG_DEBUG("Input frame format is JPEG; decoding ...");
|
||||||
if (unjpeg(src, RUN(tmp)) < 0) {
|
if (unjpeg(src, RUN(tmp), true) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
src = RUN(tmp);
|
src = RUN(tmp);
|
||||||
|
|||||||
@@ -38,8 +38,7 @@
|
|||||||
#include "../common/tools.h"
|
#include "../common/tools.h"
|
||||||
#include "../common/logging.h"
|
#include "../common/logging.h"
|
||||||
#include "../common/frame.h"
|
#include "../common/frame.h"
|
||||||
|
#include "../common/unjpeg.h"
|
||||||
#include "unjpeg.h"
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -23,18 +23,9 @@
|
|||||||
#include "blank.h"
|
#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_internal(void);
|
||||||
static frame_s *_init_external(const char *path);
|
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_frame_init(const char *path) {
|
||||||
frame_s *blank = NULL;
|
frame_s *blank = NULL;
|
||||||
@@ -72,15 +63,6 @@ static frame_s *_init_external(const char *path) {
|
|||||||
goto error;
|
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))
|
# define CHUNK_SIZE ((size_t)(100 * 1024))
|
||||||
while (true) {
|
while (true) {
|
||||||
if (blank->used + CHUNK_SIZE >= blank->allocated) {
|
if (blank->used + CHUNK_SIZE >= blank->allocated) {
|
||||||
@@ -92,7 +74,7 @@ static frame_s *_init_external(const char *path) {
|
|||||||
|
|
||||||
if (readed < CHUNK_SIZE) {
|
if (readed < CHUNK_SIZE) {
|
||||||
if (feof(fp)) {
|
if (feof(fp)) {
|
||||||
goto ok;
|
break;
|
||||||
} else {
|
} else {
|
||||||
LOG_PERROR("Can't read blank placeholder");
|
LOG_PERROR("Can't read blank placeholder");
|
||||||
goto error;
|
goto error;
|
||||||
@@ -101,6 +83,17 @@ static frame_s *_init_external(const char *path) {
|
|||||||
}
|
}
|
||||||
# undef CHUNK_SIZE
|
# 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:
|
error:
|
||||||
frame_destroy(blank);
|
frame_destroy(blank);
|
||||||
blank = NULL;
|
blank = NULL;
|
||||||
@@ -112,36 +105,3 @@ static frame_s *_init_external(const char *path) {
|
|||||||
|
|
||||||
return blank;
|
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);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -24,14 +24,13 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <setjmp.h>
|
|
||||||
|
|
||||||
#include <jpeglib.h>
|
|
||||||
#include <linux/videodev2.h>
|
#include <linux/videodev2.h>
|
||||||
|
|
||||||
#include "../libs/common/tools.h"
|
#include "../libs/common/tools.h"
|
||||||
#include "../libs/common/logging.h"
|
#include "../libs/common/logging.h"
|
||||||
#include "../libs/common/frame.h"
|
#include "../libs/common/frame.h"
|
||||||
|
#include "../libs/common/unjpeg.h"
|
||||||
|
|
||||||
#include "data/blank_jpeg.h"
|
#include "data/blank_jpeg.h"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user