|
|
|
@ -151,9 +151,10 @@ static int decode_block(GetBitContext *gb, VLC *vlc, |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int hqx_decode_422(HQXContext *ctx, HQXSliceData * slice_data, |
|
|
|
|
GetBitContext *gb, int x, int y) |
|
|
|
|
static int hqx_decode_422(HQXContext *ctx, int slice_no, int x, int y) |
|
|
|
|
{ |
|
|
|
|
HQXSlice *slice = &ctx->slice[slice_no]; |
|
|
|
|
GetBitContext *gb = &slice->gb; |
|
|
|
|
const int *quants; |
|
|
|
|
int flag; |
|
|
|
|
int last_dc; |
|
|
|
@ -171,22 +172,23 @@ static int hqx_decode_422(HQXContext *ctx, HQXSliceData * slice_data, |
|
|
|
|
if (i == 0 || i == 4 || i == 6) |
|
|
|
|
last_dc = 0; |
|
|
|
|
ret = decode_block(gb, &ctx->dc_vlc[vlc_index], quants, |
|
|
|
|
ctx->dcb, slice_data->block[i], &last_dc); |
|
|
|
|
ctx->dcb, slice->block[i], &last_dc); |
|
|
|
|
if (ret < 0) |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
put_blocks(ctx, 0, x , y, flag, slice_data->block[0], slice_data->block[2], hqx_quant_luma); |
|
|
|
|
put_blocks(ctx, 0, x + 8 , y, flag, slice_data->block[1], slice_data->block[3], hqx_quant_luma); |
|
|
|
|
put_blocks(ctx, 2, x >> 1, y, flag, slice_data->block[4], slice_data->block[5], hqx_quant_chroma); |
|
|
|
|
put_blocks(ctx, 1, x >> 1, y, flag, slice_data->block[6], slice_data->block[7], hqx_quant_chroma); |
|
|
|
|
put_blocks(ctx, 0, x, y, flag, slice->block[0], slice->block[2], hqx_quant_luma); |
|
|
|
|
put_blocks(ctx, 0, x + 8, y, flag, slice->block[1], slice->block[3], hqx_quant_luma); |
|
|
|
|
put_blocks(ctx, 2, x >> 1, y, flag, slice->block[4], slice->block[5], hqx_quant_chroma); |
|
|
|
|
put_blocks(ctx, 1, x >> 1, y, flag, slice->block[6], slice->block[7], hqx_quant_chroma); |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int hqx_decode_422a(HQXContext *ctx, HQXSliceData * slice_data, |
|
|
|
|
GetBitContext *gb, int x, int y) |
|
|
|
|
static int hqx_decode_422a(HQXContext *ctx, int slice_no, int x, int y) |
|
|
|
|
{ |
|
|
|
|
HQXSlice *slice = &ctx->slice[slice_no]; |
|
|
|
|
GetBitContext *gb = &slice->gb; |
|
|
|
|
const int *quants; |
|
|
|
|
int flag = 0; |
|
|
|
|
int last_dc; |
|
|
|
@ -196,9 +198,9 @@ static int hqx_decode_422a(HQXContext *ctx, HQXSliceData * slice_data, |
|
|
|
|
cbp = get_vlc2(gb, ctx->cbp_vlc.table, ctx->cbp_vlc.bits, 1); |
|
|
|
|
|
|
|
|
|
for (i = 0; i < 12; i++) |
|
|
|
|
memset(slice_data->block[i], 0, sizeof(**slice_data->block) * 64); |
|
|
|
|
memset(slice->block[i], 0, sizeof(**slice->block) * 64); |
|
|
|
|
for (i = 0; i < 12; i++) |
|
|
|
|
slice_data->block[i][0] = -0x800; |
|
|
|
|
slice->block[i][0] = -0x800; |
|
|
|
|
if (cbp) { |
|
|
|
|
if (ctx->interlaced) |
|
|
|
|
flag = get_bits1(gb); |
|
|
|
@ -216,26 +218,27 @@ static int hqx_decode_422a(HQXContext *ctx, HQXSliceData * slice_data, |
|
|
|
|
if (cbp & (1 << i)) { |
|
|
|
|
int vlc_index = ctx->dcb - 9; |
|
|
|
|
ret = decode_block(gb, &ctx->dc_vlc[vlc_index], quants, |
|
|
|
|
ctx->dcb, slice_data->block[i], &last_dc); |
|
|
|
|
ctx->dcb, slice->block[i], &last_dc); |
|
|
|
|
if (ret < 0) |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
put_blocks(ctx, 3, x, y, flag, slice_data->block[ 0], slice_data->block[ 2], hqx_quant_luma); |
|
|
|
|
put_blocks(ctx, 3, x + 8, y, flag, slice_data->block[ 1], slice_data->block[ 3], hqx_quant_luma); |
|
|
|
|
put_blocks(ctx, 0, x, y, flag, slice_data->block[ 4], slice_data->block[ 6], hqx_quant_luma); |
|
|
|
|
put_blocks(ctx, 0, x + 8, y, flag, slice_data->block[ 5], slice_data->block[ 7], hqx_quant_luma); |
|
|
|
|
put_blocks(ctx, 2, x >> 1, y, flag, slice_data->block[ 8], slice_data->block[ 9], hqx_quant_chroma); |
|
|
|
|
put_blocks(ctx, 1, x >> 1, y, flag, slice_data->block[10], slice_data->block[11], hqx_quant_chroma); |
|
|
|
|
put_blocks(ctx, 3, x, y, flag, slice->block[ 0], slice->block[ 2], hqx_quant_luma); |
|
|
|
|
put_blocks(ctx, 3, x + 8, y, flag, slice->block[ 1], slice->block[ 3], hqx_quant_luma); |
|
|
|
|
put_blocks(ctx, 0, x, y, flag, slice->block[ 4], slice->block[ 6], hqx_quant_luma); |
|
|
|
|
put_blocks(ctx, 0, x + 8, y, flag, slice->block[ 5], slice->block[ 7], hqx_quant_luma); |
|
|
|
|
put_blocks(ctx, 2, x >> 1, y, flag, slice->block[ 8], slice->block[ 9], hqx_quant_chroma); |
|
|
|
|
put_blocks(ctx, 1, x >> 1, y, flag, slice->block[10], slice->block[11], hqx_quant_chroma); |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int hqx_decode_444(HQXContext *ctx, HQXSliceData * slice_data, |
|
|
|
|
GetBitContext *gb, int x, int y) |
|
|
|
|
static int hqx_decode_444(HQXContext *ctx, int slice_no, int x, int y) |
|
|
|
|
{ |
|
|
|
|
HQXSlice *slice = &ctx->slice[slice_no]; |
|
|
|
|
GetBitContext *gb = &slice->gb; |
|
|
|
|
const int *quants; |
|
|
|
|
int flag; |
|
|
|
|
int last_dc; |
|
|
|
@ -253,25 +256,25 @@ static int hqx_decode_444(HQXContext *ctx, HQXSliceData * slice_data, |
|
|
|
|
if (i == 0 || i == 4 || i == 8) |
|
|
|
|
last_dc = 0; |
|
|
|
|
ret = decode_block(gb, &ctx->dc_vlc[vlc_index], quants, |
|
|
|
|
ctx->dcb, slice_data->block[i], &last_dc); |
|
|
|
|
ctx->dcb, slice->block[i], &last_dc); |
|
|
|
|
if (ret < 0) |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
put_blocks(ctx, 0, x, y, flag, slice_data->block[0], slice_data->block[ 2], hqx_quant_luma); |
|
|
|
|
put_blocks(ctx, 0, x + 8, y, flag, slice_data->block[1], slice_data->block[ 3], hqx_quant_luma); |
|
|
|
|
put_blocks(ctx, 2, x, y, flag, slice_data->block[4], slice_data->block[ 6], hqx_quant_chroma); |
|
|
|
|
put_blocks(ctx, 2, x + 8, y, flag, slice_data->block[5], slice_data->block[ 7], hqx_quant_chroma); |
|
|
|
|
put_blocks(ctx, 1, x, y, flag, slice_data->block[8], slice_data->block[10], hqx_quant_chroma); |
|
|
|
|
put_blocks(ctx, 1, x + 8, y, flag, slice_data->block[9], slice_data->block[11], hqx_quant_chroma); |
|
|
|
|
put_blocks(ctx, 0, x, y, flag, slice->block[0], slice->block[ 2], hqx_quant_luma); |
|
|
|
|
put_blocks(ctx, 0, x + 8, y, flag, slice->block[1], slice->block[ 3], hqx_quant_luma); |
|
|
|
|
put_blocks(ctx, 2, x, y, flag, slice->block[4], slice->block[ 6], hqx_quant_chroma); |
|
|
|
|
put_blocks(ctx, 2, x + 8, y, flag, slice->block[5], slice->block[ 7], hqx_quant_chroma); |
|
|
|
|
put_blocks(ctx, 1, x, y, flag, slice->block[8], slice->block[10], hqx_quant_chroma); |
|
|
|
|
put_blocks(ctx, 1, x + 8, y, flag, slice->block[9], slice->block[11], hqx_quant_chroma); |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int hqx_decode_444a(HQXContext *ctx, HQXSliceData * slice_data, |
|
|
|
|
GetBitContext *gb, int x, int y) |
|
|
|
|
static int hqx_decode_444a(HQXContext *ctx, int slice_no, int x, int y) |
|
|
|
|
{ |
|
|
|
|
HQXSlice *slice = &ctx->slice[slice_no]; |
|
|
|
|
GetBitContext *gb = &slice->gb; |
|
|
|
|
const int *quants; |
|
|
|
|
int flag = 0; |
|
|
|
|
int last_dc; |
|
|
|
@ -281,9 +284,9 @@ static int hqx_decode_444a(HQXContext *ctx, HQXSliceData * slice_data, |
|
|
|
|
cbp = get_vlc2(gb, ctx->cbp_vlc.table, ctx->cbp_vlc.bits, 1); |
|
|
|
|
|
|
|
|
|
for (i = 0; i < 16; i++) |
|
|
|
|
memset(slice_data->block[i], 0, sizeof(**slice_data->block) * 64); |
|
|
|
|
memset(slice->block[i], 0, sizeof(**slice->block) * 64); |
|
|
|
|
for (i = 0; i < 16; i++) |
|
|
|
|
slice_data->block[i][0] = -0x800; |
|
|
|
|
slice->block[i][0] = -0x800; |
|
|
|
|
if (cbp) { |
|
|
|
|
if (ctx->interlaced) |
|
|
|
|
flag = get_bits1(gb); |
|
|
|
@ -298,21 +301,21 @@ static int hqx_decode_444a(HQXContext *ctx, HQXSliceData * slice_data, |
|
|
|
|
if (cbp & (1 << i)) { |
|
|
|
|
int vlc_index = ctx->dcb - 9; |
|
|
|
|
ret = decode_block(gb, &ctx->dc_vlc[vlc_index], quants, |
|
|
|
|
ctx->dcb, slice_data->block[i], &last_dc); |
|
|
|
|
ctx->dcb, slice->block[i], &last_dc); |
|
|
|
|
if (ret < 0) |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
put_blocks(ctx, 3, x, y, flag, slice_data->block[ 0], slice_data->block[ 2], hqx_quant_luma); |
|
|
|
|
put_blocks(ctx, 3, x + 8, y, flag, slice_data->block[ 1], slice_data->block[ 3], hqx_quant_luma); |
|
|
|
|
put_blocks(ctx, 0, x, y, flag, slice_data->block[ 4], slice_data->block[ 6], hqx_quant_luma); |
|
|
|
|
put_blocks(ctx, 0, x + 8, y, flag, slice_data->block[ 5], slice_data->block[ 7], hqx_quant_luma); |
|
|
|
|
put_blocks(ctx, 2, x, y, flag, slice_data->block[ 8], slice_data->block[10], hqx_quant_chroma); |
|
|
|
|
put_blocks(ctx, 2, x + 8, y, flag, slice_data->block[ 9], slice_data->block[11], hqx_quant_chroma); |
|
|
|
|
put_blocks(ctx, 1, x, y, flag, slice_data->block[12], slice_data->block[14], hqx_quant_chroma); |
|
|
|
|
put_blocks(ctx, 1, x + 8, y, flag, slice_data->block[13], slice_data->block[15], hqx_quant_chroma); |
|
|
|
|
put_blocks(ctx, 3, x, y, flag, slice->block[ 0], slice->block[ 2], hqx_quant_luma); |
|
|
|
|
put_blocks(ctx, 3, x + 8, y, flag, slice->block[ 1], slice->block[ 3], hqx_quant_luma); |
|
|
|
|
put_blocks(ctx, 0, x, y, flag, slice->block[ 4], slice->block[ 6], hqx_quant_luma); |
|
|
|
|
put_blocks(ctx, 0, x + 8, y, flag, slice->block[ 5], slice->block[ 7], hqx_quant_luma); |
|
|
|
|
put_blocks(ctx, 2, x, y, flag, slice->block[ 8], slice->block[10], hqx_quant_chroma); |
|
|
|
|
put_blocks(ctx, 2, x + 8, y, flag, slice->block[ 9], slice->block[11], hqx_quant_chroma); |
|
|
|
|
put_blocks(ctx, 1, x, y, flag, slice->block[12], slice->block[14], hqx_quant_chroma); |
|
|
|
|
put_blocks(ctx, 1, x + 8, y, flag, slice->block[13], slice->block[15], hqx_quant_chroma); |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
@ -321,7 +324,7 @@ static const int shuffle_16[16] = { |
|
|
|
|
0, 5, 11, 14, 2, 7, 9, 13, 1, 4, 10, 15, 3, 6, 8, 12 |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static int decode_slice(HQXContext *ctx, GetBitContext *gb, int slice_no) |
|
|
|
|
static int decode_slice(HQXContext *ctx, int slice_no) |
|
|
|
|
{ |
|
|
|
|
int mb_w = (ctx->width + 15) >> 4; |
|
|
|
|
int mb_h = (ctx->height + 15) >> 4; |
|
|
|
@ -367,36 +370,34 @@ static int decode_slice(HQXContext *ctx, GetBitContext *gb, int slice_no) |
|
|
|
|
mb_x += pos % grp_w; |
|
|
|
|
mb_y = loc_row + (pos / grp_w); |
|
|
|
|
} |
|
|
|
|
ctx->decode_func(ctx, &ctx->slice[slice_no], gb, mb_x * 16, mb_y * 16); |
|
|
|
|
ctx->decode_func(ctx, slice_no, mb_x * 16, mb_y * 16); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int decode_slice_thread(AVCodecContext *avctx, void *arg, int slice, int threadnr) |
|
|
|
|
static int decode_slice_thread(AVCodecContext *avctx, void *arg, |
|
|
|
|
int slice_no, int threadnr) |
|
|
|
|
{ |
|
|
|
|
HQXContext *ctx = avctx->priv_data; |
|
|
|
|
uint32_t * slice_off = ctx->slice_off; |
|
|
|
|
unsigned data_size = ctx->data_size; |
|
|
|
|
uint32_t *slice_off = ctx->slice_off; |
|
|
|
|
int ret; |
|
|
|
|
|
|
|
|
|
if (slice_off[slice] < HQX_HEADER_SIZE || |
|
|
|
|
slice_off[slice] >= slice_off[slice + 1] || |
|
|
|
|
slice_off[slice + 1] > data_size) { |
|
|
|
|
av_log(avctx, AV_LOG_ERROR, "Invalid slice size.\n"); |
|
|
|
|
if (slice_off[slice_no] < HQX_HEADER_SIZE || |
|
|
|
|
slice_off[slice_no] >= slice_off[slice_no + 1] || |
|
|
|
|
slice_off[slice_no + 1] > ctx->data_size) { |
|
|
|
|
av_log(avctx, AV_LOG_ERROR, "Invalid slice size %d.\n", ctx->data_size); |
|
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ret = init_get_bits8(&ctx->slice[slice].gb, ctx->src + slice_off[slice], slice_off[slice + 1] - slice_off[slice]); |
|
|
|
|
ret = init_get_bits8(&ctx->slice[slice_no].gb, |
|
|
|
|
ctx->src + slice_off[slice_no], |
|
|
|
|
slice_off[slice_no + 1] - slice_off[slice_no]); |
|
|
|
|
if (ret < 0) |
|
|
|
|
return ret; |
|
|
|
|
|
|
|
|
|
ret = decode_slice(ctx, &ctx->slice[slice].gb, slice); |
|
|
|
|
if (ret < 0) { |
|
|
|
|
av_log(avctx, AV_LOG_ERROR, "Error decoding slice %d.\n", slice); |
|
|
|
|
} |
|
|
|
|
return ret; |
|
|
|
|
return decode_slice(ctx, slice_no); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int hqx_decode_frame(AVCodecContext *avctx, void *data, |
|
|
|
@ -538,5 +539,5 @@ AVCodec ff_hqx_decoder = { |
|
|
|
|
.init = hqx_decode_init, |
|
|
|
|
.decode = hqx_decode_frame, |
|
|
|
|
.close = hqx_decode_close, |
|
|
|
|
.capabilities = CODEC_CAP_DR1 | CODEC_CAP_SLICE_THREADS, |
|
|
|
|
.capabilities = CODEC_CAP_DR1 | CODEC_CAP_SLICE_THREADS, |
|
|
|
|
}; |
|
|
|
|