X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fproresdec2.c;h=2652a31c81f9c7e90457d4e0ee2f0bebddc920f7;hb=d85c84eb38e5845495dacfcef82265a433fdd043;hp=94323df1282ed4822b86413b90fe091a7438f56d;hpb=1cccf9365df0351467eca13313ae989da5c2b0f3;p=ffmpeg diff --git a/libavcodec/proresdec2.c b/libavcodec/proresdec2.c index 94323df1282..2652a31c81f 100644 --- a/libavcodec/proresdec2.c +++ b/libavcodec/proresdec2.c @@ -46,9 +46,13 @@ static void permute(uint8_t *dst, const uint8_t *src, const uint8_t permutation[ dst[i] = permutation[src[i]]; } -static void unpack_alpha_10(GetBitContext *gb, uint16_t *dst, int num_coeffs, - const int num_bits) -{ +#define ALPHA_SHIFT_16_TO_10(alpha_val) (alpha_val >> 6) +#define ALPHA_SHIFT_8_TO_10(alpha_val) ((alpha_val << 2) | (alpha_val >> 6)) +#define ALPHA_SHIFT_16_TO_12(alpha_val) (alpha_val >> 4) +#define ALPHA_SHIFT_8_TO_12(alpha_val) ((alpha_val << 4) | (alpha_val >> 4)) + +static void inline unpack_alpha(GetBitContext *gb, uint16_t *dst, int num_coeffs, + const int num_bits, const int decode_precision) { const int mask = (1 << num_bits) - 1; int i, idx, val, alpha_val; @@ -68,9 +72,17 @@ static void unpack_alpha_10(GetBitContext *gb, uint16_t *dst, int num_coeffs, } alpha_val = (alpha_val + val) & mask; if (num_bits == 16) { - dst[idx++] = alpha_val >> 6; + if (decode_precision == 10) { + dst[idx++] = ALPHA_SHIFT_16_TO_10(alpha_val); + } else { /* 12b */ + dst[idx++] = ALPHA_SHIFT_16_TO_12(alpha_val); + } } else { - dst[idx++] = (alpha_val << 2) | (alpha_val >> 6); + if (decode_precision == 10) { + dst[idx++] = ALPHA_SHIFT_8_TO_10(alpha_val); + } else { /* 12b */ + dst[idx++] = ALPHA_SHIFT_8_TO_12(alpha_val); + } } if (idx >= num_coeffs) break; @@ -81,16 +93,45 @@ static void unpack_alpha_10(GetBitContext *gb, uint16_t *dst, int num_coeffs, if (idx + val > num_coeffs) val = num_coeffs - idx; if (num_bits == 16) { - for (i = 0; i < val; i++) - dst[idx++] = alpha_val >> 6; + for (i = 0; i < val; i++) { + if (decode_precision == 10) { + dst[idx++] = ALPHA_SHIFT_16_TO_10(alpha_val); + } else { /* 12b */ + dst[idx++] = ALPHA_SHIFT_16_TO_12(alpha_val); + } + } } else { - for (i = 0; i < val; i++) - dst[idx++] = (alpha_val << 2) | (alpha_val >> 6); - + for (i = 0; i < val; i++) { + if (decode_precision == 10) { + dst[idx++] = ALPHA_SHIFT_8_TO_10(alpha_val); + } else { /* 12b */ + dst[idx++] = ALPHA_SHIFT_8_TO_12(alpha_val); + } + } } } while (idx < num_coeffs); } +static void unpack_alpha_10(GetBitContext *gb, uint16_t *dst, int num_coeffs, + const int num_bits) +{ + if (num_bits == 16) { + unpack_alpha(gb, dst, num_coeffs, 16, 10); + } else { /* 8 bits alpha */ + unpack_alpha(gb, dst, num_coeffs, 8, 10); + } +} + +static void unpack_alpha_12(GetBitContext *gb, uint16_t *dst, int num_coeffs, + const int num_bits) +{ + if (num_bits == 16) { + unpack_alpha(gb, dst, num_coeffs, 16, 12); + } else { /* 8 bits alpha */ + unpack_alpha(gb, dst, num_coeffs, 8, 12); + } +} + static av_cold int decode_init(AVCodecContext *avctx) { int ret = 0; @@ -114,15 +155,23 @@ static av_cold int decode_init(AVCodecContext *avctx) break; case MKTAG('a','p','4','h'): avctx->profile = FF_PROFILE_PRORES_4444; + avctx->bits_per_raw_sample = 12; break; case MKTAG('a','p','4','x'): avctx->profile = FF_PROFILE_PRORES_XQ; + avctx->bits_per_raw_sample = 12; break; default: avctx->profile = FF_PROFILE_UNKNOWN; av_log(avctx, AV_LOG_WARNING, "Unknown prores profile %d\n", avctx->codec_tag); } + if (avctx->bits_per_raw_sample == 10) { + av_log(avctx, AV_LOG_DEBUG, "Auto bitdepth precision. Use 10b decoding based on codec tag.\n"); + } else { /* 12b */ + av_log(avctx, AV_LOG_DEBUG, "Auto bitdepth precision. Use 12b decoding based on codec tag.\n"); + } + ff_blockdsp_init(&ctx->bdsp, avctx); ret = ff_proresdsp_init(&ctx->prodsp, avctx); if (ret < 0) { @@ -138,6 +187,8 @@ static av_cold int decode_init(AVCodecContext *avctx) if (avctx->bits_per_raw_sample == 10){ ctx->unpack_alpha = unpack_alpha_10; + } else if (avctx->bits_per_raw_sample == 12){ + ctx->unpack_alpha = unpack_alpha_12; } else { av_log(avctx, AV_LOG_ERROR, "Fail to set unpack_alpha for bits per raw sample %d\n", avctx->bits_per_raw_sample); return AVERROR_BUG; @@ -168,10 +219,14 @@ static int decode_frame_header(ProresContext *ctx, const uint8_t *buf, width = AV_RB16(buf + 8); height = AV_RB16(buf + 10); + if (width != avctx->width || height != avctx->height) { - av_log(avctx, AV_LOG_ERROR, "picture resolution change: %dx%d -> %dx%d\n", + int ret; + + av_log(avctx, AV_LOG_WARNING, "picture resolution change: %dx%d -> %dx%d\n", avctx->width, avctx->height, width, height); - return AVERROR_PATCHWELCOME; + if ((ret = ff_set_dimensions(avctx, width, height)) < 0) + return ret; } ctx->frame_type = (buf[12] >> 2) & 3; @@ -194,9 +249,17 @@ static int decode_frame_header(ProresContext *ctx, const uint8_t *buf, } if (ctx->alpha_info) { - avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUVA444P10 : AV_PIX_FMT_YUVA422P10; + if (avctx->bits_per_raw_sample == 10) { + avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUVA444P10 : AV_PIX_FMT_YUVA422P10; + } else { /* 12b */ + avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUVA444P12 : AV_PIX_FMT_YUVA422P12; + } } else { - avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUV444P10 : AV_PIX_FMT_YUV422P10; + if (avctx->bits_per_raw_sample == 10) { + avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUV444P10 : AV_PIX_FMT_YUV422P10; + } else { /* 12b */ + avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUV444P12 : AV_PIX_FMT_YUV422P12; + } } avctx->color_primaries = buf[14]; @@ -542,6 +605,7 @@ static void decode_slice_alpha(ProresContext *ctx, } block = blocks; + for (i = 0; i < 16; i++) { memcpy(dst, block, 16 * blocks_per_slice * sizeof(*dst)); dst += dst_stride >> 1; @@ -563,6 +627,7 @@ static int decode_slice_thread(AVCodecContext *avctx, void *arg, int jobnr, int LOCAL_ALIGNED_16(int16_t, qmat_chroma_scaled,[64]); int mb_x_shift; int ret; + uint16_t val_no_chroma; slice->ret = -1; //av_log(avctx, AV_LOG_INFO, "slice %d mb width %d mb x %d y %d\n", @@ -600,7 +665,8 @@ 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 || avctx->pix_fmt == AV_PIX_FMT_YUVA444P10) { + if (avctx->pix_fmt == AV_PIX_FMT_YUV444P10 || avctx->pix_fmt == AV_PIX_FMT_YUVA444P10 || + avctx->pix_fmt == AV_PIX_FMT_YUV444P12 || avctx->pix_fmt == AV_PIX_FMT_YUVA444P12) { mb_x_shift = 5; log2_chroma_blocks_per_mb = 2; } else { @@ -641,10 +707,15 @@ static int decode_slice_thread(AVCodecContext *avctx, void *arg, int jobnr, int else { size_t mb_max_x = slice->mb_count << (mb_x_shift - 1); size_t i, j; + if (avctx->bits_per_raw_sample == 10) { + val_no_chroma = 511; + } else { /* 12b */ + val_no_chroma = 511 * 4; + } for (i = 0; i < 16; ++i) for (j = 0; j < mb_max_x; ++j) { - *(uint16_t*)(dest_u + (i * chroma_stride) + (j << 1)) = 511; - *(uint16_t*)(dest_v + (i * chroma_stride) + (j << 1)) = 511; + *(uint16_t*)(dest_u + (i * chroma_stride) + (j << 1)) = val_no_chroma; + *(uint16_t*)(dest_v + (i * chroma_stride) + (j << 1)) = val_no_chroma; } } @@ -707,9 +778,6 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, buf += frame_hdr_size; buf_size -= frame_hdr_size; - if ((ret = ff_thread_get_buffer(avctx, &tframe, 0)) < 0) - return ret; - decode_picture: pic_size = decode_picture_header(avctx, buf, buf_size); if (pic_size < 0) { @@ -717,6 +785,10 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return pic_size; } + if (ctx->first_field) + if ((ret = ff_thread_get_buffer(avctx, &tframe, 0)) < 0) + return ret; + if ((ret = decode_picture(avctx)) < 0) { av_log(avctx, AV_LOG_ERROR, "error decoding picture\n"); return ret;