Imported Upstream version 6.1
[platform/upstream/ffmpeg.git] / libavcodec / magicyuv.c
index 634d45c..3f6348b 100644 (file)
 #include "avcodec.h"
 #include "bytestream.h"
 #include "codec_internal.h"
+#include "decode.h"
 #include "get_bits.h"
-#include "huffyuvdsp.h"
-#include "internal.h"
 #include "lossless_videodsp.h"
 #include "thread.h"
 
+#define VLC_BITS 12
+
 typedef struct Slice {
     uint32_t start;
     uint32_t size;
@@ -68,15 +69,20 @@ typedef struct MagicYUVContext {
     Slice            *slices[4];      // slice bitstream positions for each plane
     unsigned int      slices_size[4]; // slice sizes for each plane
     VLC               vlc[4];         // VLC for each plane
+    VLC_MULTI         multi[4];       // Buffer for joint VLC data
     int (*magy_decode_slice)(AVCodecContext *avctx, void *tdata,
                              int j, int threadnr);
     LLVidDSPContext   llviddsp;
+    HuffEntry         he[1 << 14];
+    uint8_t           len[1 << 14];
 } MagicYUVContext;
 
-static int huff_build(const uint8_t len[], uint16_t codes_pos[33],
-                      VLC *vlc, int nb_elems, void *logctx)
+static int huff_build(AVCodecContext *avctx,
+                      const uint8_t len[], uint16_t codes_pos[33],
+                      VLC *vlc, VLC_MULTI *multi, int nb_elems, void *logctx)
 {
-    HuffEntry he[4096];
+    MagicYUVContext *s = avctx->priv_data;
+    HuffEntry *he = s->he;
 
     for (int i = 31; i > 0; i--)
         codes_pos[i] += codes_pos[i + 1];
@@ -84,8 +90,9 @@ static int huff_build(const uint8_t len[], uint16_t codes_pos[33],
     for (unsigned i = nb_elems; i-- > 0;)
         he[--codes_pos[len[i]]] = (HuffEntry){ len[i], i };
 
-    ff_free_vlc(vlc);
-    return ff_init_vlc_from_lengths(vlc, FFMIN(he[0].len, 12), nb_elems,
+    ff_vlc_free(vlc);
+    ff_vlc_free_multi(multi);
+    return ff_vlc_init_multi_from_lengths(vlc, multi, FFMIN(he[0].len, VLC_BITS), nb_elems, nb_elems,
                                     &he[0].len, sizeof(he[0]),
                                     &he[0].sym, sizeof(he[0]), sizeof(he[0].sym),
                                     0, 0, logctx);
@@ -112,10 +119,25 @@ static void magicyuv_median_pred16(uint16_t *dst, const uint16_t *src1,
     *left_top = lt;
 }
 
+#define READ_PLANE(dst, plane, b, c) \
+{ \
+    x = 0; \
+    for (; CACHED_BITSTREAM_READER && x < width-c && get_bits_left(&gb) > 0;) {\
+        ret = get_vlc_multi(&gb, (uint8_t *)dst + x * b, multi, \
+                            vlc, vlc_bits, 3); \
+        if (ret <= 0) \
+            return AVERROR_INVALIDDATA; \
+        x += ret; \
+    } \
+    for (; x < width && get_bits_left(&gb) > 0; x++) \
+        dst[x] = get_vlc2(&gb, vlc, vlc_bits, 3); \
+    dst += stride; \
+}
+
 static int magy_decode_slice10(AVCodecContext *avctx, void *tdata,
                                int j, int threadnr)
 {
-    MagicYUVContext *s = avctx->priv_data;
+    const MagicYUVContext *s = avctx->priv_data;
     int interlaced = s->interlaced;
     const int bps = s->bps;
     const int max = s->max - 1;
@@ -131,6 +153,9 @@ static int magy_decode_slice10(AVCodecContext *avctx, void *tdata,
         int sheight = AV_CEIL_RSHIFT(s->slice_height, s->vshift[i]);
         ptrdiff_t fake_stride = (p->linesize[i] / 2) * (1 + interlaced);
         ptrdiff_t stride = p->linesize[i] / 2;
+        const VLC_MULTI_ELEM *const multi = s->multi[i].table;
+        const VLCElem *const vlc = s->vlc[i].table;
+        const int vlc_bits = s->vlc[i].bits;
         int flags, pred;
         int ret = init_get_bits8(&gb, s->buf + s->slices[i][j].start,
                                  s->slices[i][j].size);
@@ -152,20 +177,8 @@ static int magy_decode_slice10(AVCodecContext *avctx, void *tdata,
                 dst += stride;
             }
         } else {
-            for (k = 0; k < height; k++) {
-                for (x = 0; x < width; x++) {
-                    int pix;
-                    if (get_bits_left(&gb) <= 0)
-                        return AVERROR_INVALIDDATA;
-
-                    pix = get_vlc2(&gb, s->vlc[i].table, s->vlc[i].bits, 3);
-                    if (pix < 0)
-                        return AVERROR_INVALIDDATA;
-
-                    dst[x] = pix;
-                }
-                dst += stride;
-            }
+            for (k = 0; k < height; k++)
+                READ_PLANE(dst, i, 2, 3)
         }
 
         switch (pred) {
@@ -247,7 +260,7 @@ static int magy_decode_slice10(AVCodecContext *avctx, void *tdata,
 static int magy_decode_slice(AVCodecContext *avctx, void *tdata,
                              int j, int threadnr)
 {
-    MagicYUVContext *s = avctx->priv_data;
+    const MagicYUVContext *s = avctx->priv_data;
     int interlaced = s->interlaced;
     AVFrame *p = s->p;
     int i, k, x, min_width;
@@ -262,6 +275,9 @@ static int magy_decode_slice(AVCodecContext *avctx, void *tdata,
         ptrdiff_t fake_stride = p->linesize[i] * (1 + interlaced);
         ptrdiff_t stride = p->linesize[i];
         const uint8_t *slice = s->buf + s->slices[i][j].start;
+        const VLC_MULTI_ELEM *const multi = s->multi[i].table;
+        const VLCElem *const vlc = s->vlc[i].table;
+        const int vlc_bits = s->vlc[i].bits;
         int flags, pred;
 
         flags = bytestream_get_byte(&slice);
@@ -281,20 +297,8 @@ static int magy_decode_slice(AVCodecContext *avctx, void *tdata,
             if (ret < 0)
                 return ret;
 
-            for (k = 0; k < height; k++) {
-                for (x = 0; x < width; x++) {
-                    int pix;
-                    if (get_bits_left(&gb) <= 0)
-                        return AVERROR_INVALIDDATA;
-
-                    pix = get_vlc2(&gb, s->vlc[i].table, s->vlc[i].bits, 3);
-                    if (pix < 0)
-                        return AVERROR_INVALIDDATA;
-
-                    dst[x] = pix;
-                }
-                dst += stride;
-            }
+            for (k = 0; k < height; k++)
+                READ_PLANE(dst, i, 1, 7)
         }
 
         switch (pred) {
@@ -380,7 +384,7 @@ static int build_huffman(AVCodecContext *avctx, const uint8_t *table,
 {
     MagicYUVContext *s = avctx->priv_data;
     GetByteContext gb;
-    uint8_t len[4096];
+    uint8_t *len = s->len;
     uint16_t length_count[33] = { 0 };
     int i = 0, j = 0, k;
 
@@ -408,7 +412,7 @@ static int build_huffman(AVCodecContext *avctx, const uint8_t *table,
 
         if (j == max) {
             j = 0;
-            if (huff_build(len, length_count, &s->vlc[i], max, avctx)) {
+            if (huff_build(avctx, len, length_count, &s->vlc[i], &s->multi[i], max, avctx)) {
                 av_log(avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n");
                 return AVERROR_INVALIDDATA;
             }
@@ -525,6 +529,16 @@ static int magy_decode_frame(AVCodecContext *avctx, AVFrame *p,
         s->decorrelate = 1;
         s->bps = 12;
         break;
+    case 0x71:
+        avctx->pix_fmt = AV_PIX_FMT_GBRP14;
+        s->decorrelate = 1;
+        s->bps = 14;
+        break;
+    case 0x72:
+        avctx->pix_fmt = AV_PIX_FMT_GBRAP14;
+        s->decorrelate = 1;
+        s->bps = 14;
+        break;
     case 0x73:
         avctx->pix_fmt = AV_PIX_FMT_GRAY10;
         s->bps = 10;
@@ -638,7 +652,7 @@ static int magy_decode_frame(AVCodecContext *avctx, AVFrame *p,
         return ret;
 
     p->pict_type = AV_PICTURE_TYPE_I;
-    p->key_frame = 1;
+    p->flags |= AV_FRAME_FLAG_KEY;
 
     if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0)
         return ret;
@@ -652,7 +666,9 @@ static int magy_decode_frame(AVCodecContext *avctx, AVFrame *p,
         avctx->pix_fmt == AV_PIX_FMT_GBRP10 ||
         avctx->pix_fmt == AV_PIX_FMT_GBRAP10||
         avctx->pix_fmt == AV_PIX_FMT_GBRAP12||
-        avctx->pix_fmt == AV_PIX_FMT_GBRP12) {
+        avctx->pix_fmt == AV_PIX_FMT_GBRAP14||
+        avctx->pix_fmt == AV_PIX_FMT_GBRP12||
+        avctx->pix_fmt == AV_PIX_FMT_GBRP14) {
         FFSWAP(uint8_t*, p->data[0], p->data[1]);
         FFSWAP(int, p->linesize[0], p->linesize[1]);
     } else {
@@ -687,7 +703,8 @@ static av_cold int magy_decode_end(AVCodecContext *avctx)
     for (i = 0; i < FF_ARRAY_ELEMS(s->slices); i++) {
         av_freep(&s->slices[i]);
         s->slices_size[i] = 0;
-        ff_free_vlc(&s->vlc[i]);
+        ff_vlc_free(&s->vlc[i]);
+        ff_vlc_free_multi(&s->multi[i]);
     }
 
     return 0;
@@ -695,7 +712,7 @@ static av_cold int magy_decode_end(AVCodecContext *avctx)
 
 const FFCodec ff_magicyuv_decoder = {
     .p.name           = "magicyuv",
-    .p.long_name      = NULL_IF_CONFIG_SMALL("MagicYUV video"),
+    CODEC_LONG_NAME("MagicYUV video"),
     .p.type           = AVMEDIA_TYPE_VIDEO,
     .p.id             = AV_CODEC_ID_MAGICYUV,
     .priv_data_size   = sizeof(MagicYUVContext),
@@ -705,5 +722,4 @@ const FFCodec ff_magicyuv_decoder = {
     .p.capabilities   = AV_CODEC_CAP_DR1 |
                         AV_CODEC_CAP_FRAME_THREADS |
                         AV_CODEC_CAP_SLICE_THREADS,
-    .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE,
 };