diff options
author | Kostya Shishkov <kostya.shishkov@gmail.com> | 2006-11-20 08:21:17 +0300 |
---|---|---|
committer | Kostya Shishkov <kostya.shishkov@gmail.com> | 2006-11-20 08:21:17 +0300 |
commit | 6ffdc53de9e51c4c8f48cf3f5fa7256f5cc5707b (patch) | |
tree | da62124b0d42d6d5396f89a178350917ff2de5fa /libavcodec/mjpeg.c | |
parent | 9a313fe04076f5b04d1c64543b6873af70e8713c (diff) |
Some progressive JPEG support
Originally committed as revision 7131 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/mjpeg.c')
-rw-r--r-- | libavcodec/mjpeg.c | 122 |
1 files changed, 113 insertions, 9 deletions
diff --git a/libavcodec/mjpeg.c b/libavcodec/mjpeg.c index 7e919eb1f1..b090f17f5f 100644 --- a/libavcodec/mjpeg.c +++ b/libavcodec/mjpeg.c @@ -854,6 +854,7 @@ typedef struct MJpegDecodeContext { int bottom_field; /* true if bottom field */ int lossless; int ls; + int progressive; int rgb; int rct; /* standard rct */ int pegasus_rct; /* pegasus reversible colorspace transform */ @@ -885,6 +886,7 @@ typedef struct MJpegDecodeContext { DECLARE_ALIGNED_8(DCTELEM, block[64]); ScanTable scantable; void (*idct_put)(uint8_t *dest/*align 8*/, int line_size, DCTELEM *block/*align 16*/); + void (*idct_add)(uint8_t *dest/*align 8*/, int line_size, DCTELEM *block/*align 16*/); int restart_interval; int restart_count; @@ -941,6 +943,7 @@ static int mjpeg_decode_init(AVCodecContext *avctx) s->scantable= s2.intra_scantable; s->idct_put= s2.dsp.idct_put; + s->idct_add= s2.dsp.idct_add; s->mpeg_enc_ctx_allocated = 0; s->buffer_size = 0; @@ -1251,6 +1254,12 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s) dprintf("decode_sof0: error, len(%d) mismatch\n", len); } + /* totally blank picture as progressive JPEG will only add details to it */ + if(s->progressive){ + memset(s->picture.data[0], 0, s->picture.linesize[0] * s->height); + memset(s->picture.data[1], 0, s->picture.linesize[1] * s->height >> (s->v_max - s->v_count[1])); + memset(s->picture.data[2], 0, s->picture.linesize[2] * s->height >> (s->v_max - s->v_count[2])); + } return 0; } @@ -1328,6 +1337,83 @@ static int decode_block(MJpegDecodeContext *s, DCTELEM *block, return 0; } +/* decode block and dequantize - progressive JPEG version */ +static int decode_block_progressive(MJpegDecodeContext *s, DCTELEM *block, + int component, int dc_index, int ac_index, int16_t *quant_matrix, + int ss, int se, int Ah, int Al, int *EOBRUN) +{ + int code, i, j, level, val, run; + + /* DC coef */ + if(!ss){ + val = mjpeg_decode_dc(s, dc_index); + if (val == 0xffff) { + dprintf("error dc\n"); + return -1; + } + val = (val * quant_matrix[0] << Al) + s->last_dc[component]; + }else + val = 0; + s->last_dc[component] = val; + block[0] = val; + if(!se) return 0; + /* AC coefs */ + if(*EOBRUN){ + (*EOBRUN)--; + return 0; + } + {OPEN_READER(re, &s->gb) + for(i=ss;;i++) { + UPDATE_CACHE(re, &s->gb); + GET_VLC(code, re, &s->gb, s->vlcs[1][ac_index].table, 9, 2) + /* Progressive JPEG use AC coeffs from zero and this decoder sets offset 16 by default */ + code -= 16; + if(code & 0xF) { + i += ((unsigned) code) >> 4; + code &= 0xf; + if(code > MIN_CACHE_BITS - 16){ + UPDATE_CACHE(re, &s->gb) + } + { + int cache=GET_CACHE(re,&s->gb); + int sign=(~cache)>>31; + level = (NEG_USR32(sign ^ cache,code) ^ sign) - sign; + } + + LAST_SKIP_BITS(re, &s->gb, code) + + if (i >= se) { + if(i == se){ + j = s->scantable.permutated[se]; + block[j] = level * quant_matrix[j] << Al; + break; + } + dprintf("error count: %d\n", i); + return -1; + } + j = s->scantable.permutated[i]; + block[j] = level * quant_matrix[j] << Al; + }else{ + run = ((unsigned) code) >> 4; + if(run == 0xF){// ZRL - skip 15 coefficients + i += 15; + }else{ + val = run; + run = (1 << run); + UPDATE_CACHE(re, &s->gb); + run += (GET_CACHE(re, &s->gb) >> (32 - val)) & (run - 1); + if(val) + LAST_SKIP_BITS(re, &s->gb, val); + *EOBRUN = run - 1; + break; + } + } + } + CLOSE_READER(re, &s->gb)} + + return 0; +} + static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int predictor, int point_transform){ int i, mb_x, mb_y; uint16_t buffer[32768][4]; @@ -1479,10 +1565,11 @@ static int ljpeg_decode_yuv_scan(MJpegDecodeContext *s, int predictor, int point return 0; } -static int mjpeg_decode_scan(MJpegDecodeContext *s){ +static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int ss, int se, int Ah, int Al){ int i, mb_x, mb_y; - const int nb_components=3; + int EOBRUN = 0; + if(Ah) return 0; /* TODO decode refinement planes too */ for(mb_y = 0; mb_y < s->mb_height; mb_y++) { for(mb_x = 0; mb_x < s->mb_width; mb_x++) { if (s->restart_interval && !s->restart_count) @@ -1499,12 +1586,18 @@ static int mjpeg_decode_scan(MJpegDecodeContext *s){ y = 0; for(j=0;j<n;j++) { memset(s->block, 0, sizeof(s->block)); - if (decode_block(s, s->block, i, + if (!s->progressive && decode_block(s, s->block, i, s->dc_index[i], s->ac_index[i], s->quant_matrixes[ s->quant_index[c] ]) < 0) { dprintf("error y=%d x=%d\n", mb_y, mb_x); return -1; } + if (s->progressive && decode_block_progressive(s, s->block, i, + s->dc_index[i], s->ac_index[i], + s->quant_matrixes[ s->quant_index[c] ], ss, se, Ah, Al, &EOBRUN) < 0) { + dprintf("error y=%d x=%d\n", mb_y, mb_x); + return -1; + } // dprintf("mb: %d %d processed\n", mb_y, mb_x); ptr = s->picture.data[c] + (((s->linesize[c] * (v * mb_y + y) * 8) + @@ -1512,7 +1605,10 @@ static int mjpeg_decode_scan(MJpegDecodeContext *s){ if (s->interlaced && s->bottom_field) ptr += s->linesize[c] >> 1; //av_log(NULL, AV_LOG_DEBUG, "%d %d %d %d %d %d %d %d \n", mb_x, mb_y, x, y, c, s->bottom_field, (v * mb_y + y) * 8, (h * mb_x + x) * 8); - s->idct_put(ptr, s->linesize[c], s->block); + if(!s->progressive) + s->idct_put(ptr, s->linesize[c], s->block); + else + s->idct_add(ptr, s->linesize[c], s->block); if (++x == h) { x = 0; y++; @@ -1537,7 +1633,7 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s) int len, nb_components, i, h, v, predictor, point_transform; int vmax, hmax, index, id; const int block_size= s->lossless ? 1 : 8; - int ilv; + int ilv, prev_shift; /* XXX: verify len field validity */ len = get_bits(&s->gb, 16); @@ -1548,7 +1644,7 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s) return -1; } /* XXX: only interleaved scan accepted */ - if ((nb_components != s->nb_components) && !s->ls) + if ((nb_components != s->nb_components) && !s->ls && !s->progressive) { dprintf("decode_sos: components(%d) mismatch\n", nb_components); return -1; @@ -1602,7 +1698,7 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s) predictor= get_bits(&s->gb, 8); /* JPEG Ss / lossless JPEG predictor /JPEG-LS NEAR */ ilv= get_bits(&s->gb, 8); /* JPEG Se / JPEG-LS ILV */ - skip_bits(&s->gb, 4); /* Ah */ + prev_shift = get_bits(&s->gb, 4); /* Ah */ point_transform= get_bits(&s->gb, 4); /* Al */ for(i=0;i<nb_components;i++) @@ -1648,7 +1744,7 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s) } } }else{ - if(mjpeg_decode_scan(s) < 0) + if(mjpeg_decode_scan(s, nb_components, predictor, ilv, prev_shift, point_transform) < 0) return -1; } emms_c(); @@ -2037,17 +2133,26 @@ static int mjpeg_decode_frame(AVCodecContext *avctx, break; case SOF0: s->lossless=0; + s->progressive=0; + if (mjpeg_decode_sof(s) < 0) + return -1; + break; + case SOF2: + s->lossless=0; + s->progressive=1; if (mjpeg_decode_sof(s) < 0) return -1; break; case SOF3: s->lossless=1; + s->progressive=0; if (mjpeg_decode_sof(s) < 0) return -1; break; case SOF48: s->lossless=1; s->ls=1; + s->progressive=0; if (mjpeg_decode_sof(s) < 0) return -1; break; @@ -2094,7 +2199,6 @@ eoi_parser: mjpeg_decode_dri(s); break; case SOF1: - case SOF2: case SOF5: case SOF6: case SOF7: |