From 17c11cef9f99d31e31dd9176ee2f26bdf6e5d351 Mon Sep 17 00:00:00 2001 From: Derek Buitenhuis Date: Fri, 10 Aug 2012 16:05:49 +0000 Subject: [PATCH] cllc: Implement ARGB support Signed-off-by: Derek Buitenhuis --- libavcodec/cllc.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) diff --git a/libavcodec/cllc.c b/libavcodec/cllc.c index 68668ef39d..a1514179b7 100644 --- a/libavcodec/cllc.c +++ b/libavcodec/cllc.c @@ -74,6 +74,80 @@ static int read_code_table(CLLCContext *ctx, GetBitContext *gb, VLC *vlc) codes, 2, 2, symbols, 1, 1, 0); } +/* + * Unlike the RGB24 read/restore, which reads in a component at a time, + * ARGB read/restore reads in ARGB quads. + */ +static int read_argb_line(CLLCContext *ctx, GetBitContext *gb, int *top_left, + VLC *vlc, uint8_t *outbuf) +{ + uint8_t *dst; + int pred[4]; + int code; + int i; + + OPEN_READER(bits, gb); + + dst = outbuf; + pred[0] = top_left[0]; + pred[1] = top_left[1]; + pred[2] = top_left[2]; + pred[3] = top_left[3]; + + for (i = 0; i < ctx->avctx->width; i++) { + /* Always get the alpha component */ + UPDATE_CACHE(bits, gb); + GET_VLC(code, bits, gb, vlc[0].table, 7, 2); + + pred[0] += code; + dst[0] = pred[0]; + + /* Skip the components if they are entirely transparent */ + if (dst[0]) { + /* Red */ + UPDATE_CACHE(bits, gb); + GET_VLC(code, bits, gb, vlc[1].table, 7, 2); + + pred[1] += code; + dst[1] = pred[1]; + + /* Green */ + UPDATE_CACHE(bits, gb); + GET_VLC(code, bits, gb, vlc[2].table, 7, 2); + + pred[2] += code; + dst[2] = pred[2]; + + /* Blue */ + UPDATE_CACHE(bits, gb); + GET_VLC(code, bits, gb, vlc[3].table, 7, 2); + + pred[3] += code; + dst[3] = pred[3]; + } else { + dst[1] = 0; + dst[2] = 0; + dst[3] = 0; + } + + dst += 4; + } + + CLOSE_READER(bits, gb); + + dst -= 4 * ctx->avctx->width; + top_left[0] = dst[0]; + + /* Only stash components if they are not transparent */ + if (top_left[0]) { + top_left[1] = dst[1]; + top_left[2] = dst[2]; + top_left[3] = dst[3]; + } + + return 0; +} + static int read_rgb24_component_line(CLLCContext *ctx, GetBitContext *gb, int *top_left, VLC *vlc, uint8_t *outbuf) { @@ -104,6 +178,50 @@ static int read_rgb24_component_line(CLLCContext *ctx, GetBitContext *gb, return 0; } +static int decode_argb_frame(CLLCContext *ctx, GetBitContext *gb, AVFrame *pic) +{ + AVCodecContext *avctx = ctx->avctx; + uint8_t *dst; + int pred[4]; + int ret; + int i, j; + VLC vlc[4]; + + pred[0] = 0; + pred[1] = 0x80; + pred[2] = 0x80; + pred[3] = 0x80; + + dst = pic->data[0]; + + skip_bits(gb, 16); + + /* Read in code table for each plane */ + for (i = 0; i < 4; i++) { + ret = read_code_table(ctx, gb, &vlc[i]); + if (ret < 0) { + for (j = 0; j <= i; j++) + ff_free_vlc(&vlc[j]); + + av_log(ctx->avctx, AV_LOG_ERROR, + "Could not read code table %d.\n", i); + return ret; + } + } + + /* Read in and restore every line */ + for (i = 0; i < avctx->height; i++) { + read_argb_line(ctx, gb, pred, vlc, dst); + + dst += pic->linesize[0]; + } + + for (i = 0; i < 4; i++) + ff_free_vlc(&vlc[i]); + + return 0; +} + static int decode_rgb24_frame(CLLCContext *ctx, GetBitContext *gb, AVFrame *pic) { AVCodecContext *avctx = ctx->avctx; @@ -224,6 +342,21 @@ static int cllc_decode_frame(AVCodecContext *avctx, void *data, if (ret < 0) return ret; + break; + case 3: + avctx->pix_fmt = PIX_FMT_ARGB; + avctx->bits_per_raw_sample = 8; + + ret = avctx->get_buffer(avctx, pic); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Could not allocate buffer.\n"); + return ret; + } + + ret = decode_argb_frame(ctx, &gb, pic); + if (ret < 0) + return ret; + break; default: av_log(avctx, AV_LOG_ERROR, "Unknown coding type: %d.\n", coding_type);