summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiego Biurrun <diego@biurrun.de>2016-06-18 13:01:14 +0200
committerAnton Khirnov <anton@khirnov.net>2016-07-25 13:57:02 +0200
commit5312d7a47f638a9c6eb0dbddaf74080b17786e38 (patch)
tree2236348b2cbe79685bcf22af17f61b1186ed5a02
parent0ae2b2a6d0a01637cc10d5b46cbc8b280529e865 (diff)
cfhd: Parse subband tags after header parsing is finished
-rw-r--r--libavcodec/cfhd.c97
1 files changed, 48 insertions, 49 deletions
diff --git a/libavcodec/cfhd.c b/libavcodec/cfhd.c
index d237d08a2b..20dacd1705 100644
--- a/libavcodec/cfhd.c
+++ b/libavcodec/cfhd.c
@@ -253,10 +253,30 @@ static int alloc_buffers(AVCodecContext *avctx)
#define PARAM_ChannelHeight 105
#define PARAM_PrescaleShift 109
-static int parse_header_tag(AVCodecContext *avctx, CFHDContext *s,
- GetByteContext *gb, int16_t tag, uint16_t data,
- int *planes)
+static int parse_tag(AVCodecContext *avctx, CFHDContext *s, GetByteContext *gb,
+ int16_t *tag_, uint16_t *value, int *planes)
{
+ /* Bit weird but implement the tag parsing as the spec says */
+ uint16_t tagu = bytestream2_get_be16(gb);
+ int16_t tag = tagu;
+ int8_t tag8 = tagu >> 8;
+ uint16_t abstag = abs(tag);
+ int8_t abs_tag8 = abs(tag8);
+ uint16_t data = bytestream2_get_be16(gb);
+ *tag_ = tag;
+ *value = data;
+
+ if (abs_tag8 >= 0x60 && abs_tag8 <= 0x6F) {
+ av_log(avctx, AV_LOG_DEBUG, "large len %"PRIX16"\n",
+ ((tagu & 0xFF) << 16) | data);
+ return 0;
+ } else if (abstag >= 0x4000 && abstag <= 0x40FF) {
+ av_log(avctx, AV_LOG_DEBUG, "Small chunk length %"PRIu16" %s\n",
+ data * 4, tag < 0 ? "optional" : "required");
+ bytestream2_skipu(gb, data * 4);
+ return 0;
+ }
+
switch (tag) {
case 1:
av_log(avctx, AV_LOG_DEBUG, "Sample type? %"PRIu16"\n", data);
@@ -406,18 +426,6 @@ static int parse_header_tag(AVCodecContext *avctx, CFHDContext *s,
av_log(avctx, AV_LOG_DEBUG, "Prescale shift (VC-5): %"PRIX16"\n",
data);
break;
- default:
- av_log(avctx, AV_LOG_DEBUG,
- "Unknown header tag %"PRId16" data %"PRIX16"\n", tag, data);
- }
-
- return 0;
-}
-
-static int parse_subband_tag(AVCodecContext *avctx, CFHDContext *s, int16_t tag,
- uint16_t data)
-{
- switch (tag) {
case 27:
av_log(avctx, AV_LOG_DEBUG, "Lowpass width %"PRIu16"\n", data);
if (data < 2 || data > s->plane[s->channel_num].band[0][0].a_width) {
@@ -463,7 +471,7 @@ static int parse_subband_tag(AVCodecContext *avctx, CFHDContext *s, int16_t tag,
break;
default:
av_log(avctx, AV_LOG_DEBUG,
- "Unknown subband tag %"PRId16" data %"PRIX16"\n", tag, data);
+ "Unknown tag %"PRId16" data %"PRIX16"\n", tag, data);
}
return 0;
@@ -678,6 +686,8 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame,
GetByteContext gb;
ThreadFrame frame = { .f = data };
int ret = 0, planes, plane, got_buffer = 0;
+ int16_t tag;
+ uint16_t value;
s->coded_format = AV_PIX_FMT_YUV422P10;
init_frame_defaults(s);
@@ -686,51 +696,40 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame,
bytestream2_init(&gb, avpkt->data, avpkt->size);
while (bytestream2_get_bytes_left(&gb) > 4) {
- /* Bit weird but implement the tag parsing as the spec says */
- uint16_t tagu = bytestream2_get_be16(&gb);
- int16_t tag = tagu;
- int8_t tag8 = tagu >> 8;
- uint16_t abstag = abs(tag);
- int8_t abs_tag8 = abs(tag8);
- uint16_t data = bytestream2_get_be16(&gb);
-
- if (abs_tag8 >= 0x60 && abs_tag8 <= 0x6F) {
- av_log(avctx, AV_LOG_DEBUG, "large len %"PRIX16"\n",
- ((tagu & 0xFF) << 16) | data);
- } else if (abstag >= 0x4000 && abstag <= 0x40FF) {
- av_log(avctx, AV_LOG_DEBUG, "Small chunk length %"PRIu16" %s\n",
- data * 4, tag < 0 ? "optional" : "required");
- bytestream2_skipu(&gb, data * 4);
- } else if ((ret = parse_header_tag(avctx, s, &gb, tag, data, &planes)) < 0)
+ if ((ret = parse_tag(avctx, s, &gb, &tag, &value, &planes)) < 0)
break;
/* Some kind of end of header tag */
- if (tag == 4 && data == 0x1A4A && s->coded_width && s->coded_height &&
- s->coded_format != AV_PIX_FMT_NONE) {
- if (s->a_width != s->coded_width || s->a_height != s->coded_height ||
- s->a_format != s->coded_format) {
+ if (tag == 4 && value == 0x1A4A)
+ break;
+ }
+
+ if (s->coded_width && s->coded_height && s->coded_format != AV_PIX_FMT_NONE) {
+ if (s->a_width != s->coded_width || s->a_height != s->coded_height ||
+ s->a_format != s->coded_format) {
+ free_buffers(avctx);
+ if ((ret = alloc_buffers(avctx)) < 0) {
free_buffers(avctx);
- if ((ret = alloc_buffers(avctx)) < 0) {
- free_buffers(avctx);
- return ret;
- }
+ return ret;
}
+ }
- if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0)
- return ret;
+ if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0)
+ return ret;
- s->coded_width = 0;
- s->coded_height = 0;
- s->coded_format = AV_PIX_FMT_NONE;
- got_buffer = 1;
- }
+ s->coded_width = 0;
+ s->coded_height = 0;
+ s->coded_format = AV_PIX_FMT_NONE;
+ got_buffer = 1;
+ }
- if ((ret = parse_subband_tag(avctx, s, tag, data)) < 0)
+ while (bytestream2_get_bytes_left(&gb) > 4) {
+ if ((ret = parse_tag(avctx, s, &gb, &tag, &value, &planes)) < 0)
break;
if (s->a_width && s->a_height) {
int16_t *coeff_data = s->plane[s->channel_num].subband[s->subband_num_actual];
- if (tag == 4 && data == 0x0F0F) {
+ if (tag == 4 && value == 0x0F0F) {
if ((ret = read_lowpass_coeffs(avctx, s, &gb, coeff_data)) < 0)
return ret;
} else if (tag == 55 && s->subband_num_actual != 255) {