|
|
|
@@ -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; |
|
|
|
} |
|
|
|
|
|
|
|
static int decode_dc_progressive(MJpegDecodeContext *s, DCTELEM *block, int component, |
|
|
|
int dc_index, int16_t *quant_matrix, int Al) |
|
|
|
{ |
|
|
|
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]; |
|
|
|
s->last_dc[component] = val; |
|
|
|
block[0] = val; |
|
|
|
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_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; |
|
|
|
|
|
|
|
/* DC coef */ |
|
|
|
if(!ss){ |
|
|
|
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 */ |
|
|
|
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) |
|
|
|
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) |
|
|
|
return -1; |
|
|
|
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; |
|
|
|
} |
|
|
|
|
|
|
|
|