Commit 235d6932 authored by Kostya Shishkov's avatar Kostya Shishkov

prores: handle 444 chroma in right order

ProRes codes chroma blocks in 444 mode in different order than luma blocks,
so make both decoder and encoder read/write chroma blocks in right order.

Reported by Phil Barrett
parent 23bfcc06
...@@ -411,7 +411,7 @@ static void decode_slice_plane(ProresContext *ctx, ProresThreadData *td, ...@@ -411,7 +411,7 @@ static void decode_slice_plane(ProresContext *ctx, ProresThreadData *td,
int data_size, uint16_t *out_ptr, int data_size, uint16_t *out_ptr,
int linesize, int mbs_per_slice, int linesize, int mbs_per_slice,
int blocks_per_mb, int plane_size_factor, int blocks_per_mb, int plane_size_factor,
const int16_t *qmat) const int16_t *qmat, int is_chroma)
{ {
GetBitContext gb; GetBitContext gb;
DCTELEM *block_ptr; DCTELEM *block_ptr;
...@@ -431,18 +431,33 @@ static void decode_slice_plane(ProresContext *ctx, ProresThreadData *td, ...@@ -431,18 +431,33 @@ static void decode_slice_plane(ProresContext *ctx, ProresThreadData *td,
/* inverse quantization, inverse transform and output */ /* inverse quantization, inverse transform and output */
block_ptr = td->blocks; block_ptr = td->blocks;
for (mb_num = 0; mb_num < mbs_per_slice; mb_num++, out_ptr += blocks_per_mb * 4) { if (!is_chroma) {
ctx->dsp.idct_put(out_ptr, linesize, block_ptr, qmat); for (mb_num = 0; mb_num < mbs_per_slice; mb_num++, out_ptr += blocks_per_mb * 4) {
block_ptr += 64; ctx->dsp.idct_put(out_ptr, linesize, block_ptr, qmat);
if (blocks_per_mb > 2) {
ctx->dsp.idct_put(out_ptr + 8, linesize, block_ptr, qmat);
block_ptr += 64; block_ptr += 64;
if (blocks_per_mb > 2) {
ctx->dsp.idct_put(out_ptr + 8, linesize, block_ptr, qmat);
block_ptr += 64;
}
ctx->dsp.idct_put(out_ptr + linesize * 4, linesize, block_ptr, qmat);
block_ptr += 64;
if (blocks_per_mb > 2) {
ctx->dsp.idct_put(out_ptr + linesize * 4 + 8, linesize, block_ptr, qmat);
block_ptr += 64;
}
} }
ctx->dsp.idct_put(out_ptr + linesize * 4, linesize, block_ptr, qmat); } else {
block_ptr += 64; for (mb_num = 0; mb_num < mbs_per_slice; mb_num++, out_ptr += blocks_per_mb * 4) {
if (blocks_per_mb > 2) { ctx->dsp.idct_put(out_ptr, linesize, block_ptr, qmat);
ctx->dsp.idct_put(out_ptr + linesize * 4 + 8, linesize, block_ptr, qmat); block_ptr += 64;
ctx->dsp.idct_put(out_ptr + linesize * 4, linesize, block_ptr, qmat);
block_ptr += 64; block_ptr += 64;
if (blocks_per_mb > 2) {
ctx->dsp.idct_put(out_ptr + 8, linesize, block_ptr, qmat);
block_ptr += 64;
ctx->dsp.idct_put(out_ptr + linesize * 4 + 8, linesize, block_ptr, qmat);
block_ptr += 64;
}
} }
} }
} }
...@@ -523,7 +538,7 @@ static int decode_slice(AVCodecContext *avctx, void *tdata) ...@@ -523,7 +538,7 @@ static int decode_slice(AVCodecContext *avctx, void *tdata)
(uint16_t*) (y_data + (mb_y_pos << 4) * y_linesize + (uint16_t*) (y_data + (mb_y_pos << 4) * y_linesize +
(mb_x_pos << 5)), y_linesize, (mb_x_pos << 5)), y_linesize,
mbs_per_slice, 4, slice_width_factor + 2, mbs_per_slice, 4, slice_width_factor + 2,
td->qmat_luma_scaled); td->qmat_luma_scaled, 0);
/* decode U chroma plane */ /* decode U chroma plane */
decode_slice_plane(ctx, td, buf + hdr_size + y_data_size, u_data_size, decode_slice_plane(ctx, td, buf + hdr_size + y_data_size, u_data_size,
...@@ -531,7 +546,7 @@ static int decode_slice(AVCodecContext *avctx, void *tdata) ...@@ -531,7 +546,7 @@ static int decode_slice(AVCodecContext *avctx, void *tdata)
(mb_x_pos << ctx->mb_chroma_factor)), (mb_x_pos << ctx->mb_chroma_factor)),
u_linesize, mbs_per_slice, ctx->num_chroma_blocks, u_linesize, mbs_per_slice, ctx->num_chroma_blocks,
slice_width_factor + ctx->chroma_factor - 1, slice_width_factor + ctx->chroma_factor - 1,
td->qmat_chroma_scaled); td->qmat_chroma_scaled, 1);
/* decode V chroma plane */ /* decode V chroma plane */
decode_slice_plane(ctx, td, buf + hdr_size + y_data_size + u_data_size, decode_slice_plane(ctx, td, buf + hdr_size + y_data_size + u_data_size,
...@@ -540,7 +555,7 @@ static int decode_slice(AVCodecContext *avctx, void *tdata) ...@@ -540,7 +555,7 @@ static int decode_slice(AVCodecContext *avctx, void *tdata)
(mb_x_pos << ctx->mb_chroma_factor)), (mb_x_pos << ctx->mb_chroma_factor)),
v_linesize, mbs_per_slice, ctx->num_chroma_blocks, v_linesize, mbs_per_slice, ctx->num_chroma_blocks,
slice_width_factor + ctx->chroma_factor - 1, slice_width_factor + ctx->chroma_factor - 1,
td->qmat_chroma_scaled); td->qmat_chroma_scaled, 1);
return 0; return 0;
} }
......
...@@ -171,7 +171,7 @@ typedef struct ProresContext { ...@@ -171,7 +171,7 @@ typedef struct ProresContext {
static void get_slice_data(ProresContext *ctx, const uint16_t *src, static void get_slice_data(ProresContext *ctx, const uint16_t *src,
int linesize, int x, int y, int w, int h, int linesize, int x, int y, int w, int h,
DCTELEM *blocks, DCTELEM *blocks,
int mbs_per_slice, int blocks_per_mb) int mbs_per_slice, int blocks_per_mb, int is_chroma)
{ {
const uint16_t *esrc; const uint16_t *esrc;
const int mb_width = 4 * blocks_per_mb; const int mb_width = 4 * blocks_per_mb;
...@@ -209,17 +209,30 @@ static void get_slice_data(ProresContext *ctx, const uint16_t *src, ...@@ -209,17 +209,30 @@ static void get_slice_data(ProresContext *ctx, const uint16_t *src,
ctx->emu_buf + (bh - 1) * estride, ctx->emu_buf + (bh - 1) * estride,
mb_width * sizeof(*ctx->emu_buf)); mb_width * sizeof(*ctx->emu_buf));
} }
ctx->dsp.fdct(esrc, elinesize, blocks); if (!is_chroma) {
blocks += 64; ctx->dsp.fdct(esrc, elinesize, blocks);
if (blocks_per_mb > 2) {
ctx->dsp.fdct(src + 8, linesize, blocks);
blocks += 64; blocks += 64;
} if (blocks_per_mb > 2) {
ctx->dsp.fdct(src + linesize * 4, linesize, blocks); ctx->dsp.fdct(src + 8, linesize, blocks);
blocks += 64; blocks += 64;
if (blocks_per_mb > 2) { }
ctx->dsp.fdct(src + linesize * 4 + 8, linesize, blocks); ctx->dsp.fdct(src + linesize * 4, linesize, blocks);
blocks += 64; blocks += 64;
if (blocks_per_mb > 2) {
ctx->dsp.fdct(src + linesize * 4 + 8, linesize, blocks);
blocks += 64;
}
} else {
ctx->dsp.fdct(esrc, elinesize, blocks);
blocks += 64;
ctx->dsp.fdct(src + linesize * 4, linesize, blocks);
blocks += 64;
if (blocks_per_mb > 2) {
ctx->dsp.fdct(src + 8, linesize, blocks);
blocks += 64;
ctx->dsp.fdct(src + linesize * 4 + 8, linesize, blocks);
blocks += 64;
}
} }
x += mb_width; x += mb_width;
...@@ -383,7 +396,7 @@ static int encode_slice(AVCodecContext *avctx, const AVFrame *pic, ...@@ -383,7 +396,7 @@ static int encode_slice(AVCodecContext *avctx, const AVFrame *pic,
get_slice_data(ctx, src, pic->linesize[i], xp, yp, get_slice_data(ctx, src, pic->linesize[i], xp, yp,
pwidth, avctx->height, ctx->blocks[0], pwidth, avctx->height, ctx->blocks[0],
mbs_per_slice, num_cblocks); mbs_per_slice, num_cblocks, is_chroma);
sizes[i] = encode_slice_plane(ctx, pb, src, pic->linesize[i], sizes[i] = encode_slice_plane(ctx, pb, src, pic->linesize[i],
mbs_per_slice, ctx->blocks[0], mbs_per_slice, ctx->blocks[0],
num_cblocks, plane_factor, num_cblocks, plane_factor,
...@@ -539,7 +552,7 @@ static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic, ...@@ -539,7 +552,7 @@ static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic,
get_slice_data(ctx, src, pic->linesize[i], xp, yp, get_slice_data(ctx, src, pic->linesize[i], xp, yp,
pwidth, avctx->height, ctx->blocks[i], pwidth, avctx->height, ctx->blocks[i],
mbs_per_slice, num_cblocks[i]); mbs_per_slice, num_cblocks[i], is_chroma[i]);
} }
for (q = min_quant; q < max_quant + 2; q++) { for (q = min_quant; q < max_quant + 2; q++) {
......
#tb 0: 1/2997 #tb 0: 1/2997
0, 0, 0, 0, 12441600, 0x9d3dc525 0, 0, 0, 0, 12441600, 0x254d8f95
0, 100, 100, 0, 12441600, 0x9d3dc525 0, 100, 100, 0, 12441600, 0x254d8f95
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment