mirror of
https://github.com/nyanmisaka/mpp.git
synced 2025-10-17 14:40:44 +08:00
[jpegd_parser]: skip unhandled jpeg section
Change-Id: I621a4f09a49d886b7db13324ef1fe69952986567 Signed-off-by: Hertz Wang <wangh@rock-chips.com>
This commit is contained in:
@@ -45,7 +45,8 @@ static RK_S32 jpegd_find_marker(const RK_U8 **pbuf_ptr, const RK_U8 *buf_end)
|
|||||||
val = *buf_ptr++;
|
val = *buf_ptr++;
|
||||||
goto found;
|
goto found;
|
||||||
} else if ((v == 0x89) && (v2 == 0x50)) {
|
} else if ((v == 0x89) && (v2 == 0x50)) {
|
||||||
mpp_log("input img maybe png format,check it\n");
|
// many usb camera go here, log if set jpegd debug
|
||||||
|
jpegd_dbg_marker("input img maybe png format,check it\n");
|
||||||
}
|
}
|
||||||
skipped++;
|
skipped++;
|
||||||
}
|
}
|
||||||
@@ -167,64 +168,35 @@ static MPP_RET jpeg_judge_yuv_mode(JpegdCtx *ctx)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline RK_U16 jpegd_read_len(BitReadCtx_t *gb) {
|
||||||
|
RK_U8 lh, ll;
|
||||||
|
READ_BITS(gb, 8, &lh);
|
||||||
|
READ_BITS(gb, 8, &ll);
|
||||||
|
return (((RK_U16)lh) << 8) | ((RK_U16)ll);
|
||||||
|
|
||||||
static MPP_RET jpegd_decode_app(JpegdCtx *ctx)
|
__BITREAD_ERR:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MPP_RET jpegd_skip_section(JpegdCtx *ctx)
|
||||||
{
|
{
|
||||||
MPP_RET ret = MPP_NOK;
|
|
||||||
BitReadCtx_t *gb = ctx->bit_ctx;
|
BitReadCtx_t *gb = ctx->bit_ctx;
|
||||||
JpegdSyntax *syntax = ctx->syntax;
|
RK_U16 len = 0;
|
||||||
RK_U32 len, id;
|
|
||||||
|
|
||||||
READ_BITS(gb, 16, &len);
|
if (gb->bytes_left_ < 2)
|
||||||
if (len < 6 || len > gb->bytes_left_) {
|
return MPP_ERR_READ_BIT;
|
||||||
|
len = jpegd_read_len(gb);
|
||||||
|
if (len < 2 /* invalid marker */ || (RK_U32)len - 2 > gb->bytes_left_) {
|
||||||
/* too short length or bytes is not enough */
|
/* too short length or bytes is not enough */
|
||||||
return MPP_ERR_READ_BIT;
|
return MPP_ERR_READ_BIT;
|
||||||
}
|
}
|
||||||
|
if (len > 2)
|
||||||
|
SKIP_BITS(gb, (len - 2) * 8);
|
||||||
|
|
||||||
READ_BITS_LONG(gb, 32, &id);
|
return MPP_OK;
|
||||||
len -= 6;
|
|
||||||
|
|
||||||
if (id == JPEG_IDENTIFIER('J', 'F', 'I', 'F')) {
|
|
||||||
int t_w, t_h, v1, v2;
|
|
||||||
SKIP_BITS(gb, 8); /* the trailing zero-byte */
|
|
||||||
|
|
||||||
/* version */
|
|
||||||
READ_BITS(gb, 8, &v1);
|
|
||||||
READ_BITS(gb, 8, &v2);
|
|
||||||
|
|
||||||
SKIP_BITS(gb, 8);
|
|
||||||
|
|
||||||
READ_BITS(gb, 16, &syntax->hor_density);
|
|
||||||
READ_BITS(gb, 16, &syntax->ver_density);
|
|
||||||
if (syntax->hor_density <= 0
|
|
||||||
|| syntax->ver_density <= 0) {
|
|
||||||
syntax->hor_density = 0;
|
|
||||||
syntax->ver_density = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
jpegd_dbg_marker("mjpeg: JFIF header found (version: %x.%x) SAR=%d/%d\n",
|
|
||||||
v1, v2, syntax->hor_density, syntax->ver_density);
|
|
||||||
|
|
||||||
len -= 8;
|
|
||||||
if (len >= 2) {
|
|
||||||
READ_BITS(gb, 8, &t_w);
|
|
||||||
READ_BITS(gb, 8, &t_h);
|
|
||||||
if (t_w && t_h) {
|
|
||||||
/* skip thumbnail */
|
|
||||||
if (len - 10 - (t_w * t_h * 3) > 0)
|
|
||||||
len -= t_w * t_h * 3;
|
|
||||||
}
|
|
||||||
len -= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = MPP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
__BITREAD_ERR:
|
__BITREAD_ERR:
|
||||||
if (ret != MPP_OK)
|
return MPP_NOK;
|
||||||
jpegd_dbg_syntax("bit read error, but it does not matter!\n");
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static MPP_RET jpegd_decode_dht(JpegdCtx *ctx)
|
static MPP_RET jpegd_decode_dht(JpegdCtx *ctx)
|
||||||
@@ -236,7 +208,7 @@ static MPP_RET jpegd_decode_dht(JpegdCtx *ctx)
|
|||||||
RK_U32 table_type, table_id;
|
RK_U32 table_type, table_id;
|
||||||
RK_U32 i, code_max;
|
RK_U32 i, code_max;
|
||||||
|
|
||||||
READ_BITS(gb, 16, &len);
|
len = jpegd_read_len(gb);
|
||||||
len -= 2; /* Huffman Table Length */
|
len -= 2; /* Huffman Table Length */
|
||||||
|
|
||||||
if (len > gb->bytes_left_) {
|
if (len > gb->bytes_left_) {
|
||||||
@@ -336,7 +308,7 @@ static MPP_RET jpegd_decode_dqt(JpegdCtx *ctx)
|
|||||||
int index, i;
|
int index, i;
|
||||||
RK_U16 value;
|
RK_U16 value;
|
||||||
|
|
||||||
READ_BITS(gb, 16, &len);
|
len = jpegd_read_len(gb);
|
||||||
len -= 2; /* quantize tables length */
|
len -= 2; /* quantize tables length */
|
||||||
|
|
||||||
if (len > gb->bytes_left_) {
|
if (len > gb->bytes_left_) {
|
||||||
@@ -399,7 +371,7 @@ static MPP_RET jpegd_decode_com(JpegdCtx *ctx)
|
|||||||
BitReadCtx_t *gb = ctx->bit_ctx;
|
BitReadCtx_t *gb = ctx->bit_ctx;
|
||||||
RK_U32 len;
|
RK_U32 len;
|
||||||
|
|
||||||
READ_BITS(gb, 16, &len);
|
len = jpegd_read_len(gb);
|
||||||
if (len >= 2 && len - 2 <= gb->bytes_left_) {
|
if (len >= 2 && len - 2 <= gb->bytes_left_) {
|
||||||
RK_U32 i;
|
RK_U32 i;
|
||||||
RK_U8 *cbuf = mpp_calloc_size(RK_U8, len - 1);
|
RK_U8 *cbuf = mpp_calloc_size(RK_U8, len - 1);
|
||||||
@@ -438,7 +410,7 @@ static MPP_RET jpegd_decode_sof(JpegdCtx *ctx)
|
|||||||
RK_U32 width, height;
|
RK_U32 width, height;
|
||||||
RK_U32 nb_components, value;
|
RK_U32 nb_components, value;
|
||||||
|
|
||||||
READ_BITS(gb, 16, &len);
|
len = jpegd_read_len(gb);
|
||||||
if (len > gb->bytes_left_) {
|
if (len > gb->bytes_left_) {
|
||||||
mpp_err_f("len %d is too large\n", len);
|
mpp_err_f("len %d is too large\n", len);
|
||||||
return MPP_ERR_STREAM;
|
return MPP_ERR_STREAM;
|
||||||
@@ -533,7 +505,7 @@ static MPP_RET jpegd_decode_sos(JpegdCtx *ctx)
|
|||||||
RK_U32 len, nb_components, value;
|
RK_U32 len, nb_components, value;
|
||||||
RK_U32 id, i, index;
|
RK_U32 id, i, index;
|
||||||
|
|
||||||
READ_BITS(gb, 16, &len);
|
len = jpegd_read_len(gb);
|
||||||
if (len > gb->bytes_left_) {
|
if (len > gb->bytes_left_) {
|
||||||
mpp_err_f("len %d is too large\n", len);
|
mpp_err_f("len %d is too large\n", len);
|
||||||
return MPP_ERR_STREAM;
|
return MPP_ERR_STREAM;
|
||||||
@@ -622,7 +594,7 @@ static MPP_RET jpegd_decode_dri(JpegdCtx *ctx)
|
|||||||
JpegdSyntax *s = ctx->syntax;
|
JpegdSyntax *s = ctx->syntax;
|
||||||
RK_U32 len;
|
RK_U32 len;
|
||||||
|
|
||||||
READ_BITS(gb, 16, &len);
|
len = jpegd_read_len(gb);
|
||||||
if (len != DRI_MARKER_LENGTH) {
|
if (len != DRI_MARKER_LENGTH) {
|
||||||
mpp_err_f("DRI length %d error\n", len);
|
mpp_err_f("DRI length %d error\n", len);
|
||||||
return MPP_ERR_STREAM;
|
return MPP_ERR_STREAM;
|
||||||
@@ -779,17 +751,23 @@ static MPP_RET jpegd_decode_frame(JpegdCtx *ctx)
|
|||||||
{
|
{
|
||||||
jpegd_dbg_func("enter\n");
|
jpegd_dbg_func("enter\n");
|
||||||
MPP_RET ret = MPP_OK;
|
MPP_RET ret = MPP_OK;
|
||||||
const RK_U8 *buf = ctx->buffer;
|
const RK_U8 *const buf = ctx->buffer;
|
||||||
RK_U32 buf_size = ctx->buf_size;
|
RK_U32 buf_size = ctx->buf_size;
|
||||||
const RK_U8 *buf_end, *buf_ptr;
|
|
||||||
BitReadCtx_t *gb = ctx->bit_ctx;
|
BitReadCtx_t *gb = ctx->bit_ctx;
|
||||||
JpegdSyntax *syntax = ctx->syntax;
|
JpegdSyntax *syntax = ctx->syntax;
|
||||||
RK_S32 start_code;
|
RK_S32 start_code;
|
||||||
|
|
||||||
buf_ptr = buf;
|
const RK_U8 *buf_ptr = buf;
|
||||||
buf_end = buf + buf_size;
|
const RK_U8 *const buf_end = buf + buf_size;
|
||||||
|
|
||||||
|
if (buf_size < 4 || *buf_ptr != 0xFF || *(buf_ptr + 1) != SOI) {
|
||||||
|
// not jpeg
|
||||||
|
ret = MPP_ERR_STREAM;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
while (buf_ptr < buf_end) {
|
while (buf_ptr < buf_end) {
|
||||||
|
int section_finish = 1;
|
||||||
/* find start marker */
|
/* find start marker */
|
||||||
start_code = jpegd_find_marker(&buf_ptr, buf_end);
|
start_code = jpegd_find_marker(&buf_ptr, buf_end);
|
||||||
if (start_code < 0) {
|
if (start_code < 0) {
|
||||||
@@ -808,9 +786,6 @@ static MPP_RET jpegd_decode_frame(JpegdCtx *ctx)
|
|||||||
if (start_code >= RST0 && start_code <= RST7) {
|
if (start_code >= RST0 && start_code <= RST7) {
|
||||||
/* nothing to do with RSTn */
|
/* nothing to do with RSTn */
|
||||||
jpegd_dbg_syntax("restart marker: %d\n", start_code & 0x0f);
|
jpegd_dbg_syntax("restart marker: %d\n", start_code & 0x0f);
|
||||||
} else if (start_code >= APP0 && start_code <= APP15) {
|
|
||||||
/* APP fields */
|
|
||||||
jpegd_decode_app(ctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (start_code) {
|
switch (start_code) {
|
||||||
@@ -900,26 +875,41 @@ static MPP_RET jpegd_decode_frame(JpegdCtx *ctx)
|
|||||||
case SOF48:
|
case SOF48:
|
||||||
case LSE:
|
case LSE:
|
||||||
case JPG:
|
case JPG:
|
||||||
|
section_finish = 0;
|
||||||
mpp_log("jpeg: unsupported coding type (0x%x)\n", start_code);
|
mpp_log("jpeg: unsupported coding type (0x%x)\n", start_code);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
section_finish = 0;
|
||||||
jpegd_dbg_marker("unhandled coding type(0x%x) in switch..case..\n",
|
jpegd_dbg_marker("unhandled coding type(0x%x) in switch..case..\n",
|
||||||
start_code);
|
start_code);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!section_finish) {
|
||||||
|
if ((ret = jpegd_skip_section(ctx)) != MPP_OK) {
|
||||||
|
jpegd_dbg_marker("Fail to skip section 0xFF%02x!\n",
|
||||||
|
start_code);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
buf_ptr = ctx->bit_ctx->data_;
|
buf_ptr = ctx->bit_ctx->data_;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!syntax->eoi_found) {
|
|
||||||
mpp_err_f("EOI marker not found!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (!syntax->dht_found) {
|
if (!syntax->dht_found) {
|
||||||
jpegd_dbg_marker("sorry, DHT is not found!\n");
|
jpegd_dbg_marker("sorry, DHT is not found!\n");
|
||||||
jpegd_setup_default_dht(ctx);
|
jpegd_setup_default_dht(ctx);
|
||||||
}
|
}
|
||||||
|
if (!syntax->eoi_found) {
|
||||||
|
// recheck again, maybe we done wrong
|
||||||
|
const RK_U8 *buf_end_ = buf_end;
|
||||||
|
while (*(--buf_end_) == 0)
|
||||||
|
buf_size--;
|
||||||
|
if (buf_size < 2 || *(buf_end_ - 1) != 0xFF || *buf_end_ != EOI) {
|
||||||
|
mpp_err_f("EOI marker not found!\n");
|
||||||
|
ret = MPP_ERR_STREAM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
jpegd_dbg_func("exit\n");
|
jpegd_dbg_func("exit\n");
|
||||||
@@ -1275,6 +1265,8 @@ static MPP_RET jpegd_init(void *ctx, ParserCfg *parser_cfg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mpp_env_get_u32("jpegd_debug", &jpegd_debug, 0);
|
mpp_env_get_u32("jpegd_debug", &jpegd_debug, 0);
|
||||||
|
// mpp only support baseline
|
||||||
|
JpegCtx->scan_all_marker = 0;
|
||||||
|
|
||||||
const char* soc_name = NULL;
|
const char* soc_name = NULL;
|
||||||
soc_name = mpp_get_soc_name();
|
soc_name = mpp_get_soc_name();
|
||||||
@@ -1283,10 +1275,9 @@ static MPP_RET jpegd_init(void *ctx, ParserCfg *parser_cfg)
|
|||||||
* just scan parts of markers to reduce CPU's occupancy
|
* just scan parts of markers to reduce CPU's occupancy
|
||||||
*/
|
*/
|
||||||
JpegCtx->copy_flag = 0;
|
JpegCtx->copy_flag = 0;
|
||||||
JpegCtx->scan_all_marker = 0;
|
|
||||||
} else {
|
} else {
|
||||||
|
// TODO: do not copy if input provides valid fd and virtual ptr
|
||||||
JpegCtx->copy_flag = 1;
|
JpegCtx->copy_flag = 1;
|
||||||
JpegCtx->scan_all_marker = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JpegCtx->frame_slots = parser_cfg->frame_slots;
|
JpegCtx->frame_slots = parser_cfg->frame_slots;
|
||||||
|
Reference in New Issue
Block a user