fix progressive jpeg:
support refinement passes remove intermediate clipping remove redundant idct Originally committed as revision 16044 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
		@@ -351,9 +351,17 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s)
 | 
			
		||||
 | 
			
		||||
    /* 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]));
 | 
			
		||||
        int bw = (width  + s->h_max*8-1) / (s->h_max*8);
 | 
			
		||||
        int bh = (height + s->v_max*8-1) / (s->v_max*8);
 | 
			
		||||
        for(i=0; i<s->nb_components; i++) {
 | 
			
		||||
            int size = bw * bh * s->h_count[i] * s->v_count[i];
 | 
			
		||||
            av_freep(&s->blocks[i]);
 | 
			
		||||
            av_freep(&s->last_nnz[i]);
 | 
			
		||||
            s->blocks[i] = av_malloc(size * sizeof(**s->blocks));
 | 
			
		||||
            s->last_nnz[i] = av_mallocz(size * sizeof(**s->last_nnz));
 | 
			
		||||
            s->block_stride[i] = bw * s->h_count[i];
 | 
			
		||||
        }
 | 
			
		||||
        memset(s->coefs_finished, 0, sizeof(s->coefs_finished));
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -432,27 +440,29 @@ 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)
 | 
			
		||||
static int decode_dc_progressive(MJpegDecodeContext *s, DCTELEM *block, int component,
 | 
			
		||||
                                 int dc_index, int16_t *quant_matrix, int Al)
 | 
			
		||||
{
 | 
			
		||||
    int code, i, j, level, val, run;
 | 
			
		||||
 | 
			
		||||
    /* DC coef */
 | 
			
		||||
    if(!ss){
 | 
			
		||||
    int val;
 | 
			
		||||
    memset(block, 0, 64*sizeof(DCTELEM));
 | 
			
		||||
    val = mjpeg_decode_dc(s, dc_index);
 | 
			
		||||
    if (val == 0xffff) {
 | 
			
		||||
        av_log(s->avctx, AV_LOG_ERROR, "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 */
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* decode block and dequantize - progressive JPEG version */
 | 
			
		||||
static int decode_block_progressive(MJpegDecodeContext *s, DCTELEM *block, uint8_t *last_nnz,
 | 
			
		||||
                                    int ac_index, int16_t *quant_matrix,
 | 
			
		||||
                                    int ss, int se, int Al, int *EOBRUN)
 | 
			
		||||
{
 | 
			
		||||
    int code, i, j, level, val, run;
 | 
			
		||||
 | 
			
		||||
    if(*EOBRUN){
 | 
			
		||||
        (*EOBRUN)--;
 | 
			
		||||
        return 0;
 | 
			
		||||
@@ -505,9 +515,100 @@ static int decode_block_progressive(MJpegDecodeContext *s, DCTELEM *block,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    CLOSE_READER(re, &s->gb)}
 | 
			
		||||
    if(i > *last_nnz)
 | 
			
		||||
        *last_nnz = i;
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define REFINE_BIT(j) {\
 | 
			
		||||
    UPDATE_CACHE(re, &s->gb);\
 | 
			
		||||
    sign = block[j]>>15;\
 | 
			
		||||
    block[j] += SHOW_UBITS(re, &s->gb, 1) * ((quant_matrix[j]^sign)-sign) << Al;\
 | 
			
		||||
    LAST_SKIP_BITS(re, &s->gb, 1);\
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define ZERO_RUN \
 | 
			
		||||
for(;;i++) {\
 | 
			
		||||
    if(i > last) {\
 | 
			
		||||
        i += run;\
 | 
			
		||||
        if(i > se) {\
 | 
			
		||||
            av_log(s->avctx, AV_LOG_ERROR, "error count: %d\n", i);\
 | 
			
		||||
            return -1;\
 | 
			
		||||
        }\
 | 
			
		||||
        break;\
 | 
			
		||||
    }\
 | 
			
		||||
    j = s->scantable.permutated[i];\
 | 
			
		||||
    if(block[j])\
 | 
			
		||||
        REFINE_BIT(j)\
 | 
			
		||||
    else if(run-- == 0)\
 | 
			
		||||
        break;\
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* decode block and dequantize - progressive JPEG refinement pass */
 | 
			
		||||
static int decode_block_refinement(MJpegDecodeContext *s, DCTELEM *block, uint8_t *last_nnz,
 | 
			
		||||
                        int ac_index, int16_t *quant_matrix,
 | 
			
		||||
                        int ss, int se, int Al, int *EOBRUN)
 | 
			
		||||
{
 | 
			
		||||
    int code, i=ss, j, sign, val, run;
 | 
			
		||||
    int last = FFMIN(se, *last_nnz);
 | 
			
		||||
 | 
			
		||||
    OPEN_READER(re, &s->gb);
 | 
			
		||||
    if(*EOBRUN)
 | 
			
		||||
        (*EOBRUN)--;
 | 
			
		||||
    else {
 | 
			
		||||
        for(;;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) {
 | 
			
		||||
                run = ((unsigned) code) >> 4;
 | 
			
		||||
                UPDATE_CACHE(re, &s->gb);
 | 
			
		||||
                val = SHOW_UBITS(re, &s->gb, 1);
 | 
			
		||||
                LAST_SKIP_BITS(re, &s->gb, 1);
 | 
			
		||||
                ZERO_RUN;
 | 
			
		||||
                j = s->scantable.permutated[i];
 | 
			
		||||
                val--;
 | 
			
		||||
                block[j] = ((quant_matrix[j]^val)-val) << Al;
 | 
			
		||||
                if(i == se) {
 | 
			
		||||
                    if(i > *last_nnz)
 | 
			
		||||
                        *last_nnz = i;
 | 
			
		||||
                    CLOSE_READER(re, &s->gb)
 | 
			
		||||
                    return 0;
 | 
			
		||||
                }
 | 
			
		||||
            }else{
 | 
			
		||||
                run = ((unsigned) code) >> 4;
 | 
			
		||||
                if(run == 0xF){
 | 
			
		||||
                    ZERO_RUN;
 | 
			
		||||
                }else{
 | 
			
		||||
                    val = run;
 | 
			
		||||
                    run = (1 << run);
 | 
			
		||||
                    if(val) {
 | 
			
		||||
                        UPDATE_CACHE(re, &s->gb);
 | 
			
		||||
                        run += SHOW_UBITS(re, &s->gb, val);
 | 
			
		||||
                        LAST_SKIP_BITS(re, &s->gb, val);
 | 
			
		||||
                    }
 | 
			
		||||
                    *EOBRUN = run - 1;
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(i > *last_nnz)
 | 
			
		||||
            *last_nnz = i;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for(;i<=last;i++) {
 | 
			
		||||
        j = s->scantable.permutated[i];
 | 
			
		||||
        if(block[j])
 | 
			
		||||
            REFINE_BIT(j)
 | 
			
		||||
    }
 | 
			
		||||
    CLOSE_READER(re, &s->gb);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
#undef REFINE_BIT
 | 
			
		||||
#undef ZERO_RUN
 | 
			
		||||
 | 
			
		||||
static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int predictor, int point_transform){
 | 
			
		||||
    int i, mb_x, mb_y;
 | 
			
		||||
@@ -660,18 +761,16 @@ static int ljpeg_decode_yuv_scan(MJpegDecodeContext *s, int predictor, int point
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int ss, int se, int Ah, int Al){
 | 
			
		||||
static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int Ah, int Al){
 | 
			
		||||
    int i, mb_x, mb_y;
 | 
			
		||||
    int EOBRUN = 0;
 | 
			
		||||
    uint8_t* data[MAX_COMPONENTS];
 | 
			
		||||
    int linesize[MAX_COMPONENTS];
 | 
			
		||||
 | 
			
		||||
    if(Ah) return 0; /* TODO decode refinement planes too */
 | 
			
		||||
 | 
			
		||||
    for(i=0; i < nb_components; i++) {
 | 
			
		||||
        int c = s->comp_index[i];
 | 
			
		||||
        data[c] = s->picture.data[c];
 | 
			
		||||
        linesize[c]=s->linesize[c];
 | 
			
		||||
        s->coefs_finished[c] |= 1;
 | 
			
		||||
        if(s->avctx->codec->id==CODEC_ID_AMV) {
 | 
			
		||||
            //picture should be flipped upside-down for this codec
 | 
			
		||||
            assert(!(s->avctx->flags & CODEC_FLAG_EMU_EDGE));
 | 
			
		||||
@@ -695,30 +794,32 @@ static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int ss, i
 | 
			
		||||
                x = 0;
 | 
			
		||||
                y = 0;
 | 
			
		||||
                for(j=0;j<n;j++) {
 | 
			
		||||
                    memset(s->block, 0, sizeof(s->block));
 | 
			
		||||
                    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) {
 | 
			
		||||
                        av_log(s->avctx, AV_LOG_ERROR, "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) {
 | 
			
		||||
                        av_log(s->avctx, AV_LOG_ERROR, "error y=%d x=%d\n", mb_y, mb_x);
 | 
			
		||||
                        return -1;
 | 
			
		||||
                    }
 | 
			
		||||
//                    av_log(s->avctx, AV_LOG_DEBUG, "mb: %d %d processed\n", mb_y, mb_x);
 | 
			
		||||
                    ptr = data[c] +
 | 
			
		||||
                        (((linesize[c] * (v * mb_y + y) * 8) +
 | 
			
		||||
                        (h * mb_x + x) * 8) >> s->avctx->lowres);
 | 
			
		||||
                    if(s->interlaced && s->bottom_field)
 | 
			
		||||
                        ptr += 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);
 | 
			
		||||
                    if(!s->progressive)
 | 
			
		||||
                    if(!s->progressive) {
 | 
			
		||||
                        memset(s->block, 0, sizeof(s->block));
 | 
			
		||||
                        if(decode_block(s, s->block, i,
 | 
			
		||||
                                     s->dc_index[i], s->ac_index[i],
 | 
			
		||||
                                     s->quant_matrixes[ s->quant_index[c] ]) < 0) {
 | 
			
		||||
                            av_log(s->avctx, AV_LOG_ERROR, "error y=%d x=%d\n", mb_y, mb_x);
 | 
			
		||||
                            return -1;
 | 
			
		||||
                        }
 | 
			
		||||
                        s->dsp.idct_put(ptr, linesize[c], s->block);
 | 
			
		||||
                    else
 | 
			
		||||
                        s->dsp.idct_add(ptr, linesize[c], s->block);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        int block_idx = s->block_stride[c] * (v * mb_y + y) + (h * mb_x + x);
 | 
			
		||||
                        DCTELEM *block = s->blocks[c][block_idx];
 | 
			
		||||
                        if(Ah)
 | 
			
		||||
                            block[0] += get_bits1(&s->gb) * s->quant_matrixes[ s->quant_index[c] ][0] << Al;
 | 
			
		||||
                        else if(decode_dc_progressive(s, block, i, s->dc_index[i], s->quant_matrixes[ s->quant_index[c] ], Al) < 0) {
 | 
			
		||||
                            av_log(s->avctx, AV_LOG_ERROR, "error y=%d x=%d\n", mb_y, mb_x);
 | 
			
		||||
                            return -1;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
//                    av_log(s->avctx, AV_LOG_DEBUG, "mb: %d %d processed\n", mb_y, mb_x);
 | 
			
		||||
//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);
 | 
			
		||||
                    if (++x == h) {
 | 
			
		||||
                        x = 0;
 | 
			
		||||
                        y++;
 | 
			
		||||
@@ -738,6 +839,49 @@ static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int ss, i
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int mjpeg_decode_scan_progressive_ac(MJpegDecodeContext *s, int ss, int se, int Ah, int Al){
 | 
			
		||||
    int mb_x, mb_y;
 | 
			
		||||
    int EOBRUN = 0;
 | 
			
		||||
    int c = s->comp_index[0];
 | 
			
		||||
    uint8_t* data = s->picture.data[c];
 | 
			
		||||
    int linesize = s->linesize[c];
 | 
			
		||||
    int last_scan = 0;
 | 
			
		||||
    int16_t *quant_matrix = s->quant_matrixes[ s->quant_index[c] ];
 | 
			
		||||
 | 
			
		||||
    if(!Al) {
 | 
			
		||||
        s->coefs_finished[c] |= (1LL<<(se+1))-(1LL<<ss);
 | 
			
		||||
        last_scan = !~s->coefs_finished[c];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(s->interlaced && s->bottom_field)
 | 
			
		||||
        data += linesize >> 1;
 | 
			
		||||
 | 
			
		||||
    for(mb_y = 0; mb_y < s->mb_height; mb_y++) {
 | 
			
		||||
        uint8_t *ptr = data + (mb_y*linesize*8 >> s->avctx->lowres);
 | 
			
		||||
        int block_idx = mb_y * s->block_stride[c];
 | 
			
		||||
        DCTELEM (*block)[64] = &s->blocks[c][block_idx];
 | 
			
		||||
        uint8_t *last_nnz = &s->last_nnz[c][block_idx];
 | 
			
		||||
        for(mb_x = 0; mb_x < s->mb_width; mb_x++, block++, last_nnz++) {
 | 
			
		||||
            int ret;
 | 
			
		||||
            if(Ah)
 | 
			
		||||
                ret = decode_block_refinement(s, *block, last_nnz, s->ac_index[0],
 | 
			
		||||
                                              quant_matrix, ss, se, Al, &EOBRUN);
 | 
			
		||||
            else
 | 
			
		||||
                ret = decode_block_progressive(s, *block, last_nnz, s->ac_index[0],
 | 
			
		||||
                                               quant_matrix, ss, se, Al, &EOBRUN);
 | 
			
		||||
            if(ret < 0) {
 | 
			
		||||
                av_log(s->avctx, AV_LOG_ERROR, "error y=%d x=%d\n", mb_y, mb_x);
 | 
			
		||||
                return -1;
 | 
			
		||||
            }
 | 
			
		||||
            if(last_scan) {
 | 
			
		||||
                s->dsp.idct_put(ptr, linesize, *block);
 | 
			
		||||
                ptr += 8 >> s->avctx->lowres;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ff_mjpeg_decode_sos(MJpegDecodeContext *s)
 | 
			
		||||
{
 | 
			
		||||
    int len, nb_components, i, h, v, predictor, point_transform;
 | 
			
		||||
@@ -849,8 +993,13 @@ int ff_mjpeg_decode_sos(MJpegDecodeContext *s)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }else{
 | 
			
		||||
        if(mjpeg_decode_scan(s, nb_components, predictor, ilv, prev_shift, point_transform) < 0)
 | 
			
		||||
        if(s->progressive && predictor) {
 | 
			
		||||
            if(mjpeg_decode_scan_progressive_ac(s, predictor, ilv, prev_shift, point_transform) < 0)
 | 
			
		||||
                return -1;
 | 
			
		||||
        } else {
 | 
			
		||||
            if(mjpeg_decode_scan(s, nb_components, prev_shift, point_transform) < 0)
 | 
			
		||||
                return -1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    emms_c();
 | 
			
		||||
    return 0;
 | 
			
		||||
@@ -1354,6 +1503,10 @@ av_cold int ff_mjpeg_decode_end(AVCodecContext *avctx)
 | 
			
		||||
        for(j=0;j<4;j++)
 | 
			
		||||
            free_vlc(&s->vlcs[i][j]);
 | 
			
		||||
    }
 | 
			
		||||
    for(i=0; i<MAX_COMPONENTS; i++) {
 | 
			
		||||
        av_freep(&s->blocks[i]);
 | 
			
		||||
        av_freep(&s->last_nnz[i]);
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -67,6 +67,7 @@ typedef struct MJpegDecodeContext {
 | 
			
		||||
    int width, height;
 | 
			
		||||
    int mb_width, mb_height;
 | 
			
		||||
    int nb_components;
 | 
			
		||||
    int block_stride[MAX_COMPONENTS];
 | 
			
		||||
    int component_id[MAX_COMPONENTS];
 | 
			
		||||
    int h_count[MAX_COMPONENTS]; /* horizontal and vertical count for each component */
 | 
			
		||||
    int v_count[MAX_COMPONENTS];
 | 
			
		||||
@@ -83,6 +84,9 @@ typedef struct MJpegDecodeContext {
 | 
			
		||||
    int linesize[MAX_COMPONENTS];                   ///< linesize << interlaced
 | 
			
		||||
    int8_t *qscale_table;
 | 
			
		||||
    DECLARE_ALIGNED_16(DCTELEM, block[64]);
 | 
			
		||||
    DCTELEM (*blocks[MAX_COMPONENTS])[64]; ///< intermediate sums (progressive mode)
 | 
			
		||||
    uint8_t *last_nnz[MAX_COMPONENTS];
 | 
			
		||||
    uint64_t coefs_finished[MAX_COMPONENTS]; ///< bitmask of which coefs have been completely decoded (progressive mode)
 | 
			
		||||
    ScanTable scantable;
 | 
			
		||||
    DSPContext dsp;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user