---
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

Reply via email to