|
|
@@ -30,6 +30,7 @@ |
|
|
|
#include "get_bits.h" |
|
|
|
#include "huffyuvdsp.h" |
|
|
|
#include "internal.h" |
|
|
|
#include "lossless_videodsp.h" |
|
|
|
#include "thread.h" |
|
|
|
|
|
|
|
typedef struct Slice { |
|
|
@@ -44,13 +45,14 @@ typedef enum Prediction { |
|
|
|
} Prediction; |
|
|
|
|
|
|
|
typedef struct HuffEntry { |
|
|
|
uint8_t sym; |
|
|
|
uint16_t sym; |
|
|
|
uint8_t len; |
|
|
|
uint32_t code; |
|
|
|
} HuffEntry; |
|
|
|
|
|
|
|
typedef struct MagicYUVContext { |
|
|
|
AVFrame *p; |
|
|
|
int max; |
|
|
|
int slice_height; |
|
|
|
int nb_slices; |
|
|
|
int planes; // number of encoded planes in bitstream |
|
|
@@ -61,9 +63,13 @@ typedef struct MagicYUVContext { |
|
|
|
int vshift[4]; |
|
|
|
Slice *slices[4]; // slice bitstream positions for each plane |
|
|
|
unsigned int slices_size[4]; // slice sizes for each plane |
|
|
|
uint8_t len[4][256]; // table of code lengths for each plane |
|
|
|
uint8_t len[4][1024]; // table of code lengths for each plane |
|
|
|
VLC vlc[4]; // VLC for each plane |
|
|
|
int (*huff_build)(VLC *vlc, uint8_t *len); |
|
|
|
int (*magy_decode_slice)(AVCodecContext *avctx, void *tdata, |
|
|
|
int j, int threadnr); |
|
|
|
HuffYUVDSPContext hdsp; |
|
|
|
LLVidDSPContext llviddsp; |
|
|
|
} MagicYUVContext; |
|
|
|
|
|
|
|
static int huff_cmp_len(const void *a, const void *b) |
|
|
@@ -72,6 +78,42 @@ static int huff_cmp_len(const void *a, const void *b) |
|
|
|
return (aa->len - bb->len) * 256 + aa->sym - bb->sym; |
|
|
|
} |
|
|
|
|
|
|
|
static int huff_cmp_len10(const void *a, const void *b) |
|
|
|
{ |
|
|
|
const HuffEntry *aa = a, *bb = b; |
|
|
|
return (aa->len - bb->len) * 1024 + aa->sym - bb->sym; |
|
|
|
} |
|
|
|
|
|
|
|
static int huff_build10(VLC *vlc, uint8_t *len) |
|
|
|
{ |
|
|
|
HuffEntry he[1024]; |
|
|
|
uint32_t codes[1024]; |
|
|
|
uint8_t bits[1024]; |
|
|
|
uint16_t syms[1024]; |
|
|
|
uint32_t code; |
|
|
|
int i; |
|
|
|
|
|
|
|
for (i = 0; i < 1024; i++) { |
|
|
|
he[i].sym = 1023 - i; |
|
|
|
he[i].len = len[i]; |
|
|
|
} |
|
|
|
AV_QSORT(he, 1024, HuffEntry, huff_cmp_len10); |
|
|
|
|
|
|
|
code = 1; |
|
|
|
for (i = 1023; i >= 0; i--) { |
|
|
|
codes[i] = code >> (32 - he[i].len); |
|
|
|
bits[i] = he[i].len; |
|
|
|
syms[i] = he[i].sym; |
|
|
|
code += 0x80000000u >> (he[i].len - 1); |
|
|
|
} |
|
|
|
|
|
|
|
ff_free_vlc(vlc); |
|
|
|
return ff_init_vlc_sparse(vlc, FFMIN(he[1023].len, 12), 1024, |
|
|
|
bits, sizeof(*bits), sizeof(*bits), |
|
|
|
codes, sizeof(*codes), sizeof(*codes), |
|
|
|
syms, sizeof(*syms), sizeof(*syms), 0); |
|
|
|
} |
|
|
|
|
|
|
|
static int huff_build(VLC *vlc, uint8_t *len) |
|
|
|
{ |
|
|
|
HuffEntry he[256]; |
|
|
@@ -102,6 +144,158 @@ static int huff_build(VLC *vlc, uint8_t *len) |
|
|
|
syms, sizeof(*syms), sizeof(*syms), 0); |
|
|
|
} |
|
|
|
|
|
|
|
static void magicyuv_median_pred10(uint16_t *dst, const uint16_t *src1, |
|
|
|
const uint16_t *diff, intptr_t w, |
|
|
|
int *left, int *left_top) |
|
|
|
{ |
|
|
|
int i; |
|
|
|
uint16_t l, lt; |
|
|
|
|
|
|
|
l = *left; |
|
|
|
lt = *left_top; |
|
|
|
|
|
|
|
for (i = 0; i < w; i++) { |
|
|
|
l = mid_pred(l, src1[i], (l + src1[i] - lt)) + diff[i]; |
|
|
|
l &= 0x3FF; |
|
|
|
lt = src1[i]; |
|
|
|
dst[i] = l; |
|
|
|
} |
|
|
|
|
|
|
|
*left = l; |
|
|
|
*left_top = lt; |
|
|
|
} |
|
|
|
|
|
|
|
static int magy_decode_slice10(AVCodecContext *avctx, void *tdata, |
|
|
|
int j, int threadnr) |
|
|
|
{ |
|
|
|
MagicYUVContext *s = avctx->priv_data; |
|
|
|
int interlaced = s->interlaced; |
|
|
|
AVFrame *p = s->p; |
|
|
|
int i, k, x; |
|
|
|
GetBitContext gb; |
|
|
|
uint16_t *dst; |
|
|
|
|
|
|
|
for (i = 0; i < s->planes; i++) { |
|
|
|
int left, lefttop, top; |
|
|
|
int height = AV_CEIL_RSHIFT(FFMIN(s->slice_height, avctx->coded_height - j * s->slice_height), s->vshift[i]); |
|
|
|
int width = AV_CEIL_RSHIFT(avctx->coded_width, s->hshift[i]); |
|
|
|
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; |
|
|
|
int flags, pred; |
|
|
|
int ret = init_get_bits8(&gb, s->buf + s->slices[i][j].start, |
|
|
|
s->slices[i][j].size); |
|
|
|
|
|
|
|
if (ret < 0) |
|
|
|
return ret; |
|
|
|
|
|
|
|
flags = get_bits(&gb, 8); |
|
|
|
pred = get_bits(&gb, 8); |
|
|
|
|
|
|
|
dst = (uint16_t *)p->data[i] + j * sheight * stride; |
|
|
|
if (flags & 1) { |
|
|
|
for (k = 0; k < height; k++) { |
|
|
|
for (x = 0; x < width; x++) |
|
|
|
dst[x] = get_bits(&gb, 10); |
|
|
|
|
|
|
|
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] = 1023 - pix; |
|
|
|
} |
|
|
|
dst += stride; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
switch (pred) { |
|
|
|
case LEFT: |
|
|
|
dst = (uint16_t *)p->data[i] + j * sheight * stride; |
|
|
|
s->llviddsp.add_hfyu_left_pred_int16(dst, dst, 1023, width, 0); |
|
|
|
dst += stride; |
|
|
|
if (interlaced) { |
|
|
|
s->llviddsp.add_hfyu_left_pred_int16(dst, dst, 1023, width, 0); |
|
|
|
dst += stride; |
|
|
|
} |
|
|
|
for (k = 1 + interlaced; k < height; k++) { |
|
|
|
s->llviddsp.add_hfyu_left_pred_int16(dst, dst, 1023, width, dst[-fake_stride]); |
|
|
|
dst += stride; |
|
|
|
} |
|
|
|
break; |
|
|
|
case GRADIENT: |
|
|
|
dst = (uint16_t *)p->data[i] + j * sheight * stride; |
|
|
|
s->llviddsp.add_hfyu_left_pred_int16(dst, dst, 1023, width, 0); |
|
|
|
left = lefttop = 0; |
|
|
|
dst += stride; |
|
|
|
if (interlaced) { |
|
|
|
s->llviddsp.add_hfyu_left_pred_int16(dst, dst, 1023, width, 0); |
|
|
|
left = lefttop = 0; |
|
|
|
dst += stride; |
|
|
|
} |
|
|
|
for (k = 1 + interlaced; k < height; k++) { |
|
|
|
top = dst[-fake_stride]; |
|
|
|
left = top + dst[0]; |
|
|
|
dst[0] = left & 0x3FF; |
|
|
|
for (x = 1; x < width; x++) { |
|
|
|
top = dst[x - fake_stride]; |
|
|
|
lefttop = dst[x - (fake_stride + 1)]; |
|
|
|
left += top - lefttop + dst[x]; |
|
|
|
dst[x] = left & 0x3FF; |
|
|
|
} |
|
|
|
dst += stride; |
|
|
|
} |
|
|
|
break; |
|
|
|
case MEDIAN: |
|
|
|
dst = (uint16_t *)p->data[i] + j * sheight * stride; |
|
|
|
lefttop = left = dst[0]; |
|
|
|
s->llviddsp.add_hfyu_left_pred_int16(dst, dst, 1023, width, 0); |
|
|
|
dst += stride; |
|
|
|
if (interlaced) { |
|
|
|
lefttop = left = dst[0]; |
|
|
|
s->llviddsp.add_hfyu_left_pred_int16(dst, dst, 1023, width, 0); |
|
|
|
dst += stride; |
|
|
|
} |
|
|
|
for (k = 1 + interlaced; k < height; k++) { |
|
|
|
magicyuv_median_pred10(dst, dst - fake_stride, dst, width, &left, &lefttop); |
|
|
|
lefttop = left = dst[0]; |
|
|
|
dst += stride; |
|
|
|
} |
|
|
|
break; |
|
|
|
default: |
|
|
|
avpriv_request_sample(avctx, "Unknown prediction: %d", pred); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (s->decorrelate) { |
|
|
|
int height = FFMIN(s->slice_height, avctx->coded_height - j * s->slice_height); |
|
|
|
int width = avctx->coded_width; |
|
|
|
uint16_t *r = (uint16_t *)p->data[0] + j * s->slice_height * p->linesize[0] / 2; |
|
|
|
uint16_t *g = (uint16_t *)p->data[1] + j * s->slice_height * p->linesize[1] / 2; |
|
|
|
uint16_t *b = (uint16_t *)p->data[2] + j * s->slice_height * p->linesize[2] / 2; |
|
|
|
|
|
|
|
for (i = 0; i < height; i++) { |
|
|
|
for (k = 0; k < width; k++) { |
|
|
|
b[k] = (b[k] + g[k]) & 0x3FF; |
|
|
|
r[k] = (r[k] + g[k]) & 0x3FF; |
|
|
|
} |
|
|
|
b += p->linesize[0] / 2; |
|
|
|
g += p->linesize[1] / 2; |
|
|
|
r += p->linesize[2] / 2; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int magy_decode_slice(AVCodecContext *avctx, void *tdata, |
|
|
|
int j, int threadnr) |
|
|
|
{ |
|
|
@@ -232,6 +426,45 @@ static int magy_decode_slice(AVCodecContext *avctx, void *tdata, |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int build_huffman(AVCodecContext *avctx, GetBitContext *gbit, int max) |
|
|
|
{ |
|
|
|
MagicYUVContext *s = avctx->priv_data; |
|
|
|
int i = 0, j = 0, k; |
|
|
|
|
|
|
|
memset(s->len, 0, sizeof(s->len)); |
|
|
|
while (get_bits_left(gbit) >= 8) { |
|
|
|
int b = get_bits(gbit, 4); |
|
|
|
int x = get_bits(gbit, 4); |
|
|
|
int l = get_bitsz(gbit, b) + 1; |
|
|
|
|
|
|
|
for (k = 0; k < l; k++) |
|
|
|
if (j + k < max) |
|
|
|
s->len[i][j + k] = x; |
|
|
|
|
|
|
|
j += l; |
|
|
|
if (j == max) { |
|
|
|
j = 0; |
|
|
|
if (s->huff_build(&s->vlc[i], s->len[i])) { |
|
|
|
av_log(avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n"); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
i++; |
|
|
|
if (i == s->planes) { |
|
|
|
break; |
|
|
|
} |
|
|
|
} else if (j > max) { |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (i != s->planes) { |
|
|
|
av_log(avctx, AV_LOG_ERROR, "Huffman tables too short\n"); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int magy_decode_frame(AVCodecContext *avctx, void *data, |
|
|
|
int *got_frame, AVPacket *avpkt) |
|
|
|
{ |
|
|
@@ -242,7 +475,7 @@ static int magy_decode_frame(AVCodecContext *avctx, void *data, |
|
|
|
GetBitContext gbit; |
|
|
|
uint32_t first_offset, offset, next_offset, header_size, slice_width; |
|
|
|
int width, height, format, version, table_size; |
|
|
|
int ret, i, j, k; |
|
|
|
int ret, i, j; |
|
|
|
|
|
|
|
bytestream2_init(&gbyte, avpkt->data, avpkt->size); |
|
|
|
if (bytestream2_get_le32(&gbyte) != MKTAG('M', 'A', 'G', 'Y')) |
|
|
@@ -266,6 +499,9 @@ static int magy_decode_frame(AVCodecContext *avctx, void *data, |
|
|
|
s->hshift[2] = |
|
|
|
s->vshift[2] = 0; |
|
|
|
s->decorrelate = 0; |
|
|
|
s->max = 256; |
|
|
|
s->huff_build = huff_build; |
|
|
|
s->magy_decode_slice = magy_decode_slice; |
|
|
|
|
|
|
|
format = bytestream2_get_byte(&gbyte); |
|
|
|
switch (format) { |
|
|
@@ -298,6 +534,34 @@ static int magy_decode_frame(AVCodecContext *avctx, void *data, |
|
|
|
case 0x6b: |
|
|
|
avctx->pix_fmt = AV_PIX_FMT_GRAY8; |
|
|
|
break; |
|
|
|
case 0x6c: |
|
|
|
avctx->pix_fmt = AV_PIX_FMT_YUV422P10; |
|
|
|
s->hshift[1] = |
|
|
|
s->hshift[2] = 1; |
|
|
|
s->max = 1024; |
|
|
|
s->huff_build = huff_build10; |
|
|
|
s->magy_decode_slice = magy_decode_slice10; |
|
|
|
break; |
|
|
|
case 0x6d: |
|
|
|
avctx->pix_fmt = AV_PIX_FMT_GBRP10; |
|
|
|
s->decorrelate = 1; |
|
|
|
s->max = 1024; |
|
|
|
s->huff_build = huff_build10; |
|
|
|
s->magy_decode_slice = magy_decode_slice10; |
|
|
|
break; |
|
|
|
case 0x6e: |
|
|
|
avctx->pix_fmt = AV_PIX_FMT_GBRAP10; |
|
|
|
s->decorrelate = 1; |
|
|
|
s->max = 1024; |
|
|
|
s->huff_build = huff_build10; |
|
|
|
s->magy_decode_slice = magy_decode_slice10; |
|
|
|
break; |
|
|
|
case 0x73: |
|
|
|
avctx->pix_fmt = AV_PIX_FMT_GRAY10; |
|
|
|
s->max = 1024; |
|
|
|
s->huff_build = huff_build10; |
|
|
|
s->magy_decode_slice = magy_decode_slice10; |
|
|
|
break; |
|
|
|
default: |
|
|
|
avpriv_request_sample(avctx, "Format 0x%X", format); |
|
|
|
return AVERROR_PATCHWELCOME; |
|
|
@@ -375,37 +639,9 @@ static int magy_decode_frame(AVCodecContext *avctx, void *data, |
|
|
|
if (ret < 0) |
|
|
|
return ret; |
|
|
|
|
|
|
|
memset(s->len, 0, sizeof(s->len)); |
|
|
|
j = i = 0; |
|
|
|
while (get_bits_left(&gbit) >= 8) { |
|
|
|
int b = get_bits(&gbit, 4); |
|
|
|
int x = get_bits(&gbit, 4); |
|
|
|
int l = get_bitsz(&gbit, b) + 1; |
|
|
|
|
|
|
|
for (k = 0; k < l; k++) |
|
|
|
if (j + k < 256) |
|
|
|
s->len[i][j + k] = x; |
|
|
|
|
|
|
|
j += l; |
|
|
|
if (j == 256) { |
|
|
|
j = 0; |
|
|
|
if (huff_build(&s->vlc[i], s->len[i])) { |
|
|
|
av_log(avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n"); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
i++; |
|
|
|
if (i == s->planes) { |
|
|
|
break; |
|
|
|
} |
|
|
|
} else if (j > 256) { |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (i != s->planes) { |
|
|
|
av_log(avctx, AV_LOG_ERROR, "Huffman tables too short\n"); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
ret = build_huffman(avctx, &gbit, s->max); |
|
|
|
if (ret < 0) |
|
|
|
return ret; |
|
|
|
|
|
|
|
p->pict_type = AV_PICTURE_TYPE_I; |
|
|
|
p->key_frame = 1; |
|
|
@@ -415,10 +651,12 @@ static int magy_decode_frame(AVCodecContext *avctx, void *data, |
|
|
|
|
|
|
|
s->buf = avpkt->data; |
|
|
|
s->p = p; |
|
|
|
avctx->execute2(avctx, magy_decode_slice, NULL, NULL, s->nb_slices); |
|
|
|
avctx->execute2(avctx, s->magy_decode_slice, NULL, NULL, s->nb_slices); |
|
|
|
|
|
|
|
if (avctx->pix_fmt == AV_PIX_FMT_GBRP || |
|
|
|
avctx->pix_fmt == AV_PIX_FMT_GBRAP) { |
|
|
|
if (avctx->pix_fmt == AV_PIX_FMT_GBRP || |
|
|
|
avctx->pix_fmt == AV_PIX_FMT_GBRAP || |
|
|
|
avctx->pix_fmt == AV_PIX_FMT_GBRP10 || |
|
|
|
avctx->pix_fmt == AV_PIX_FMT_GBRAP10) { |
|
|
|
FFSWAP(uint8_t*, p->data[0], p->data[1]); |
|
|
|
FFSWAP(int, p->linesize[0], p->linesize[1]); |
|
|
|
} |
|
|
@@ -447,6 +685,7 @@ static av_cold int magy_decode_init(AVCodecContext *avctx) |
|
|
|
{ |
|
|
|
MagicYUVContext *s = avctx->priv_data; |
|
|
|
ff_huffyuvdsp_init(&s->hdsp); |
|
|
|
ff_llviddsp_init(&s->llviddsp, avctx); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|