On Fri, 17 May 2013 19:43:36 +0200, Kostya Shishkov <[email protected]> wrote: > --- > Maybe I'll work on encoder support as well. > --- > libavcodec/proresdec.c | 112 > ++++++++++++++++++++++++++++++++++++++++++++---- > 1 file changed, 103 insertions(+), 9 deletions(-) > > diff --git a/libavcodec/proresdec.c b/libavcodec/proresdec.c > index c42e444..0d1eb7a 100644 > --- a/libavcodec/proresdec.c > +++ b/libavcodec/proresdec.c > @@ -134,12 +134,21 @@ static int decode_frame_header(ProresContext *ctx, > const uint8_t *buf, > ctx->chroma_factor = (buf[12] >> 6) & 3; > ctx->mb_chroma_factor = ctx->chroma_factor + 2; > ctx->num_chroma_blocks = (1 << ctx->chroma_factor) >> 1; > + 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; > + } > + > switch (ctx->chroma_factor) { > case 2: > - avctx->pix_fmt = AV_PIX_FMT_YUV422P10; > + avctx->pix_fmt = ctx->alpha_info ? AV_PIX_FMT_YUVA422P10 > + : AV_PIX_FMT_YUV422P10; > break; > case 3: > - avctx->pix_fmt = AV_PIX_FMT_YUV444P10; > + avctx->pix_fmt = ctx->alpha_info ? AV_PIX_FMT_YUVA444P10 > + : AV_PIX_FMT_YUV444P10; > break; > default: > av_log(avctx, AV_LOG_ERROR, > @@ -168,10 +177,6 @@ static int decode_frame_header(ProresContext *ctx, const > uint8_t *buf, > avctx->color_trc = buf[15]; > avctx->colorspace = buf[16]; > > - ctx->alpha_info = buf[17] & 0xf; > - if (ctx->alpha_info) > - avpriv_report_missing_feature(avctx, "Alpha channel"); > - > ctx->qmat_changed = 0; > ptr = buf + 20; > flags = buf[19]; > @@ -466,6 +471,78 @@ static void decode_slice_plane(ProresContext *ctx, > ProresThreadData *td, > } > > > +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 - 1) > + break; > + } while (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_alpha_plane(ProresContext *ctx, ProresThreadData *td, > + const uint8_t *buf, int data_size, > + uint16_t *out_ptr, int linesize, > + int mbs_per_slice) > +{ > + GetBitContext gb; > + int i; > + uint16_t *block_ptr; > + > + memset(td->blocks, 0, 8 * 4 * 64 * sizeof(*td->blocks)); > + > + init_get_bits(&gb, buf, data_size << 3); > + > + if (ctx->alpha_info == 2) > + unpack_alpha(&gb, td->blocks, mbs_per_slice * 4 * 64, 16); > + else > + unpack_alpha(&gb, td->blocks, mbs_per_slice * 4 * 64, 8); > + > + block_ptr = td->blocks; > + > + for (i = 0; i < 16; i++) { > + memcpy(out_ptr, block_ptr, 16 * mbs_per_slice * sizeof(*out_ptr)); > + out_ptr += linesize >> 1; > + block_ptr += 16 * mbs_per_slice; > + } > +} > + > static int decode_slice(AVCodecContext *avctx, void *tdata) > { > ProresThreadData *td = tdata; > @@ -476,11 +553,12 @@ static int decode_slice(AVCodecContext *avctx, void > *tdata) > int slice_num = td->slice_num; > int mbs_per_slice = td->slice_width; > const uint8_t *buf; > - uint8_t *y_data, *u_data, *v_data; > + uint8_t *y_data, *u_data, *v_data, *a_data; > AVFrame *pic = ctx->frame; > int i, sf, slice_width_factor; > - int slice_data_size, hdr_size, y_data_size, u_data_size, v_data_size; > - int y_linesize, u_linesize, v_linesize; > + int slice_data_size, hdr_size; > + int y_data_size, u_data_size, v_data_size, a_data_size; > + int y_linesize, u_linesize, v_linesize, a_linesize; > > buf = ctx->slice_data[slice_num].index; > slice_data_size = ctx->slice_data[slice_num + 1].index - buf; > @@ -490,19 +568,23 @@ static int decode_slice(AVCodecContext *avctx, void > *tdata) > y_data = pic->data[0]; > u_data = pic->data[1]; > v_data = pic->data[2]; > + a_data = pic->data[3]; > y_linesize = pic->linesize[0]; > u_linesize = pic->linesize[1]; > v_linesize = pic->linesize[2]; > + a_linesize = pic->linesize[3]; > > if (pic->interlaced_frame) { > if (!(pic_num ^ pic->top_field_first)) { > y_data += y_linesize; > u_data += u_linesize; > v_data += v_linesize; > + a_data += a_linesize; > } > y_linesize <<= 1; > u_linesize <<= 1; > v_linesize <<= 1; > + a_linesize <<= 1; > } > > if (slice_data_size < 6) { > @@ -516,6 +598,8 @@ static int decode_slice(AVCodecContext *avctx, void > *tdata) > u_data_size = AV_RB16(buf + 4); > v_data_size = hdr_size > 7 ? AV_RB16(buf + 6) : > slice_data_size - y_data_size - u_data_size - hdr_size; > + a_data_size = slice_data_size - y_data_size - u_data_size - > + v_data_size - hdr_size; > > if (hdr_size + y_data_size + u_data_size + v_data_size > slice_data_size > || > v_data_size < 0 || hdr_size < 6) { > @@ -560,6 +644,16 @@ static int decode_slice(AVCodecContext *avctx, void > *tdata) > slice_width_factor + ctx->chroma_factor - 1, > td->qmat_chroma_scaled, 1); > > + /* decode alpha plane if available */ > + if (a_data && a_data_size) > + decode_alpha_plane(ctx, td, > + buf + hdr_size + y_data_size + > + u_data_size + v_data_size, > + a_data_size, > + (uint16_t*) (a_data + (mb_y_pos << 4) * > a_linesize + > + (mb_x_pos << 5)), a_linesize, > + mbs_per_slice); > +
This construct is quite unshapely and could be prettiefied. E.g. the third parameter shares a lot of stuff with a_data_size. The fifth parameter could be declared a temp variable. -- Anton Khirnov _______________________________________________ libav-devel mailing list [email protected] https://lists.libav.org/mailman/listinfo/libav-devel
