diff options
| author | Tim Redfern <tim@eclectronics.org> | 2013-12-29 12:19:38 +0000 |
|---|---|---|
| committer | Tim Redfern <tim@eclectronics.org> | 2013-12-29 12:19:38 +0000 |
| commit | f7813a5324be39d13ab536c245d15dfc602a7849 (patch) | |
| tree | fad99148b88823d34a5df2f0a25881a002eb291b /ffmpeg/libavcodec/proresdec2.c | |
| parent | b7a5a477b8ff4d4e3028b9dfb9a9df0a41463f92 (diff) | |
basic type mechanism working
Diffstat (limited to 'ffmpeg/libavcodec/proresdec2.c')
| -rw-r--r-- | ffmpeg/libavcodec/proresdec2.c | 235 |
1 files changed, 164 insertions, 71 deletions
diff --git a/ffmpeg/libavcodec/proresdec2.c b/ffmpeg/libavcodec/proresdec2.c index b7aef36..b1affad 100644 --- a/ffmpeg/libavcodec/proresdec2.c +++ b/ffmpeg/libavcodec/proresdec2.c @@ -33,6 +33,7 @@ #include "internal.h" #include "simple_idct.h" #include "proresdec.h" +#include "proresdata.h" static void permute(uint8_t *dst, const uint8_t *src, const uint8_t permutation[64]) { @@ -41,28 +42,6 @@ static void permute(uint8_t *dst, const uint8_t *src, const uint8_t permutation[ dst[i] = permutation[src[i]]; } -static const uint8_t progressive_scan[64] = { - 0, 1, 8, 9, 2, 3, 10, 11, - 16, 17, 24, 25, 18, 19, 26, 27, - 4, 5, 12, 20, 13, 6, 7, 14, - 21, 28, 29, 22, 15, 23, 30, 31, - 32, 33, 40, 48, 41, 34, 35, 42, - 49, 56, 57, 50, 43, 36, 37, 44, - 51, 58, 59, 52, 45, 38, 39, 46, - 53, 60, 61, 54, 47, 55, 62, 63 -}; - -static const uint8_t interlaced_scan[64] = { - 0, 8, 1, 9, 16, 24, 17, 25, - 2, 10, 3, 11, 18, 26, 19, 27, - 32, 40, 33, 34, 41, 48, 56, 49, - 42, 35, 43, 50, 57, 58, 51, 59, - 4, 12, 5, 6, 13, 20, 28, 21, - 14, 7, 15, 22, 29, 36, 44, 37, - 30, 23, 31, 38, 45, 52, 60, 53, - 46, 39, 47, 54, 61, 62, 55, 63, -}; - static av_cold int decode_init(AVCodecContext *avctx) { ProresContext *ctx = avctx->priv_data; @@ -76,8 +55,8 @@ static av_cold int decode_init(AVCodecContext *avctx) ff_init_scantable_permutation(idct_permutation, ctx->prodsp.idct_permutation_type); - permute(ctx->progressive_scan, progressive_scan, idct_permutation); - permute(ctx->interlaced_scan, interlaced_scan, idct_permutation); + permute(ctx->progressive_scan, ff_prores_progressive_scan, idct_permutation); + permute(ctx->interlaced_scan, ff_prores_interlaced_scan, idct_permutation); return 0; } @@ -93,14 +72,14 @@ static int decode_frame_header(ProresContext *ctx, const uint8_t *buf, av_dlog(avctx, "header size %d\n", hdr_size); if (hdr_size > data_size) { av_log(avctx, AV_LOG_ERROR, "error, wrong header size\n"); - return -1; + return AVERROR_INVALIDDATA; } version = AV_RB16(buf + 2); av_dlog(avctx, "%.4s version %d\n", buf+4, version); if (version > 1) { av_log(avctx, AV_LOG_ERROR, "unsupported version: %d\n", version); - return -1; + return AVERROR_PATCHWELCOME; } width = AV_RB16(buf + 8); @@ -108,10 +87,17 @@ static int decode_frame_header(ProresContext *ctx, const uint8_t *buf, if (width != avctx->width || height != avctx->height) { av_log(avctx, AV_LOG_ERROR, "picture resolution change: %dx%d -> %dx%d\n", avctx->width, avctx->height, width, height); - return -1; + return AVERROR_PATCHWELCOME; } ctx->frame_type = (buf[12] >> 2) & 3; + ctx->alpha_info = buf[17] & 0xf; + + if (ctx->alpha_info > 2) { + av_log(avctx, AV_LOG_ERROR, "Invalid alpha mode %d\n", ctx->alpha_info); + return AVERROR_INVALIDDATA; + } + if (avctx->skip_alpha) ctx->alpha_info = 0; av_dlog(avctx, "frame type %d\n", ctx->frame_type); @@ -123,7 +109,11 @@ static int decode_frame_header(ProresContext *ctx, const uint8_t *buf, ctx->frame->top_field_first = ctx->frame_type == 1; } - avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUV444P10 : AV_PIX_FMT_YUV422P10; + if (ctx->alpha_info) { + avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUVA444P10 : AV_PIX_FMT_YUVA422P10; + } else { + avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUV444P10 : AV_PIX_FMT_YUV422P10; + } ptr = buf + 20; flags = buf[19]; @@ -132,7 +122,7 @@ static int decode_frame_header(ProresContext *ctx, const uint8_t *buf, if (flags & 2) { if(buf + data_size - ptr < 64) { av_log(avctx, AV_LOG_ERROR, "Header truncated\n"); - return -1; + return AVERROR_INVALIDDATA; } permute(ctx->qmat_luma, ctx->prodsp.idct_permutation, ptr); ptr += 64; @@ -143,7 +133,7 @@ static int decode_frame_header(ProresContext *ctx, const uint8_t *buf, if (flags & 1) { if(buf + data_size - ptr < 64) { av_log(avctx, AV_LOG_ERROR, "Header truncated\n"); - return -1; + return AVERROR_INVALIDDATA; } permute(ctx->qmat_chroma, ctx->prodsp.idct_permutation, ptr); } else { @@ -165,13 +155,13 @@ static int decode_picture_header(AVCodecContext *avctx, const uint8_t *buf, cons hdr_size = buf[0] >> 3; if (hdr_size < 8 || hdr_size > buf_size) { av_log(avctx, AV_LOG_ERROR, "error, wrong picture header size\n"); - return -1; + return AVERROR_INVALIDDATA; } pic_data_size = AV_RB32(buf + 1); if (pic_data_size > buf_size) { av_log(avctx, AV_LOG_ERROR, "error, wrong picture data size\n"); - return -1; + return AVERROR_INVALIDDATA; } log2_slice_mb_width = buf[7] >> 4; @@ -179,7 +169,7 @@ static int decode_picture_header(AVCodecContext *avctx, const uint8_t *buf, cons if (log2_slice_mb_width > 3 || log2_slice_mb_height) { av_log(avctx, AV_LOG_ERROR, "unsupported slice resolution: %dx%d\n", 1 << log2_slice_mb_width, 1 << log2_slice_mb_height); - return -1; + return AVERROR_INVALIDDATA; } ctx->mb_width = (avctx->width + 15) >> 4; @@ -203,7 +193,7 @@ static int decode_picture_header(AVCodecContext *avctx, const uint8_t *buf, cons if (hdr_size + slice_count*2 > buf_size) { av_log(avctx, AV_LOG_ERROR, "error, wrong slice count\n"); - return -1; + return AVERROR_INVALIDDATA; } // parse slice information @@ -230,7 +220,7 @@ static int decode_picture_header(AVCodecContext *avctx, const uint8_t *buf, cons if (slice->data_size < 6) { av_log(avctx, AV_LOG_ERROR, "error, wrong slice data size\n"); - return -1; + return AVERROR_INVALIDDATA; } mb_x += slice_mb_count; @@ -241,14 +231,14 @@ static int decode_picture_header(AVCodecContext *avctx, const uint8_t *buf, cons } if (data_ptr > buf + buf_size) { av_log(avctx, AV_LOG_ERROR, "error, slice out of bounds\n"); - return -1; + return AVERROR_INVALIDDATA; } } if (mb_x || mb_y != ctx->mb_height) { av_log(avctx, AV_LOG_ERROR, "error wrong mb count y %d h %d\n", mb_y, ctx->mb_height); - return -1; + return AVERROR_INVALIDDATA; } return pic_data_size; @@ -320,8 +310,8 @@ static av_always_inline void decode_dc_coeffs(GetBitContext *gb, int16_t *out, static const uint8_t run_to_cb[16] = { 0x06, 0x06, 0x05, 0x05, 0x04, 0x29, 0x29, 0x29, 0x29, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x4C }; static const uint8_t lev_to_cb[10] = { 0x04, 0x0A, 0x05, 0x06, 0x04, 0x28, 0x28, 0x28, 0x28, 0x4C }; -static av_always_inline void decode_ac_coeffs(AVCodecContext *avctx, GetBitContext *gb, - int16_t *out, int blocks_per_slice) +static av_always_inline int decode_ac_coeffs(AVCodecContext *avctx, GetBitContext *gb, + int16_t *out, int blocks_per_slice) { ProresContext *ctx = avctx->priv_data; int block_mask, sign; @@ -346,7 +336,7 @@ static av_always_inline void decode_ac_coeffs(AVCodecContext *avctx, GetBitConte pos += run + 1; if (pos >= max_coeffs) { av_log(avctx, AV_LOG_ERROR, "ac tex damaged %d, %d\n", pos, max_coeffs); - return; + return AVERROR_INVALIDDATA; } DECODE_CODEWORD(level, lev_to_cb[FFMIN(level, 9)]); @@ -360,18 +350,20 @@ static av_always_inline void decode_ac_coeffs(AVCodecContext *avctx, GetBitConte } CLOSE_READER(re, gb); + return 0; } -static void decode_slice_luma(AVCodecContext *avctx, SliceContext *slice, - uint16_t *dst, int dst_stride, - const uint8_t *buf, unsigned buf_size, - const int16_t *qmat) +static int decode_slice_luma(AVCodecContext *avctx, SliceContext *slice, + uint16_t *dst, int dst_stride, + const uint8_t *buf, unsigned buf_size, + const int16_t *qmat) { ProresContext *ctx = avctx->priv_data; LOCAL_ALIGNED_16(int16_t, blocks, [8*4*64]); int16_t *block; GetBitContext gb; int i, blocks_per_slice = slice->mb_count<<2; + int ret; for (i = 0; i < blocks_per_slice; i++) ctx->dsp.clear_block(blocks+(i<<6)); @@ -379,7 +371,8 @@ static void decode_slice_luma(AVCodecContext *avctx, SliceContext *slice, init_get_bits(&gb, buf, buf_size << 3); decode_dc_coeffs(&gb, blocks, blocks_per_slice); - decode_ac_coeffs(avctx, &gb, blocks, blocks_per_slice); + if ((ret = decode_ac_coeffs(avctx, &gb, blocks, blocks_per_slice)) < 0) + return ret; block = blocks; for (i = 0; i < slice->mb_count; i++) { @@ -390,18 +383,20 @@ static void decode_slice_luma(AVCodecContext *avctx, SliceContext *slice, block += 4*64; dst += 16; } + return 0; } -static void decode_slice_chroma(AVCodecContext *avctx, SliceContext *slice, - uint16_t *dst, int dst_stride, - const uint8_t *buf, unsigned buf_size, - const int16_t *qmat, int log2_blocks_per_mb) +static int decode_slice_chroma(AVCodecContext *avctx, SliceContext *slice, + uint16_t *dst, int dst_stride, + const uint8_t *buf, unsigned buf_size, + const int16_t *qmat, int log2_blocks_per_mb) { ProresContext *ctx = avctx->priv_data; LOCAL_ALIGNED_16(int16_t, blocks, [8*4*64]); int16_t *block; GetBitContext gb; int i, j, blocks_per_slice = slice->mb_count << log2_blocks_per_mb; + int ret; for (i = 0; i < blocks_per_slice; i++) ctx->dsp.clear_block(blocks+(i<<6)); @@ -409,7 +404,8 @@ static void decode_slice_chroma(AVCodecContext *avctx, SliceContext *slice, init_get_bits(&gb, buf, buf_size << 3); decode_dc_coeffs(&gb, blocks, blocks_per_slice); - decode_ac_coeffs(avctx, &gb, blocks, blocks_per_slice); + if ((ret = decode_ac_coeffs(avctx, &gb, blocks, blocks_per_slice)) < 0) + return ret; block = blocks; for (i = 0; i < slice->mb_count; i++) { @@ -420,6 +416,84 @@ static void decode_slice_chroma(AVCodecContext *avctx, SliceContext *slice, dst += 8; } } + return 0; +} + +static void unpack_alpha(GetBitContext *gb, uint16_t *dst, int num_coeffs, + const int num_bits) +{ + const int mask = (1 << num_bits) - 1; + int i, idx, val, alpha_val; + + idx = 0; + alpha_val = mask; + do { + do { + if (get_bits1(gb)) { + val = get_bits(gb, num_bits); + } else { + int sign; + val = get_bits(gb, num_bits == 16 ? 7 : 4); + sign = val & 1; + val = (val + 2) >> 1; + if (sign) + val = -val; + } + alpha_val = (alpha_val + val) & mask; + if (num_bits == 16) { + dst[idx++] = alpha_val >> 6; + } else { + dst[idx++] = (alpha_val << 2) | (alpha_val >> 6); + } + if (idx >= num_coeffs) + break; + } while (get_bits_left(gb)>0 && get_bits1(gb)); + val = get_bits(gb, 4); + if (!val) + val = get_bits(gb, 11); + if (idx + val > num_coeffs) + val = num_coeffs - idx; + if (num_bits == 16) { + for (i = 0; i < val; i++) + dst[idx++] = alpha_val >> 6; + } else { + for (i = 0; i < val; i++) + dst[idx++] = (alpha_val << 2) | (alpha_val >> 6); + + } + } while (idx < num_coeffs); +} + +/** + * Decode alpha slice plane. + */ +static void decode_slice_alpha(ProresContext *ctx, + uint16_t *dst, int dst_stride, + const uint8_t *buf, int buf_size, + int blocks_per_slice) +{ + GetBitContext gb; + int i; + LOCAL_ALIGNED_16(int16_t, blocks, [8*4*64]); + int16_t *block; + + for (i = 0; i < blocks_per_slice<<2; i++) + ctx->dsp.clear_block(blocks+(i<<6)); + + init_get_bits(&gb, buf, buf_size << 3); + + if (ctx->alpha_info == 2) { + unpack_alpha(&gb, blocks, blocks_per_slice * 4 * 64, 16); + } else { + unpack_alpha(&gb, blocks, blocks_per_slice * 4 * 64, 8); + } + + block = blocks; + for (i = 0; i < 16; i++) { + memcpy(dst, block, 16 * blocks_per_slice * sizeof(*dst)); + dst += dst_stride >> 1; + block += 16 * blocks_per_slice; + } } static int decode_slice_thread(AVCodecContext *avctx, void *arg, int jobnr, int threadnr) @@ -430,11 +504,12 @@ static int decode_slice_thread(AVCodecContext *avctx, void *arg, int jobnr, int AVFrame *pic = ctx->frame; int i, hdr_size, qscale, log2_chroma_blocks_per_mb; int luma_stride, chroma_stride; - int y_data_size, u_data_size, v_data_size; - uint8_t *dest_y, *dest_u, *dest_v; + int y_data_size, u_data_size, v_data_size, a_data_size; + uint8_t *dest_y, *dest_u, *dest_v, *dest_a; int16_t qmat_luma_scaled[64]; int16_t qmat_chroma_scaled[64]; int mb_x_shift; + int ret; slice->ret = -1; //av_log(avctx, AV_LOG_INFO, "slice %d mb width %d mb x %d y %d\n", @@ -448,11 +523,13 @@ static int decode_slice_thread(AVCodecContext *avctx, void *arg, int jobnr, int u_data_size = AV_RB16(buf + 4); v_data_size = slice->data_size - y_data_size - u_data_size - hdr_size; if (hdr_size > 7) v_data_size = AV_RB16(buf + 6); + a_data_size = slice->data_size - y_data_size - u_data_size - + v_data_size - hdr_size; if (y_data_size < 0 || u_data_size < 0 || v_data_size < 0 || hdr_size+y_data_size+u_data_size+v_data_size > slice->data_size){ av_log(avctx, AV_LOG_ERROR, "invalid plane data size\n"); - return -1; + return AVERROR_INVALIDDATA; } buf += hdr_size; @@ -470,7 +547,7 @@ static int decode_slice_thread(AVCodecContext *avctx, void *arg, int jobnr, int chroma_stride = pic->linesize[1] << 1; } - if (avctx->pix_fmt == AV_PIX_FMT_YUV444P10) { + if (avctx->pix_fmt == AV_PIX_FMT_YUV444P10 || avctx->pix_fmt == AV_PIX_FMT_YUVA444P10) { mb_x_shift = 5; log2_chroma_blocks_per_mb = 2; } else { @@ -481,24 +558,38 @@ static int decode_slice_thread(AVCodecContext *avctx, void *arg, int jobnr, int dest_y = pic->data[0] + (slice->mb_y << 4) * luma_stride + (slice->mb_x << 5); dest_u = pic->data[1] + (slice->mb_y << 4) * chroma_stride + (slice->mb_x << mb_x_shift); dest_v = pic->data[2] + (slice->mb_y << 4) * chroma_stride + (slice->mb_x << mb_x_shift); + dest_a = pic->data[3] + (slice->mb_y << 4) * luma_stride + (slice->mb_x << 5); if (ctx->frame_type && ctx->first_field ^ ctx->frame->top_field_first) { dest_y += pic->linesize[0]; dest_u += pic->linesize[1]; dest_v += pic->linesize[2]; + dest_a += pic->linesize[3]; } - decode_slice_luma(avctx, slice, (uint16_t*)dest_y, luma_stride, - buf, y_data_size, qmat_luma_scaled); + ret = decode_slice_luma(avctx, slice, (uint16_t*)dest_y, luma_stride, + buf, y_data_size, qmat_luma_scaled); + if (ret < 0) + return ret; if (!(avctx->flags & CODEC_FLAG_GRAY)) { - decode_slice_chroma(avctx, slice, (uint16_t*)dest_u, chroma_stride, - buf + y_data_size, u_data_size, - qmat_chroma_scaled, log2_chroma_blocks_per_mb); - decode_slice_chroma(avctx, slice, (uint16_t*)dest_v, chroma_stride, - buf + y_data_size + u_data_size, v_data_size, - qmat_chroma_scaled, log2_chroma_blocks_per_mb); + ret = decode_slice_chroma(avctx, slice, (uint16_t*)dest_u, chroma_stride, + buf + y_data_size, u_data_size, + qmat_chroma_scaled, log2_chroma_blocks_per_mb); + if (ret < 0) + return ret; + + ret = decode_slice_chroma(avctx, slice, (uint16_t*)dest_v, chroma_stride, + buf + y_data_size + u_data_size, v_data_size, + qmat_chroma_scaled, log2_chroma_blocks_per_mb); + if (ret < 0) + return ret; } + /* decode alpha plane if available */ + if (ctx->alpha_info && pic->data[3] && a_data_size) + decode_slice_alpha(ctx, (uint16_t*)dest_a, luma_stride, + buf + y_data_size + u_data_size + v_data_size, + a_data_size, slice->mb_count); slice->ret = 0; return 0; @@ -525,14 +616,16 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; - int frame_hdr_size, pic_size; + int frame_hdr_size, pic_size, ret; if (buf_size < 28 || AV_RL32(buf + 4) != AV_RL32("icpf")) { av_log(avctx, AV_LOG_ERROR, "invalid frame header\n"); - return -1; + return AVERROR_INVALIDDATA; } ctx->frame = frame; + ctx->frame->pict_type = AV_PICTURE_TYPE_I; + ctx->frame->key_frame = 1; ctx->first_field = 1; buf += 8; @@ -540,24 +633,24 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, frame_hdr_size = decode_frame_header(ctx, buf, buf_size, avctx); if (frame_hdr_size < 0) - return -1; + return frame_hdr_size; buf += frame_hdr_size; buf_size -= frame_hdr_size; - if (ff_get_buffer(avctx, frame, 0) < 0) - return -1; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; decode_picture: pic_size = decode_picture_header(avctx, buf, buf_size); if (pic_size < 0) { av_log(avctx, AV_LOG_ERROR, "error decoding picture header\n"); - return -1; + return pic_size; } - if (decode_picture(avctx)) { + if ((ret = decode_picture(avctx)) < 0) { av_log(avctx, AV_LOG_ERROR, "error decoding picture\n"); - return -1; + return ret; } buf += pic_size; @@ -584,12 +677,12 @@ static av_cold int decode_close(AVCodecContext *avctx) AVCodec ff_prores_decoder = { .name = "prores", + .long_name = NULL_IF_CONFIG_SMALL("ProRes"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_PRORES, .priv_data_size = sizeof(ProresContext), .init = decode_init, .close = decode_close, .decode = decode_frame, - .long_name = NULL_IF_CONFIG_SMALL("ProRes"), .capabilities = CODEC_CAP_DR1 | CODEC_CAP_SLICE_THREADS, }; |
