From 6956673e39396cf717f3e4d1caeab495b0ed9aa9 Mon Sep 17 00:00:00 2001 From: Nathan Caldwell Date: Sun, 2 Aug 2009 00:51:46 -0600 Subject: [PATCH] Implement decoding of U and V channels. -Reorder some functions to remove forward declirations -Remove/add parameters to functions to make implementation clearer. Still unknown if U and V channels are in the correct order, of if they need swapped. --- libavcodec/lagarith.c | 372 ++++++++++++++++++++++++++------------------------ 1 file changed, 193 insertions(+), 179 deletions(-) diff --git a/libavcodec/lagarith.c b/libavcodec/lagarith.c index 8fc5637f0e..e3df924131 100644 --- a/libavcodec/lagarith.c +++ b/libavcodec/lagarith.c @@ -62,11 +62,6 @@ typedef struct LagarithContext{ uint32_t i_shift; } LagarithContext; -/* Forward declirations */ -static int lag_decode_arith_plane(LagarithContext *lag_ctx, uint8_t *p_dst, int i_stride, int b_obsolete); -static uint32_t lag_read_prob_header(LagarithContext *lag_ctx); - - /** * initializes decoder * @param avctx codec context @@ -85,95 +80,9 @@ static av_cold int lag_decode_init(AVCodecContext *avctx) return 0; } - -/** -* decode a frame -* @param avctx codec context -* @param data output AVFrame -* @param data_size size of output data or 0 if no picture is returned -* @param avpkt input packet -* @return number of consumed bytes on success or negative if decode fails -*/ -static int lag_decode_frame(AVCodecContext *avctx, - void *data, int *data_size, - AVPacket *avpkt) -{ - const uint8_t *p_buf = avpkt->data; - int buf_size = avpkt->size; - LagarithContext *lag_ctx = avctx->priv_data; - AVFrame * const p= &lag_ctx->picture; - uint8_t i_frametype = 0; - int i; - uint32_t offset_gu = 0, offset_bv = 0; - - AVFrame *picture = data; - - if(p->data[0]) - avctx->release_buffer(avctx, p); - - p->reference = 0; - p->key_frame = 1; - - init_get_bits(&lag_ctx->gb, p_buf, buf_size); - - i_frametype = get_bits(&lag_ctx->gb, 8); - - offset_gu = *(const uint32_t*)(lag_ctx->gb.buffer+(get_bits_count(&lag_ctx->gb)/8)); - skip_bits_long(&lag_ctx->gb, 32); - offset_bv = *(const uint32_t*)(lag_ctx->gb.buffer+(get_bits_count(&lag_ctx->gb)/8)); - skip_bits_long(&lag_ctx->gb, 32); - - switch(i_frametype) { - case FRAME_RAW: - { - /* Assume RGB, this is incorrect. Lagarith doesn't specify a type for raw frames. */ - avctx->pix_fmt = PIX_FMT_RGB24; - for(i = 0; i < 3; i++) - memcpy(picture->data[i], p_buf +((avctx->width * avctx->height * i)+1), buf_size + ((avctx->width * avctx->height * i) - 1)); - } - break; - case FRAME_ARITH_RGB24: - avctx->pix_fmt = PIX_FMT_RGB24; - - if(avctx->get_buffer(avctx, p) < 0){ - av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); - return -1; - } - - lag_decode_arith_plane(lag_ctx, p->data[0], p->linesize[0], 0); - break; - case FRAME_ARITH_YV12: - avctx->pix_fmt = PIX_FMT_YUV420P; - - if(avctx->get_buffer(avctx, p) < 0){ - av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); - return -1; - } - - lag_decode_arith_plane(lag_ctx, p->data[0], p->linesize[0], 0); -// lag_decode_arith_plane(lag_ctx, p->data[1], p->linesize[1], 0); -// lag_decode_arith_plane(lag_ctx, p->data[2], p->linesize[2], 0); - - memset(p->data[1], 0x80, p->linesize[1]/2*avctx->height); - memset(p->data[2], 0x80, p->linesize[2]/2*avctx->height); - break; - default: - av_log(avctx, AV_LOG_ERROR, "Unsupported Lagarith frame type: %#x\n", i_frametype); - return -1; - } - - *picture= *(AVFrame*)&lag_ctx->picture; - *data_size = sizeof(AVPicture); - - return buf_size; -} - - -static void lag_rac_init(lag_rac *l, GetBitContext *gb, int length, int scale) -{ - int i, j; - +static void lag_rac_init(lag_rac *l, GetBitContext *gb, int length) +{ /* According to reference decoder "1st byte is garbage" */ // skip_bits(gb, 8); align_get_bits(gb); @@ -184,8 +93,8 @@ static void lag_rac_init(lag_rac *l, GetBitContext *gb, int length, int scale) l->range = 0x80; l->low = *l->bytestream >> 1; - l->scale = scale; l->hash_shift = FFMAX(l->scale-8, 0); + /* for (i = 0, j = 0; i < 257; i++) { unsigned r = i << l->hash_shift; @@ -239,15 +148,15 @@ static inline int lag_get_rac(struct lag_rac *l) return val; } -static void lag_decode_zero_runs(LagarithContext *lag_ctx, const uint8_t *p_src, uint8_t *p_dst, int length, int level) +static void lag_decode_zero_runs(const uint8_t *p_src, uint8_t *p_dst, int i_length, int i_escape) { - int b=0; - uint8_t mask1 = level < 2 ? 0x00 : 0xff; - uint8_t mask2 = level < 3 ? 0x00 : 0xff; - const uint8_t *p_end = (p_src + length)-(level-1); - uint8_t *p_start = p_src; + uint8_t mask1 = i_escape < 2 ? 0x00 : 0xff; + uint8_t mask2 = i_escape < 3 ? 0x00 : 0xff; + const uint8_t *p_end = (p_src + i_length)-(i_escape-1); - /* FIXME: This _will_ overrun! */ + /* FIXME: This _will_ overrun! + * Also, the last line of p_src doesn't get copied to p_dst. + */ //dprintf(lag_ctx->avctx, "length = %d\n", length); while( p_src < p_end ) { @@ -257,9 +166,9 @@ static void lag_decode_zero_runs(LagarithContext *lag_ctx, const uint8_t *p_src, } //dprintf(lag_ctx->avctx, "zero run at %d, length %d\n", p_src-p_start, run_table[p_src[level]]); - memset(p_dst, 0, run_table[p_src[level]]+level); - p_dst += run_table[p_src[level]]+level; - p_src += level+1; + memset(p_dst, 0, run_table[p_src[i_escape]]+i_escape); + p_dst += run_table[p_src[i_escape]]+i_escape; + p_src += i_escape+1; } } @@ -269,12 +178,12 @@ static inline int lag_predict(uint8_t *p_src, int stride) int L = p_src[-1]; int TL = p_src[-stride - 1]; - return mid_pred( T, L, T + L - TL); + return mid_pred( T, L, L + T - TL); } -static void lag_pred_plane(LagarithContext *lag_ctx, uint8_t *p_buf, int i_width, int i_height, int i_stride) +static void lag_pred_plane(uint8_t *p_buf, int i_width, int i_height, int i_stride) { - int i, j; + int i; int mode = 0; //dprintf(lag_ctx->avctx, "source[0] = %#x\n", p_buf[0]); @@ -292,64 +201,15 @@ static void lag_pred_plane(LagarithContext *lag_ctx, uint8_t *p_buf, int i_width for(i = i_stride+1; i < i_stride * i_height; i++) { - int T = p_buf[i-i_stride]; - int L = p_buf[i-1]; - int TL = p_buf[i-i_stride-1]; //dprintf(lag_ctx->avctx, "source[%d] = %#x, L = %#x, T = %#x, TL = %#x, L+T-TL = %#x, median = %#x\n", // i, p_buf[i], L, T, TL, T+L-TL, mid_pred(T, L, T+L-TL) ); - p_buf[i] += mid_pred(T, L, L+T-TL); + p_buf[i] += lag_predict(p_buf+i, i_stride); //dprintf(lag_ctx->avctx, "source[%d] = %#x\n", i, p_buf[i]); } } -static int lag_decode_arith_plane(LagarithContext *lag_ctx, uint8_t *p_dst, int i_stride, int b_obsolete) -{ - int rle = get_bits(&lag_ctx->gb, 8); - uint32_t offset; - uint32_t length; - uint8_t *buf = NULL, *buf2 = NULL; - uint8_t *p_end = NULL; - int i=0; - - if (rle < 4) { - length = *(const uint32_t*)(lag_ctx->gb.buffer+(get_bits_count(&lag_ctx->gb)/8)); -//dprintf(lag_ctx->avctx, "length = %d\tsize = %d\n", length, lag_ctx->avctx->height*lag_ctx->avctx->width); - skip_bits_long(&lag_ctx->gb, 32); - - offset = lag_read_prob_header(lag_ctx); - - lag_rac_init(&lag_ctx->rac, &lag_ctx->gb, length, lag_ctx->i_shift); - - buf = av_malloc(length); - - while(irac); - } - - buf2 = av_malloc(lag_ctx->avctx->width * lag_ctx->avctx->height); - - lag_decode_zero_runs(lag_ctx, buf, buf2, length, rle); - - av_free(buf); - - lag_pred_plane(lag_ctx, buf2, lag_ctx->avctx->width, lag_ctx->avctx->height, lag_ctx->avctx->width); - - for(i=0; i < lag_ctx->avctx->height-1; i++) - { - memcpy(p_dst+(i*i_stride), buf2+(i*lag_ctx->avctx->width), lag_ctx->avctx->width); - } - - av_free(buf2); - - } else { - /* TODO */ - } - - return 0; -} - -static uint32_t lag_decode_prob(LagarithContext *lag_ctx) +static uint32_t lag_decode_prob(GetBitContext *p_gb) { unsigned int bit=0; unsigned int series[]={1,2,3,5,8,13,21,34}; @@ -361,14 +221,14 @@ static uint32_t lag_decode_prob(LagarithContext *lag_ctx) for( i=0 ; !( prevbit && bit ); i++) { prevbit = bit; - bit = get_bits1(&lag_ctx->gb); + bit = get_bits1(p_gb); if ( bit && !prevbit ) bits+=series[i]; } bits--; if (bits == 0) return 0; - value = get_bits_long(&lag_ctx->gb, bits); + value = get_bits_long(p_gb, bits); value |= 1 << bits; return value-1; @@ -386,52 +246,52 @@ static inline uint32_t clp2(uint32_t x) return x+1; } -static uint32_t lag_read_prob_header(LagarithContext *lag_ctx) +static uint32_t lag_read_prob_header(lag_rac *p_rac, GetBitContext *p_gb) { unsigned int freq = 0; unsigned int i,j; unsigned int cumul_prob = 0; unsigned int temp = 1; double scale_factor = 0; - unsigned int new_cumul_prob = 0; + unsigned int scaled_cumul_prob = 0; - lag_ctx->rac.prob[0] = 0; + p_rac->prob[0] = 0; /* Read frequencies from bitstream */ for(i=1; i<257; i++) { - lag_ctx->rac.prob[i] = lag_decode_prob(lag_ctx); - cumul_prob += lag_ctx->rac.prob[i]; - if(lag_ctx->rac.prob[i] == 0) { - freq = lag_decode_prob(lag_ctx); + p_rac->prob[i] = lag_decode_prob(p_gb); + cumul_prob += p_rac->prob[i]; + if(p_rac->prob[i] == 0) { + freq = lag_decode_prob(p_gb); if(i+freq >= 258) freq = 257-i; for(j=0; j < freq; j++) - lag_ctx->rac.prob[++i] = 0; + p_rac->prob[++i] = 0; } } - /* Scale frequencies so cumulative frequency is a power of 2. */ + /* Scale probabilities so cumulative probability is a power of 2. */ temp = clp2(cumul_prob); scale_factor = temp/(double)cumul_prob; for(i=1; i<257; i++) { - lag_ctx->rac.prob[i] = (unsigned int)(lag_ctx->rac.prob[i] * scale_factor); - new_cumul_prob += lag_ctx->rac.prob[i]; + p_rac->prob[i] = (unsigned int)(p_rac->prob[i] * scale_factor); + scaled_cumul_prob += p_rac->prob[i]; } - new_cumul_prob = temp - new_cumul_prob; + scaled_cumul_prob = temp - scaled_cumul_prob; - if ( (signed int)new_cumul_prob < 0 ){ // should never happen + if ( (signed int)scaled_cumul_prob < 0 ){ // should never happen /* TODO */ } i=0; - while(new_cumul_prob) + while(scaled_cumul_prob) { - if( lag_ctx->rac.prob[i+1] ) { - lag_ctx->rac.prob[i+1]++; - new_cumul_prob--; + if( p_rac->prob[i+1] ) { + p_rac->prob[i+1]++; + scaled_cumul_prob--; } /* Comment from reference source: @@ -450,16 +310,170 @@ static uint32_t lag_read_prob_header(LagarithContext *lag_ctx) for( i=0; temp; i++) temp >>= 1; - lag_ctx->i_shift = i-1; + p_rac->scale = i-1; /* Fill probability array with cumulative probability for each symbol. */ for( i=1; i<257; i++ ) - lag_ctx->rac.prob[i] += lag_ctx->rac.prob[i-1]; + p_rac->prob[i] += p_rac->prob[i-1]; + + return 0; +} + +static int lag_decode_arith_plane(uint8_t *p_dst, int i_width, int i_height, int i_stride, + const uint8_t *p_src, int i_src, int b_obsolete) +{ + int rle = p_src[0]; + uint32_t offset; + uint32_t length; + uint8_t *buf = NULL, *buf2 = NULL; + int i=0; + GetBitContext gb; + lag_rac rac; +//dprintf(l->avctx, "rle = %d\n", rle); + + if ( rle && ( rle < 8 || rle == 0xff ) ) { + if (rle < 4) { + length = *(const uint32_t*)(p_src+1); +//dprintf(l->avctx, "length = %d, size = %d\n", length, i_height*i_width); + + init_get_bits(&gb, p_src+5, i_src*8); + + offset = lag_read_prob_header(&rac, &gb); + + lag_rac_init(&rac, &gb, length); + + buf = av_malloc(length); + + while(idata; + int buf_size = avpkt->size; + LagarithContext *lag_ctx = avctx->priv_data; + AVFrame * const p= &lag_ctx->picture; + uint8_t i_frametype = 0; + int i; + uint32_t offset_gu = 0, offset_bv = 0; + + AVFrame *picture = data; + + if(p->data[0]) + avctx->release_buffer(avctx, p); + + p->reference = 0; + p->key_frame = 1; + + i_frametype = buf[0]; + + offset_gu = *(const uint32_t*)(buf+1); + offset_bv = *(const uint32_t*)(buf+5); +//dprintf(lag_ctx->avctx, "offset_gu = %d, offset_bv = %d, buf[offset] = %d\n", offset_gu, offset_bv, *(uint32_t*)(buf+offset_gu+1)); + switch(i_frametype) { + case FRAME_RAW: + { + /* Assume RGB, this is incorrect. Lagarith doesn't specify a type for raw frames. */ + avctx->pix_fmt = PIX_FMT_RGB24; + for(i = 0; i < 3; i++) + memcpy(picture->data[i], buf +((avctx->width * avctx->height * i)+1), buf_size + ((avctx->width * avctx->height * i) - 1)); + } + break; + case FRAME_ARITH_RGB24: + avctx->pix_fmt = PIX_FMT_RGB24; + + if(avctx->get_buffer(avctx, p) < 0){ + av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); + return -1; + } + + lag_decode_arith_plane(lag_ctx, p->data[0], avctx->width, avctx->height, p->linesize[0], + buf+9, buf_size, 0); + break; + case FRAME_ARITH_YV12: + avctx->pix_fmt = PIX_FMT_YUV420P; + + if(avctx->get_buffer(avctx, p) < 0){ + av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); + return -1; + } + + lag_decode_arith_plane(p->data[0], avctx->width, avctx->height, p->linesize[0], + buf+9, buf_size, 0); + lag_decode_arith_plane(p->data[1], avctx->width/2, avctx->height/2, p->linesize[1], + buf+offset_gu, buf_size, 0); + lag_decode_arith_plane(p->data[2], avctx->width/2, avctx->height/2, p->linesize[2], + buf+offset_bv, buf_size, 0); + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unsupported Lagarith frame type: %#x\n", i_frametype); + return -1; + } + + *picture= *(AVFrame*)&lag_ctx->picture; + *data_size = sizeof(AVPicture); + + return buf_size; +} + +/** * closes decoder * @param avctx codec context * @return 0 on success or negative if fails -- 2.11.4.GIT