[FFmpeg-devel] [PATCH v4 1/2] libavcodec/jpeg2000dec.c: Add functions and modify structs for PPT marker support
gautamramk at gmail.com
gautamramk at gmail.com
Sat Mar 28 14:28:09 EET 2020
From: Gautam Ramakrishnan <gautamramk at gmail.com>
This patch adds support for the PPT marker. It breaks down the
jpeg2000_decode_packet() function to decode headers and data
separately.
---
libavcodec/jpeg2000dec.c | 200 +++++++++++++++++++++++++++++++++------
1 file changed, 170 insertions(+), 30 deletions(-)
diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 7103cd6ceb..44b3e7e41b 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -83,8 +83,12 @@ typedef struct Jpeg2000Tile {
Jpeg2000QuantStyle qntsty[4];
Jpeg2000POC poc;
Jpeg2000TilePart tile_part[32];
- uint16_t tp_idx; // Tile-part index
- int coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}}
+ uint8_t has_ppt; // whether this tile has a ppt marker
+ uint8_t *packed_headers; // contains packed headers. Used only along with PPT marker
+ int packed_headers_size; // size in bytes of the packed headers
+ GetByteContext packed_headers_stream; // byte context corresponding to packed headers
+ uint16_t tp_idx; // Tile-part index
+ int coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}}
} Jpeg2000Tile;
typedef struct Jpeg2000DecoderContext {
@@ -855,6 +859,38 @@ static int get_plt(Jpeg2000DecoderContext *s, int n)
return 0;
}
+static int get_ppt(Jpeg2000DecoderContext *s, int n)
+{
+ Jpeg2000Tile *tile;
+
+ tile = &s->tile[s->curtileno];
+
+ av_assert1(s->curtileno >= 0);
+ if (tile->tp_idx != 0) {
+ av_log(s->avctx, AV_LOG_ERROR,
+ "PPT marker can occur only on first tile part of a tile.\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ tile->has_ppt = 1; // this tile has a ppt marker
+/* Zppt = */ bytestream2_get_byte(&s->g);
+ if (!tile->packed_headers) {
+ tile->packed_headers = av_malloc_array(n - 3, sizeof(uint8_t));
+ memcpy(tile->packed_headers, s->g.buffer, sizeof(uint8_t)*(n - 3));
+ tile->packed_headers_size = n - 3;
+ } else {
+ tile->packed_headers = av_realloc_array(tile->packed_headers,
+ tile->packed_headers_size + n - 3,
+ sizeof(uint8_t));
+ memcpy(tile->packed_headers + tile->packed_headers_size,
+ s->g.buffer, sizeof(uint8_t)*(n - 3));
+ tile->packed_headers_size += n - 3;
+ }
+ bytestream2_skip(&s->g, n - 3);
+
+ return 0;
+}
+
static int init_tile(Jpeg2000DecoderContext *s, int tileno)
{
int compno;
@@ -927,30 +963,38 @@ static int getlblockinc(Jpeg2000DecoderContext *s)
return res;
}
-static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, int *tp_index,
- Jpeg2000CodingStyle *codsty,
- Jpeg2000ResLevel *rlevel, int precno,
- int layno, uint8_t *expn, int numgbits)
+static int jpeg2000_decode_packet_header(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
+ int *tp_index,
+ Jpeg2000CodingStyle *codsty,
+ Jpeg2000ResLevel *rlevel, int precno,
+ int layno, uint8_t *expn, int numgbits,
+ int *process_data)
{
int bandno, cblkno, ret, nb_code_blocks;
- int cwsno;
- if (layno < rlevel->band[0].prec[precno].decoded_layers)
+ if (layno < rlevel->band[0].prec[precno].decoded_layers) {
+ *process_data = 0;
return 0;
+ }
rlevel->band[0].prec[precno].decoded_layers = layno + 1;
- if (bytestream2_get_bytes_left(&s->g) == 0 && s->bit_index == 8) {
- if (*tp_index < FF_ARRAY_ELEMS(tile->tile_part) - 1) {
- s->g = tile->tile_part[++(*tp_index)].tpg;
+ if (tile->has_ppt) {
+ s->g = tile->packed_headers_stream;
+ } else {
+ s->g = tile->tile_part[*tp_index].tpg;
+ if (bytestream2_get_bytes_left(&s->g) == 0 && s->bit_index == 8) {
+ if (*tp_index < FF_ARRAY_ELEMS(tile->tile_part) - 1) {
+ s->g = tile->tile_part[++(*tp_index)].tpg;
+ }
}
+ if (bytestream2_peek_be32(&s->g) == JPEG2000_SOP_FIXED_BYTES)
+ bytestream2_skip(&s->g, JPEG2000_SOP_BYTE_LENGTH);
}
- if (bytestream2_peek_be32(&s->g) == JPEG2000_SOP_FIXED_BYTES)
- bytestream2_skip(&s->g, JPEG2000_SOP_BYTE_LENGTH);
-
if (!(ret = get_bits(s, 1))) {
jpeg2000_flush(s);
- return 0;
+ *process_data = 0;
+ goto end;
} else if (ret < 0)
return ret;
@@ -1055,6 +1099,34 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
else
av_log(s->avctx, AV_LOG_ERROR, "EPH marker not found. instead %X\n", bytestream2_peek_be32(&s->g));
}
+end:
+ if (tile->has_ppt)
+ tile->packed_headers_stream = s->g;
+ else
+ tile->tile_part[*tp_index].tpg = s->g;
+ return 0;
+}
+
+static int jpeg2000_decode_packet_data(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
+ int *tp_index,
+ Jpeg2000CodingStyle *codsty,
+ Jpeg2000ResLevel *rlevel, int precno,
+ int layno, uint8_t *expn, int numgbits)
+{
+ int bandno, cblkno, nb_code_blocks;
+ int cwsno;
+
+ s->g = tile->tile_part[*tp_index].tpg;
+ if (tile->has_ppt) {
+ if (bytestream2_get_bytes_left(&s->g) == 0 && s->bit_index == 8) {
+ if (*tp_index < FF_ARRAY_ELEMS(tile->tile_part) - 1) {
+ s->g = tile->tile_part[++(*tp_index)].tpg;
+ }
+ }
+ if (bytestream2_peek_be32(&s->g) == JPEG2000_SOP_FIXED_BYTES)
+ bytestream2_skip(&s->g, JPEG2000_SOP_BYTE_LENGTH);
+ }
+
for (bandno = 0; bandno < rlevel->nbands; bandno++) {
Jpeg2000Band *band = rlevel->band + bandno;
@@ -1097,6 +1169,7 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
av_freep(&cblk->lengthinc);
}
}
+ tile->tile_part[*tp_index].tpg = s->g;
return 0;
}
@@ -1124,13 +1197,25 @@ static int jpeg2000_decode_packets_po_iteration(Jpeg2000DecoderContext *s, Jpeg2
Jpeg2000ResLevel *rlevel = tile->comp[compno].reslevel +
reslevelno;
ok_reslevel = 1;
- for (precno = 0; precno < rlevel->num_precincts_x * rlevel->num_precincts_y; precno++)
- if ((ret = jpeg2000_decode_packet(s, tile, tp_index,
+ for (precno = 0; precno < rlevel->num_precincts_x * rlevel->num_precincts_y; precno++) {
+ int process_data = 1;
+ if ((ret = jpeg2000_decode_packet_header(s, tile, tp_index,
+ codsty, rlevel,
+ precno, layno,
+ qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
+ qntsty->nguardbits, &process_data)) < 0)
+ return ret;
+
+ if (!process_data)
+ continue;
+
+ if ((ret = jpeg2000_decode_packet_data(s, tile, tp_index,
codsty, rlevel,
precno, layno,
qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
qntsty->nguardbits)) < 0)
return ret;
+ }
}
}
}
@@ -1150,13 +1235,25 @@ static int jpeg2000_decode_packets_po_iteration(Jpeg2000DecoderContext *s, Jpeg2
Jpeg2000ResLevel *rlevel = tile->comp[compno].reslevel +
reslevelno;
ok_reslevel = 1;
- for (precno = 0; precno < rlevel->num_precincts_x * rlevel->num_precincts_y; precno++)
- if ((ret = jpeg2000_decode_packet(s, tile, tp_index,
+ for (precno = 0; precno < rlevel->num_precincts_x * rlevel->num_precincts_y; precno++) {
+ int process_data = 1;
+ if ((ret = jpeg2000_decode_packet_header(s, tile, tp_index,
+ codsty, rlevel,
+ precno, layno,
+ qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
+ qntsty->nguardbits, &process_data)) < 0)
+ return ret;
+
+ if (!process_data)
+ continue;
+
+ if ((ret = jpeg2000_decode_packet_data(s, tile, tp_index,
codsty, rlevel,
precno, layno,
qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
qntsty->nguardbits)) < 0)
return ret;
+ }
}
}
}
@@ -1218,7 +1315,19 @@ static int jpeg2000_decode_packets_po_iteration(Jpeg2000DecoderContext *s, Jpeg2
}
for (layno = 0; layno < LYEpoc; layno++) {
- if ((ret = jpeg2000_decode_packet(s, tile, tp_index, codsty, rlevel,
+ int process_data = 1;
+ if ((ret = jpeg2000_decode_packet_header(s, tile, tp_index,
+ codsty, rlevel,
+ precno, layno,
+ qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
+ qntsty->nguardbits, &process_data)) < 0)
+ return ret;
+
+ if (!process_data)
+ continue;
+
+ if ((ret = jpeg2000_decode_packet_data(s, tile, tp_index,
+ codsty, rlevel,
precno, layno,
qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
qntsty->nguardbits)) < 0)
@@ -1288,14 +1397,25 @@ static int jpeg2000_decode_packets_po_iteration(Jpeg2000DecoderContext *s, Jpeg2
continue;
}
- for (layno = 0; layno < LYEpoc; layno++) {
- if ((ret = jpeg2000_decode_packet(s, tile, tp_index,
- codsty, rlevel,
- precno, layno,
- qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
- qntsty->nguardbits)) < 0)
- return ret;
- }
+ for (layno = 0; layno < LYEpoc; layno++) {
+ int process_data = 1;
+ if ((ret = jpeg2000_decode_packet_header(s, tile, tp_index,
+ codsty, rlevel,
+ precno, layno,
+ qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
+ qntsty->nguardbits, &process_data)) < 0)
+ return ret;
+
+ if (!process_data)
+ continue;
+
+ if ((ret = jpeg2000_decode_packet_data(s, tile, tp_index,
+ codsty, rlevel,
+ precno, layno,
+ qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
+ qntsty->nguardbits)) < 0)
+ return ret;
+ }
}
}
}
@@ -1359,7 +1479,19 @@ static int jpeg2000_decode_packets_po_iteration(Jpeg2000DecoderContext *s, Jpeg2
}
for (layno = 0; layno < LYEpoc; layno++) {
- if ((ret = jpeg2000_decode_packet(s, tile, tp_index, codsty, rlevel,
+ int process_data = 1;
+ if ((ret = jpeg2000_decode_packet_header(s, tile, tp_index,
+ codsty, rlevel,
+ precno, layno,
+ qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
+ qntsty->nguardbits, &process_data)) < 0)
+ return ret;
+
+ if (!process_data)
+ continue;
+
+ if ((ret = jpeg2000_decode_packet_data(s, tile, tp_index,
+ codsty, rlevel,
precno, layno,
qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
qntsty->nguardbits)) < 0)
@@ -1929,6 +2061,11 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s)
av_log(s->avctx, AV_LOG_ERROR, "Invalid tpend\n");
return AVERROR_INVALIDDATA;
}
+
+ if (tile->has_ppt && tile->tp_idx == 0) {
+ bytestream2_init(&tile->packed_headers_stream, tile->packed_headers, tile->packed_headers_size);
+ }
+
bytestream2_init(&tp->tpg, s->g.buffer, tp->tp_end - s->g.buffer);
bytestream2_skip(&s->g, tp->tp_end - s->g.buffer);
@@ -1991,6 +2128,10 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s)
// Packet length, tile-part header
ret = get_plt(s, len);
break;
+ case JPEG2000_PPT:
+ // Packed headers, tile-part header
+ ret = get_ppt(s, len);
+ break;
default:
av_log(s->avctx, AV_LOG_ERROR,
"unsupported marker 0x%.4"PRIX16" at pos 0x%X\n",
@@ -2020,7 +2161,6 @@ static int jpeg2000_read_bitstream_packets(Jpeg2000DecoderContext *s)
if ((ret = init_tile(s, tileno)) < 0)
return ret;
- s->g = tile->tile_part[0].tpg;
if ((ret = jpeg2000_decode_packets(s, tile)) < 0)
return ret;
}
--
2.17.1
More information about the ffmpeg-devel
mailing list