---
To be applied on top of v3.
Vittorio
libavcodec/hq_hqa.c | 100 +++++++++++++++++++++++++++---------------------
libavcodec/hq_hqa.h | 3 ++
libavcodec/hq_hqadata.c | 2 +-
3 files changed, 61 insertions(+), 44 deletions(-)
diff --git a/libavcodec/hq_hqa.c b/libavcodec/hq_hqa.c
index 860bb05..1c2105d 100644
--- a/libavcodec/hq_hqa.c
+++ b/libavcodec/hq_hqa.c
@@ -21,6 +21,7 @@
#include <stdint.h>
#include "libavutil/attributes.h"
+#include "libavutil/common.h"
#include "libavutil/intreadwrite.h"
#include "avcodec.h"
@@ -95,20 +96,21 @@ static int hq_decode_mb(HQContext *c, AVFrame *pic,
}
static int hq_decode_frame(HQContext *ctx, AVFrame *pic,
- uint8_t *src, int data_size)
+ int prof_num, size_t data_size)
{
const HQProfile *profile;
GetBitContext gb;
+ const uint8_t *perm, *src = ctx->gbc.buffer;
uint32_t slice_off[21];
- int start_off, next_off;
- const uint8_t *perm;
- int i, slice, ret;
+ int slice, start_off, next_off, i, ret;
- if (src[3] >= NUM_HQ_PROFILES) {
+ if (prof_num >= NUM_HQ_PROFILES) {
profile = &ff_hq_profile[0];
- avpriv_request_sample(ctx->avctx, "Profile %d", src[3]);
- } else
- profile = &ff_hq_profile[src[3]];
+ avpriv_request_sample(ctx->avctx, "HQ Profile %d", prof_num);
+ } else {
+ profile = &ff_hq_profile[prof_num];
+ av_log(ctx->avctx, AV_LOG_VERBOSE, "HQ Profile %d\n", prof_num);
+ }
ctx->avctx->coded_width = FFALIGN(profile->width, 16);
ctx->avctx->coded_height = FFALIGN(profile->height, 16);
@@ -123,8 +125,9 @@ static int hq_decode_frame(HQContext *ctx, AVFrame *pic,
return ret;
}
+ /* Offsets are stored from HQA1 position, so adjust them accordingly. */
for (i = 0; i < profile->num_slices + 1; i++)
- slice_off[i] = AV_RB24(src + 4 + i * 3);
+ slice_off[i] = bytestream2_get_be24(&ctx->gbc) - 4;
next_off = 0;
for (slice = 0; slice < profile->num_slices; slice++) {
@@ -132,11 +135,11 @@ static int hq_decode_frame(HQContext *ctx, AVFrame *pic,
next_off = profile->tab_h * (slice + 1) / profile->num_slices;
perm = profile->perm_tab + start_off * profile->tab_w * 2;
- if (slice_off[slice] < (profile->num_slices + 1) * 3 + 4 ||
+ if (slice_off[slice] < (profile->num_slices + 1) * 3 ||
slice_off[slice] >= slice_off[slice + 1] ||
slice_off[slice + 1] > data_size) {
av_log(ctx->avctx, AV_LOG_ERROR,
- "Invalid slice size %d.\n", data_size);
+ "Invalid slice size %zu.\n", data_size);
break;
}
init_get_bits(&gb, src + slice_off[slice],
@@ -217,16 +220,17 @@ static int hqa_decode_slice(HQContext *ctx, AVFrame *pic,
GetBitContext *gb,
return 0;
}
-static int hqa_decode_frame(HQContext *ctx, AVFrame *pic,
- uint8_t *src, int data_size)
+static int hqa_decode_frame(HQContext *ctx, AVFrame *pic, size_t data_size)
{
GetBitContext gb;
+ const int num_slices = 8;
uint32_t slice_off[9];
int i, slice, ret;
- int width, height, num_slices = 8;
+ int width, height, quant;
+ const uint8_t *src = ctx->gbc.buffer;
- width = AV_RB16(src + 4);
- height = AV_RB16(src + 6);
+ width = bytestream2_get_be16(&ctx->gbc);
+ height = bytestream2_get_be16(&ctx->gbc);
ctx->avctx->coded_width = FFALIGN(width, 16);
ctx->avctx->coded_height = FFALIGN(height, 16);
@@ -235,27 +239,37 @@ static int hqa_decode_frame(HQContext *ctx, AVFrame *pic,
ctx->avctx->bits_per_raw_sample = 8;
ctx->avctx->pix_fmt = AV_PIX_FMT_YUVA422P;
+ av_log(ctx->avctx, AV_LOG_VERBOSE, "HQA Profile\n");
+
+ quant = bytestream2_get_be32(&ctx->gbc);
+ if (quant >= NUM_HQ_QUANTS) {
+ av_log(ctx->avctx, AV_LOG_ERROR,
+ "Invalid quantization matrix %d.\n", quant);
+ return AVERROR_INVALIDDATA;
+ }
+
ret = ff_get_buffer(ctx->avctx, pic, 0);
if (ret < 0) {
av_log(ctx->avctx, AV_LOG_ERROR, "Could not allocate buffer.\n");
return ret;
}
+ /* Offsets are stored from HQA1 position, so adjust them accordingly. */
for (i = 0; i < num_slices + 1; i++)
- slice_off[i] = AV_RB32(src + 12 + i * 4);
+ slice_off[i] = bytestream2_get_be32(&ctx->gbc) - 4;
for (slice = 0; slice < num_slices; slice++) {
- if (slice_off[slice] < (num_slices + 1) * 3 + 4 ||
+ if (slice_off[slice] < (num_slices + 1) * 3 ||
slice_off[slice] >= slice_off[slice + 1] ||
slice_off[slice + 1] > data_size) {
av_log(ctx->avctx, AV_LOG_ERROR,
- "Invalid slice size %d.\n", data_size);
+ "Invalid slice size %zu.\n", data_size);
break;
}
init_get_bits(&gb, src + slice_off[slice],
(slice_off[slice + 1] - slice_off[slice]) * 8);
- ret = hqa_decode_slice(ctx, pic, &gb, src[8], slice, width, height);
+ ret = hqa_decode_slice(ctx, pic, &gb, quant, slice, width, height);
if (ret < 0)
return ret;
}
@@ -268,52 +282,51 @@ static int hq_hqa_decode_frame(AVCodecContext *avctx,
void *data,
{
HQContext *ctx = avctx->priv_data;
AVFrame *pic = data;
- uint8_t *src = avpkt->data;
- uint32_t info_tag, info_size;
- int data_start, ret;
+ uint32_t info_tag;
unsigned int data_size;
+ int tag, ret;
- /* Take into account tag and size. */
- if (avpkt->size < 4 + 4) {
+ bytestream2_init(&ctx->gbc, avpkt->data, avpkt->size);
+ if (bytestream2_get_bytes_left(&ctx->gbc) < 4 + 4) {
av_log(avctx, AV_LOG_ERROR, "Frame is too small (%d).\n", avpkt->size);
return AVERROR_INVALIDDATA;
}
- info_tag = AV_RL32(src);
+ info_tag = bytestream2_get_le32(&ctx->gbc);
if (info_tag == MKTAG('I', 'N', 'F', 'O')) {
int par_x, par_y, field_order;
+ int info_size = bytestream2_get_le32(&ctx->gbc);
- info_size = AV_RL32(src + 4);
- if (info_size != HQ_HQA_INFO_SIZE || info_size + 8 > avpkt->size) {
- av_log(avctx, AV_LOG_ERROR, "Invalid INFO size %d > %d.\n",
- info_size + 8, avpkt->size);
+ if (info_size != HQ_HQA_INFO_SIZE ||
+ bytestream2_get_bytes_left(&ctx->gbc) < info_size) {
+ av_log(avctx, AV_LOG_ERROR, "Invalid INFO size (%d).\n",
info_size);
return AVERROR_INVALIDDATA;
}
- /* Skip unknown 8 bytes, then parse aspect ratio. */
- par_x = AV_RL32(src + 16);
- par_y = AV_RL32(src + 20);
+ /* Parse aspect ratio. */
+ bytestream2_skip(&ctx->gbc, 8); // unknown
+ par_x = bytestream2_get_le32(&ctx->gbc);
+ par_y = bytestream2_get_le32(&ctx->gbc);
if (par_x && par_y)
av_reduce(&avctx->sample_aspect_ratio.num,
&avctx->sample_aspect_ratio.den,
par_x, par_y, 255);
- /* Skip unknown RDRT tag. */
+ bytestream2_skip(&ctx->gbc, 16); // unknown RDRT tag
/* Parse FIEL tag. */
- field_order = AV_RL32(src + 48);
+ bytestream2_skip(&ctx->gbc, 8); // 'FIEL' and 4 bytes 0
+ field_order = bytestream2_get_le32(&ctx->gbc);
switch (field_order) {
case 0: avctx->field_order = AV_FIELD_TT; break;
case 1: avctx->field_order = AV_FIELD_BB; break;
case 2: avctx->field_order = AV_FIELD_PROGRESSIVE; break;
}
- src += info_size + 8;
+ bytestream2_skip(&ctx->gbc, 12);
}
- data_start = src - avpkt->data;
- data_size = avpkt->size - data_start;
-
+ data_size = bytestream2_get_bytes_left(&ctx->gbc);
if (data_size < 4) {
av_log(avctx, AV_LOG_ERROR, "Frame is too small (%d).\n", data_size);
return AVERROR_INVALIDDATA;
@@ -322,10 +335,11 @@ static int hq_hqa_decode_frame(AVCodecContext *avctx,
void *data,
/* HQ defines dimensions and number of slices, so walking order is too;
* HQA has no size constraint and features a fixed number of slices,
* thus there is a separate scheme for it. */
- if (src[0] == 'U' && src[1] == 'V' && src[2] == 'C') {
- ret = hq_decode_frame(ctx, pic, src, data_size);
- } else if (src[0] == 'H' && src[1] == 'Q' && src[2] == 'A') {
- ret = hqa_decode_frame(ctx, pic, src, data_size);
+ tag = bytestream2_get_le32(&ctx->gbc);
+ if ((tag & 0x00FFFFFF) == (MKTAG('U', 'V', 'C', ' ') & 0x00FFFFFF)) {
+ ret = hq_decode_frame(ctx, pic, tag >> 24, data_size);
+ } else if (tag == MKTAG('H', 'Q', 'A', '1')) {
+ ret = hqa_decode_frame(ctx, pic, data_size);
} else {
av_log(avctx, AV_LOG_ERROR, "Not a HQ/HQA frame.\n");
return AVERROR_INVALIDDATA;
diff --git a/libavcodec/hq_hqa.h b/libavcodec/hq_hqa.h
index 3fc0a92..6bd858d 100644
--- a/libavcodec/hq_hqa.h
+++ b/libavcodec/hq_hqa.h
@@ -25,14 +25,17 @@
#include "avcodec.h"
#include "get_bits.h"
+#include "bytestream.h"
#include "hq_hqadsp.h"
#define NUM_HQ_AC_ENTRIES 746
#define NUM_HQ_PROFILES 22
+#define NUM_HQ_QUANTS 16
typedef struct HQContext {
AVCodecContext *avctx;
HQDSPContext hqhqadsp;
+ GetByteContext gbc;
VLC hq_ac_vlc;
VLC hqa_cbp_vlc;
diff --git a/libavcodec/hq_hqadata.c b/libavcodec/hq_hqadata.c
index d80d0a4..4ade753 100644
--- a/libavcodec/hq_hqadata.c
+++ b/libavcodec/hq_hqadata.c
@@ -1123,7 +1123,7 @@ static const int32_t qmat4D[MAT_SIZE] = {
0x24CF8B9, 0x384AC0F, 0x709581F, 0x3CDBBA7,
};
-const int32_t *const ff_hq_quants[16][2][4] = {
+const int32_t *const ff_hq_quants[NUM_HQ_QUANTS][2][4] = {
{ { qmat00, qmat02, qmat06, qmat0E }, { qmat01, qmat03, qmat07, qmat0F } },
{ { qmat02, qmat06, qmat0E, qmat16 }, { qmat03, qmat07, qmat0F, qmat17 } },
{ { qmat04, qmat0A, qmat12, qmat1E }, { qmat05, qmat0B, qmat13, qmat1F } },
--
1.9.5 (Apple Git-50.3)
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel