* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <inttypes.h>
+
#include "avcodec.h"
+#include "bitstream.h"
#include "bytestream.h"
-#include "dsputil.h"
-#include "internal.h"
-#include "get_bits.h"
#include "golomb.h"
+#include "internal.h"
+#include "idctdsp.h"
+#include "thread.h"
#include "unary.h"
#define AIC_HDR_SIZE 24
177, 184, 176, 169, 162, 161, 168, 160,
};
-static const uint8_t *aic_scan[NUM_BANDS] = {
+static const uint8_t * const aic_scan[NUM_BANDS] = {
aic_y_scan, aic_c_scan, aic_y_ext_scan, aic_c_ext_scan
};
typedef struct AICContext {
AVCodecContext *avctx;
AVFrame *frame;
- DSPContext dsp;
+ IDCTDSPContext idsp;
ScanTable scantable;
int num_x_slices;
width = AV_RB16(src + 6);
height = AV_RB16(src + 8);
if (frame_size > size) {
- av_log(ctx->avctx, AV_LOG_ERROR, "Frame size should be %d got %d\n",
+ av_log(ctx->avctx, AV_LOG_ERROR, "Frame size should be %"PRIu32" got %d\n",
frame_size, size);
return AVERROR_INVALIDDATA;
}
#define GET_CODE(val, type, add_bits) \
do { \
if (type) \
- val = get_ue_golomb(gb); \
+ val = get_ue_golomb(bc); \
else \
- val = get_unary(gb, 1, 31); \
+ val = get_unary(bc, 1, 31); \
if (add_bits) \
- val = (val << add_bits) + get_bits(gb, add_bits); \
+ val = (val << add_bits) + bitstream_read(bc, add_bits); \
} while (0)
-static int aic_decode_coeffs(GetBitContext *gb, int16_t *dst,
+static int aic_decode_coeffs(BitstreamContext *bc, int16_t *dst,
int band, int slice_width, int force_chroma)
{
int has_skips, coeff_type, coeff_bits, skip_type, skip_bits;
const uint8_t *scan = aic_scan[band | force_chroma];
int mb, idx, val;
- has_skips = get_bits1(gb);
- coeff_type = get_bits1(gb);
- coeff_bits = get_bits(gb, 3);
+ has_skips = bitstream_read_bit(bc);
+ coeff_type = bitstream_read_bit(bc);
+ coeff_bits = bitstream_read(bc, 3);
if (has_skips) {
- skip_type = get_bits1(gb);
- skip_bits = get_bits(gb, 3);
+ skip_type = bitstream_read_bit(bc);
+ skip_bits = bitstream_read(bc, 3);
for (mb = 0; mb < slice_width; mb++) {
idx = -1;
do {
GET_CODE(val, skip_type, skip_bits);
+ if (val < 0)
+ return AVERROR_INVALIDDATA;
idx += val + 1;
if (idx >= num_coeffs)
break;
GET_CODE(val, coeff_type, coeff_bits);
val++;
- if (val >= 0x10000)
+ if (val >= 0x10000 || val < 0)
return AVERROR_INVALIDDATA;
dst[scan[idx]] = val;
} while (idx < num_coeffs - 1);
for (mb = 0; mb < slice_width; mb++) {
for (idx = 0; idx < num_coeffs; idx++) {
GET_CODE(val, coeff_type, coeff_bits);
- if (val >= 0x10000)
+ if (val >= 0x10000 || val < 0)
return AVERROR_INVALIDDATA;
dst[scan[idx]] = val;
}
static int aic_decode_slice(AICContext *ctx, int mb_x, int mb_y,
const uint8_t *src, int src_size)
{
- GetBitContext gb;
+ BitstreamContext bc;
int ret, i, mb, blk;
int slice_width = FFMIN(ctx->slice_width, ctx->mb_width - mb_x);
uint8_t *Y, *C[2];
for (i = 0; i < 2; i++)
C[i] = ctx->frame->data[i + 1] + mb_x * 8
+ mb_y * 8 * ctx->frame->linesize[i + 1];
- init_get_bits(&gb, src, src_size * 8);
+ bitstream_init8(&bc, src, src_size);
memset(ctx->slice_data, 0,
sizeof(*ctx->slice_data) * slice_width * AIC_BAND_COEFFS);
for (i = 0; i < NUM_BANDS; i++)
- if ((ret = aic_decode_coeffs(&gb, ctx->data_ptr[i],
+ if ((ret = aic_decode_coeffs(&bc, ctx->data_ptr[i],
i, slice_width,
!ctx->interlaced)) < 0)
return ret;
recombine_block_il(ctx->block, ctx->scantable.permutated,
&base_y, &ext_y, blk);
unquant_block(ctx->block, ctx->quant);
- ctx->dsp.idct(ctx->block);
+ ctx->idsp.idct(ctx->block);
if (!ctx->interlaced) {
dst = Y + (blk >> 1) * 8 * ystride + (blk & 1) * 8;
- ctx->dsp.put_signed_pixels_clamped(ctx->block, dst,
- ystride);
+ ctx->idsp.put_signed_pixels_clamped(ctx->block, dst, ystride);
} else {
dst = Y + (blk & 1) * 8 + (blk >> 1) * ystride;
- ctx->dsp.put_signed_pixels_clamped(ctx->block, dst,
- ystride * 2);
+ ctx->idsp.put_signed_pixels_clamped(ctx->block, dst,
+ ystride * 2);
}
}
Y += 16;
recombine_block(ctx->block, ctx->scantable.permutated,
&base_c, &ext_c);
unquant_block(ctx->block, ctx->quant);
- ctx->dsp.idct(ctx->block);
- ctx->dsp.put_signed_pixels_clamped(ctx->block, C[blk],
- ctx->frame->linesize[blk + 1]);
+ ctx->idsp.idct(ctx->block);
+ ctx->idsp.put_signed_pixels_clamped(ctx->block, C[blk],
+ ctx->frame->linesize[blk + 1]);
C[blk] += 8;
}
}
uint32_t off;
int x, y, ret;
int slice_size;
+ ThreadFrame frame = { .f = data };
ctx->frame = data;
ctx->frame->pict_type = AV_PICTURE_TYPE_I;
return AVERROR_INVALIDDATA;
}
- if ((ret = aic_decode_header(ctx, buf, buf_size)) < 0)
+ ret = aic_decode_header(ctx, buf, buf_size);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Invalid header\n");
return ret;
+ }
- if ((ret = ff_get_buffer(avctx, ctx->frame, 0)) < 0)
+ if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0)
return ret;
bytestream2_init(&gb, buf + AIC_HDR_SIZE,
for (x = 0; x < ctx->mb_width; x += ctx->slice_width) {
slice_size = bytestream2_get_le16(&gb) * 4;
if (slice_size + off > buf_size || !slice_size) {
- av_log(avctx, AV_LOG_ERROR, "Incorrect slice size\n");
+ av_log(avctx, AV_LOG_ERROR,
+ "Incorrect slice size %d at %d.%d\n", slice_size, x, y);
return AVERROR_INVALIDDATA;
}
- if ((ret = aic_decode_slice(ctx, x, y,
- buf + off, slice_size)) < 0)
+ ret = aic_decode_slice(ctx, x, y, buf + off, slice_size);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Error decoding slice at %d.%d\n", x, y);
return ret;
+ }
off += slice_size;
}
avctx->pix_fmt = AV_PIX_FMT_YUV420P;
- ff_dsputil_init(&ctx->dsp, avctx);
+ ff_idctdsp_init(&ctx->idsp, avctx);
for (i = 0; i < 64; i++)
scan[i] = i;
- ff_init_scantable(ctx->dsp.idct_permutation, &ctx->scantable, scan);
+ ff_init_scantable(ctx->idsp.idct_permutation, &ctx->scantable, scan);
ctx->mb_width = FFALIGN(avctx->width, 16) >> 4;
ctx->mb_height = FFALIGN(avctx->height, 16) >> 4;
- ctx->num_x_slices = 16;
- ctx->slice_width = ctx->mb_width / 16;
+ ctx->num_x_slices = (ctx->mb_width + 15) >> 4;
+ ctx->slice_width = 16;
for (i = 1; i < 32; i++) {
- if (!(ctx->mb_width % i) && (ctx->mb_width / i < 32)) {
+ if (!(ctx->mb_width % i) && (ctx->mb_width / i <= 32)) {
ctx->slice_width = ctx->mb_width / i;
ctx->num_x_slices = i;
break;
AVCodec ff_aic_decoder = {
.name = "aic",
+ .long_name = NULL_IF_CONFIG_SMALL("Apple Intermediate Codec"),
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_AIC,
.priv_data_size = sizeof(AICContext),
.init = aic_decode_init,
.close = aic_decode_close,
.decode = aic_decode_frame,
- .capabilities = CODEC_CAP_DR1,
- .long_name = NULL_IF_CONFIG_SMALL("Apple Intermediate Codec")
+ .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
+ .init_thread_copy = ONLY_IF_THREADS_ENABLED(aic_decode_init),
+ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
};