mirror of
https://github.com/xenia-project/FFmpeg.git
synced 2024-11-24 12:09:55 +00:00
avcodec/magicyuv: add 12 bit formats
Signed-off-by: Paul B Mahol <onemda@gmail.com>
This commit is contained in:
parent
fa3fd7f5a0
commit
0281d5ece6
@ -53,6 +53,7 @@ typedef struct HuffEntry {
|
|||||||
typedef struct MagicYUVContext {
|
typedef struct MagicYUVContext {
|
||||||
AVFrame *p;
|
AVFrame *p;
|
||||||
int max;
|
int max;
|
||||||
|
int bps;
|
||||||
int slice_height;
|
int slice_height;
|
||||||
int nb_slices;
|
int nb_slices;
|
||||||
int planes; // number of encoded planes in bitstream
|
int planes; // number of encoded planes in bitstream
|
||||||
@ -65,7 +66,7 @@ typedef struct MagicYUVContext {
|
|||||||
int vshift[4];
|
int vshift[4];
|
||||||
Slice *slices[4]; // slice bitstream positions for each plane
|
Slice *slices[4]; // slice bitstream positions for each plane
|
||||||
unsigned int slices_size[4]; // slice sizes for each plane
|
unsigned int slices_size[4]; // slice sizes for each plane
|
||||||
uint8_t len[4][1024]; // table of code lengths for each plane
|
uint8_t len[4][4096]; // table of code lengths for each plane
|
||||||
VLC vlc[4]; // VLC for each plane
|
VLC vlc[4]; // VLC for each plane
|
||||||
int (*huff_build)(VLC *vlc, uint8_t *len);
|
int (*huff_build)(VLC *vlc, uint8_t *len);
|
||||||
int (*magy_decode_slice)(AVCodecContext *avctx, void *tdata,
|
int (*magy_decode_slice)(AVCodecContext *avctx, void *tdata,
|
||||||
@ -85,6 +86,12 @@ static int huff_cmp_len10(const void *a, const void *b)
|
|||||||
return (aa->len - bb->len) * 1024 + aa->sym - bb->sym;
|
return (aa->len - bb->len) * 1024 + aa->sym - bb->sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int huff_cmp_len12(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
const HuffEntry *aa = a, *bb = b;
|
||||||
|
return (aa->len - bb->len) * 4096 + aa->sym - bb->sym;
|
||||||
|
}
|
||||||
|
|
||||||
static int huff_build10(VLC *vlc, uint8_t *len)
|
static int huff_build10(VLC *vlc, uint8_t *len)
|
||||||
{
|
{
|
||||||
HuffEntry he[1024];
|
HuffEntry he[1024];
|
||||||
@ -117,6 +124,38 @@ static int huff_build10(VLC *vlc, uint8_t *len)
|
|||||||
syms, sizeof(*syms), sizeof(*syms), 0);
|
syms, sizeof(*syms), sizeof(*syms), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int huff_build12(VLC *vlc, uint8_t *len)
|
||||||
|
{
|
||||||
|
HuffEntry he[4096];
|
||||||
|
uint32_t codes[4096];
|
||||||
|
uint8_t bits[4096];
|
||||||
|
uint16_t syms[4096];
|
||||||
|
uint32_t code;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 4096; i++) {
|
||||||
|
he[i].sym = 4095 - i;
|
||||||
|
he[i].len = len[i];
|
||||||
|
if (len[i] == 0)
|
||||||
|
return AVERROR_INVALIDDATA;
|
||||||
|
}
|
||||||
|
AV_QSORT(he, 4096, HuffEntry, huff_cmp_len12);
|
||||||
|
|
||||||
|
code = 1;
|
||||||
|
for (i = 4095; 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[4095].len, 14), 4096,
|
||||||
|
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)
|
static int huff_build(VLC *vlc, uint8_t *len)
|
||||||
{
|
{
|
||||||
HuffEntry he[256];
|
HuffEntry he[256];
|
||||||
@ -149,9 +188,9 @@ static int huff_build(VLC *vlc, uint8_t *len)
|
|||||||
syms, sizeof(*syms), sizeof(*syms), 0);
|
syms, sizeof(*syms), sizeof(*syms), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void magicyuv_median_pred10(uint16_t *dst, const uint16_t *src1,
|
static void magicyuv_median_pred16(uint16_t *dst, const uint16_t *src1,
|
||||||
const uint16_t *diff, intptr_t w,
|
const uint16_t *diff, intptr_t w,
|
||||||
int *left, int *left_top)
|
int *left, int *left_top, int max)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
uint16_t l, lt;
|
uint16_t l, lt;
|
||||||
@ -161,7 +200,7 @@ static void magicyuv_median_pred10(uint16_t *dst, const uint16_t *src1,
|
|||||||
|
|
||||||
for (i = 0; i < w; i++) {
|
for (i = 0; i < w; i++) {
|
||||||
l = mid_pred(l, src1[i], (l + src1[i] - lt)) + diff[i];
|
l = mid_pred(l, src1[i], (l + src1[i] - lt)) + diff[i];
|
||||||
l &= 0x3FF;
|
l &= max;
|
||||||
lt = src1[i];
|
lt = src1[i];
|
||||||
dst[i] = l;
|
dst[i] = l;
|
||||||
}
|
}
|
||||||
@ -175,6 +214,8 @@ static int magy_decode_slice10(AVCodecContext *avctx, void *tdata,
|
|||||||
{
|
{
|
||||||
MagicYUVContext *s = avctx->priv_data;
|
MagicYUVContext *s = avctx->priv_data;
|
||||||
int interlaced = s->interlaced;
|
int interlaced = s->interlaced;
|
||||||
|
const int bps = s->bps;
|
||||||
|
const int max = s->max - 1;
|
||||||
AVFrame *p = s->p;
|
AVFrame *p = s->p;
|
||||||
int i, k, x;
|
int i, k, x;
|
||||||
GetBitContext gb;
|
GetBitContext gb;
|
||||||
@ -201,7 +242,7 @@ static int magy_decode_slice10(AVCodecContext *avctx, void *tdata,
|
|||||||
if (flags & 1) {
|
if (flags & 1) {
|
||||||
for (k = 0; k < height; k++) {
|
for (k = 0; k < height; k++) {
|
||||||
for (x = 0; x < width; x++)
|
for (x = 0; x < width; x++)
|
||||||
dst[x] = get_bits(&gb, 10);
|
dst[x] = get_bits(&gb, bps);
|
||||||
|
|
||||||
dst += stride;
|
dst += stride;
|
||||||
}
|
}
|
||||||
@ -216,7 +257,7 @@ static int magy_decode_slice10(AVCodecContext *avctx, void *tdata,
|
|||||||
if (pix < 0)
|
if (pix < 0)
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
|
|
||||||
dst[x] = 1023 - pix;
|
dst[x] = max - pix;
|
||||||
}
|
}
|
||||||
dst += stride;
|
dst += stride;
|
||||||
}
|
}
|
||||||
@ -225,36 +266,36 @@ static int magy_decode_slice10(AVCodecContext *avctx, void *tdata,
|
|||||||
switch (pred) {
|
switch (pred) {
|
||||||
case LEFT:
|
case LEFT:
|
||||||
dst = (uint16_t *)p->data[i] + j * sheight * stride;
|
dst = (uint16_t *)p->data[i] + j * sheight * stride;
|
||||||
s->llviddsp.add_left_pred_int16(dst, dst, 1023, width, 0);
|
s->llviddsp.add_left_pred_int16(dst, dst, max, width, 0);
|
||||||
dst += stride;
|
dst += stride;
|
||||||
if (interlaced) {
|
if (interlaced) {
|
||||||
s->llviddsp.add_left_pred_int16(dst, dst, 1023, width, 0);
|
s->llviddsp.add_left_pred_int16(dst, dst, max, width, 0);
|
||||||
dst += stride;
|
dst += stride;
|
||||||
}
|
}
|
||||||
for (k = 1 + interlaced; k < height; k++) {
|
for (k = 1 + interlaced; k < height; k++) {
|
||||||
s->llviddsp.add_left_pred_int16(dst, dst, 1023, width, dst[-fake_stride]);
|
s->llviddsp.add_left_pred_int16(dst, dst, max, width, dst[-fake_stride]);
|
||||||
dst += stride;
|
dst += stride;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GRADIENT:
|
case GRADIENT:
|
||||||
dst = (uint16_t *)p->data[i] + j * sheight * stride;
|
dst = (uint16_t *)p->data[i] + j * sheight * stride;
|
||||||
s->llviddsp.add_left_pred_int16(dst, dst, 1023, width, 0);
|
s->llviddsp.add_left_pred_int16(dst, dst, max, width, 0);
|
||||||
left = lefttop = 0;
|
left = lefttop = 0;
|
||||||
dst += stride;
|
dst += stride;
|
||||||
if (interlaced) {
|
if (interlaced) {
|
||||||
s->llviddsp.add_left_pred_int16(dst, dst, 1023, width, 0);
|
s->llviddsp.add_left_pred_int16(dst, dst, max, width, 0);
|
||||||
left = lefttop = 0;
|
left = lefttop = 0;
|
||||||
dst += stride;
|
dst += stride;
|
||||||
}
|
}
|
||||||
for (k = 1 + interlaced; k < height; k++) {
|
for (k = 1 + interlaced; k < height; k++) {
|
||||||
top = dst[-fake_stride];
|
top = dst[-fake_stride];
|
||||||
left = top + dst[0];
|
left = top + dst[0];
|
||||||
dst[0] = left & 0x3FF;
|
dst[0] = left & max;
|
||||||
for (x = 1; x < width; x++) {
|
for (x = 1; x < width; x++) {
|
||||||
top = dst[x - fake_stride];
|
top = dst[x - fake_stride];
|
||||||
lefttop = dst[x - (fake_stride + 1)];
|
lefttop = dst[x - (fake_stride + 1)];
|
||||||
left += top - lefttop + dst[x];
|
left += top - lefttop + dst[x];
|
||||||
dst[x] = left & 0x3FF;
|
dst[x] = left & max;
|
||||||
}
|
}
|
||||||
dst += stride;
|
dst += stride;
|
||||||
}
|
}
|
||||||
@ -262,15 +303,15 @@ static int magy_decode_slice10(AVCodecContext *avctx, void *tdata,
|
|||||||
case MEDIAN:
|
case MEDIAN:
|
||||||
dst = (uint16_t *)p->data[i] + j * sheight * stride;
|
dst = (uint16_t *)p->data[i] + j * sheight * stride;
|
||||||
lefttop = left = dst[0];
|
lefttop = left = dst[0];
|
||||||
s->llviddsp.add_left_pred_int16(dst, dst, 1023, width, 0);
|
s->llviddsp.add_left_pred_int16(dst, dst, max, width, 0);
|
||||||
dst += stride;
|
dst += stride;
|
||||||
if (interlaced) {
|
if (interlaced) {
|
||||||
lefttop = left = dst[0];
|
lefttop = left = dst[0];
|
||||||
s->llviddsp.add_left_pred_int16(dst, dst, 1023, width, 0);
|
s->llviddsp.add_left_pred_int16(dst, dst, max, width, 0);
|
||||||
dst += stride;
|
dst += stride;
|
||||||
}
|
}
|
||||||
for (k = 1 + interlaced; k < height; k++) {
|
for (k = 1 + interlaced; k < height; k++) {
|
||||||
magicyuv_median_pred10(dst, dst - fake_stride, dst, width, &left, &lefttop);
|
magicyuv_median_pred16(dst, dst - fake_stride, dst, width, &left, &lefttop, max);
|
||||||
lefttop = left = dst[0];
|
lefttop = left = dst[0];
|
||||||
dst += stride;
|
dst += stride;
|
||||||
}
|
}
|
||||||
@ -289,8 +330,8 @@ static int magy_decode_slice10(AVCodecContext *avctx, void *tdata,
|
|||||||
|
|
||||||
for (i = 0; i < height; i++) {
|
for (i = 0; i < height; i++) {
|
||||||
for (k = 0; k < width; k++) {
|
for (k = 0; k < width; k++) {
|
||||||
b[k] = (b[k] + g[k]) & 0x3FF;
|
b[k] = (b[k] + g[k]) & max;
|
||||||
r[k] = (r[k] + g[k]) & 0x3FF;
|
r[k] = (r[k] + g[k]) & max;
|
||||||
}
|
}
|
||||||
b += p->linesize[0] / 2;
|
b += p->linesize[0] / 2;
|
||||||
g += p->linesize[1] / 2;
|
g += p->linesize[1] / 2;
|
||||||
@ -458,6 +499,7 @@ static int build_huffman(AVCodecContext *avctx, GetBitContext *gbit, int max)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (j > max) {
|
} else if (j > max) {
|
||||||
|
av_log(avctx, AV_LOG_ERROR, "Invalid Huffman codes\n");
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -505,6 +547,7 @@ static int magy_decode_frame(AVCodecContext *avctx, void *data,
|
|||||||
s->vshift[2] = 0;
|
s->vshift[2] = 0;
|
||||||
s->decorrelate = 0;
|
s->decorrelate = 0;
|
||||||
s->max = 256;
|
s->max = 256;
|
||||||
|
s->bps = 8;
|
||||||
s->huff_build = huff_build;
|
s->huff_build = huff_build;
|
||||||
s->magy_decode_slice = magy_decode_slice;
|
s->magy_decode_slice = magy_decode_slice;
|
||||||
|
|
||||||
@ -546,6 +589,7 @@ static int magy_decode_frame(AVCodecContext *avctx, void *data,
|
|||||||
s->max = 1024;
|
s->max = 1024;
|
||||||
s->huff_build = huff_build10;
|
s->huff_build = huff_build10;
|
||||||
s->magy_decode_slice = magy_decode_slice10;
|
s->magy_decode_slice = magy_decode_slice10;
|
||||||
|
s->bps = 10;
|
||||||
break;
|
break;
|
||||||
case 0x6d:
|
case 0x6d:
|
||||||
avctx->pix_fmt = AV_PIX_FMT_GBRP10;
|
avctx->pix_fmt = AV_PIX_FMT_GBRP10;
|
||||||
@ -553,6 +597,7 @@ static int magy_decode_frame(AVCodecContext *avctx, void *data,
|
|||||||
s->max = 1024;
|
s->max = 1024;
|
||||||
s->huff_build = huff_build10;
|
s->huff_build = huff_build10;
|
||||||
s->magy_decode_slice = magy_decode_slice10;
|
s->magy_decode_slice = magy_decode_slice10;
|
||||||
|
s->bps = 10;
|
||||||
break;
|
break;
|
||||||
case 0x6e:
|
case 0x6e:
|
||||||
avctx->pix_fmt = AV_PIX_FMT_GBRAP10;
|
avctx->pix_fmt = AV_PIX_FMT_GBRAP10;
|
||||||
@ -560,12 +605,30 @@ static int magy_decode_frame(AVCodecContext *avctx, void *data,
|
|||||||
s->max = 1024;
|
s->max = 1024;
|
||||||
s->huff_build = huff_build10;
|
s->huff_build = huff_build10;
|
||||||
s->magy_decode_slice = magy_decode_slice10;
|
s->magy_decode_slice = magy_decode_slice10;
|
||||||
|
s->bps = 10;
|
||||||
|
break;
|
||||||
|
case 0x6f:
|
||||||
|
avctx->pix_fmt = AV_PIX_FMT_GBRP12;
|
||||||
|
s->decorrelate = 1;
|
||||||
|
s->max = 4096;
|
||||||
|
s->huff_build = huff_build12;
|
||||||
|
s->magy_decode_slice = magy_decode_slice10;
|
||||||
|
s->bps = 12;
|
||||||
|
break;
|
||||||
|
case 0x70:
|
||||||
|
avctx->pix_fmt = AV_PIX_FMT_GBRAP12;
|
||||||
|
s->decorrelate = 1;
|
||||||
|
s->max = 4096;
|
||||||
|
s->huff_build = huff_build12;
|
||||||
|
s->magy_decode_slice = magy_decode_slice10;
|
||||||
|
s->bps = 12;
|
||||||
break;
|
break;
|
||||||
case 0x73:
|
case 0x73:
|
||||||
avctx->pix_fmt = AV_PIX_FMT_GRAY10;
|
avctx->pix_fmt = AV_PIX_FMT_GRAY10;
|
||||||
s->max = 1024;
|
s->max = 1024;
|
||||||
s->huff_build = huff_build10;
|
s->huff_build = huff_build10;
|
||||||
s->magy_decode_slice = magy_decode_slice10;
|
s->magy_decode_slice = magy_decode_slice10;
|
||||||
|
s->bps = 10;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
avpriv_request_sample(avctx, "Format 0x%X", format);
|
avpriv_request_sample(avctx, "Format 0x%X", format);
|
||||||
@ -663,7 +726,9 @@ static int magy_decode_frame(AVCodecContext *avctx, void *data,
|
|||||||
if (avctx->pix_fmt == AV_PIX_FMT_GBRP ||
|
if (avctx->pix_fmt == AV_PIX_FMT_GBRP ||
|
||||||
avctx->pix_fmt == AV_PIX_FMT_GBRAP ||
|
avctx->pix_fmt == AV_PIX_FMT_GBRAP ||
|
||||||
avctx->pix_fmt == AV_PIX_FMT_GBRP10 ||
|
avctx->pix_fmt == AV_PIX_FMT_GBRP10 ||
|
||||||
avctx->pix_fmt == AV_PIX_FMT_GBRAP10) {
|
avctx->pix_fmt == AV_PIX_FMT_GBRAP10||
|
||||||
|
avctx->pix_fmt == AV_PIX_FMT_GBRAP12||
|
||||||
|
avctx->pix_fmt == AV_PIX_FMT_GBRP12) {
|
||||||
FFSWAP(uint8_t*, p->data[0], p->data[1]);
|
FFSWAP(uint8_t*, p->data[0], p->data[1]);
|
||||||
FFSWAP(int, p->linesize[0], p->linesize[1]);
|
FFSWAP(int, p->linesize[0], p->linesize[1]);
|
||||||
} else {
|
} else {
|
||||||
|
@ -289,6 +289,8 @@ const AVCodecTag ff_codec_movvideo_tags[] = {
|
|||||||
{ AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'Y', '2') },
|
{ AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'Y', '2') },
|
||||||
{ AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'Y', '4') },
|
{ AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'Y', '4') },
|
||||||
{ AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'Y', 'A') },
|
{ AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'Y', 'A') },
|
||||||
|
{ AV_CODEC_ID_MAGICYUV, MKTAG('M', '2', 'R', 'A') },
|
||||||
|
{ AV_CODEC_ID_MAGICYUV, MKTAG('M', '2', 'R', 'G') },
|
||||||
|
|
||||||
{ AV_CODEC_ID_SHEERVIDEO, MKTAG('S', 'h', 'r', '0') },
|
{ AV_CODEC_ID_SHEERVIDEO, MKTAG('S', 'h', 'r', '0') },
|
||||||
{ AV_CODEC_ID_SHEERVIDEO, MKTAG('S', 'h', 'r', '1') },
|
{ AV_CODEC_ID_SHEERVIDEO, MKTAG('S', 'h', 'r', '1') },
|
||||||
|
@ -447,6 +447,8 @@ const AVCodecTag ff_codec_bmp_tags[] = {
|
|||||||
{ AV_CODEC_ID_MAGICYUV, MKTAG('M', '0', 'R', 'G') },
|
{ AV_CODEC_ID_MAGICYUV, MKTAG('M', '0', 'R', 'G') },
|
||||||
{ AV_CODEC_ID_MAGICYUV, MKTAG('M', '0', 'G', '0') },
|
{ AV_CODEC_ID_MAGICYUV, MKTAG('M', '0', 'G', '0') },
|
||||||
{ AV_CODEC_ID_MAGICYUV, MKTAG('M', '0', 'Y', '2') },
|
{ AV_CODEC_ID_MAGICYUV, MKTAG('M', '0', 'Y', '2') },
|
||||||
|
{ AV_CODEC_ID_MAGICYUV, MKTAG('M', '2', 'R', 'A') },
|
||||||
|
{ AV_CODEC_ID_MAGICYUV, MKTAG('M', '2', 'R', 'G') },
|
||||||
{ AV_CODEC_ID_YLC, MKTAG('Y', 'L', 'C', '0') },
|
{ AV_CODEC_ID_YLC, MKTAG('Y', 'L', 'C', '0') },
|
||||||
{ AV_CODEC_ID_SPEEDHQ, MKTAG('S', 'H', 'Q', '0') },
|
{ AV_CODEC_ID_SPEEDHQ, MKTAG('S', 'H', 'Q', '0') },
|
||||||
{ AV_CODEC_ID_SPEEDHQ, MKTAG('S', 'H', 'Q', '1') },
|
{ AV_CODEC_ID_SPEEDHQ, MKTAG('S', 'H', 'Q', '1') },
|
||||||
|
Loading…
Reference in New Issue
Block a user