#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;
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];
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);
*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;
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);
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) {
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;
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);
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) {
{
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;
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;
}
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;
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;
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 {
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;
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),
.p.capabilities = AV_CODEC_CAP_DR1 |
AV_CODEC_CAP_FRAME_THREADS |
AV_CODEC_CAP_SLICE_THREADS,
- .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
};