X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fmjpegdec.c;h=d468133a189fc7b0ab80a89b5401769f068ef48b;hb=32b3ab9b60f05c1c1e82022e9f57a21a0e3e1ec4;hp=b3ced4d5fc57171e33c98efdebb48a0d5ef686a9;hpb=4922a5b0ee9108e406b8b14356f19851702604d1;p=ffmpeg diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index b3ced4d5fc5..d468133a189 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -1,9 +1,13 @@ /* * MJPEG decoder - * Copyright (c) 2000, 2001 Fabrice Bellard. + * Copyright (c) 2000, 2001 Fabrice Bellard * Copyright (c) 2003 Alex Beregszaszi * Copyright (c) 2003-2004 Michael Niedermayer * + * Support for external huffman table, various fixes (AVID workaround), + * aspecting, new decode_frame mechanism and apple mjpeg-b support + * by Alex Beregszaszi + * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -19,14 +23,10 @@ * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Support for external huffman table, various fixes (AVID workaround), - * aspecting, new decode_frame mechanism and apple mjpeg-b support - * by Alex Beregszaszi */ /** - * @file mjpegdec.c + * @file libavcodec/mjpegdec.c * MJPEG decoder. */ @@ -35,13 +35,11 @@ #include "avcodec.h" #include "dsputil.h" -#include "bytestream.h" #include "mjpeg.h" +#include "mjpegdec.h" #include "jpeglsdec.h" -static int mjpeg_decode_dht(MJpegDecodeContext *s); - static int build_vlc(VLC *vlc, const uint8_t *bits_table, const uint8_t *val_table, int nb_codes, int use_static, int is_ac) { @@ -51,7 +49,7 @@ static int build_vlc(VLC *vlc, const uint8_t *bits_table, const uint8_t *val_tab assert(nb_codes <= 256); memset(huff_size, 0, sizeof(huff_size)); - build_huffman_codes(huff_size, huff_code, bits_table, val_table); + ff_mjpeg_build_huffman_codes(huff_size, huff_code, bits_table, val_table); if(is_ac){ memmove(huff_size+16, huff_size, sizeof(uint8_t)*nb_codes); @@ -64,7 +62,18 @@ static int build_vlc(VLC *vlc, const uint8_t *bits_table, const uint8_t *val_tab return init_vlc(vlc, 9, nb_codes, huff_size, 1, 1, huff_code, 2, 2, use_static); } -static int mjpeg_decode_init(AVCodecContext *avctx) +static void build_basic_mjpeg_vlc(MJpegDecodeContext * s) { + build_vlc(&s->vlcs[0][0], ff_mjpeg_bits_dc_luminance, + ff_mjpeg_val_dc, 12, 0, 0); + build_vlc(&s->vlcs[0][1], ff_mjpeg_bits_dc_chrominance, + ff_mjpeg_val_dc, 12, 0, 0); + build_vlc(&s->vlcs[1][0], ff_mjpeg_bits_ac_luminance, + ff_mjpeg_val_ac_luminance, 251, 0, 1); + build_vlc(&s->vlcs[1][1], ff_mjpeg_bits_ac_chrominance, + ff_mjpeg_val_ac_chrominance, 251, 0, 1); +} + +av_cold int ff_mjpeg_decode_init(AVCodecContext *avctx) { MJpegDecodeContext *s = avctx->priv_data; @@ -76,18 +85,18 @@ static int mjpeg_decode_init(AVCodecContext *avctx) s->start_code = -1; s->first_picture = 1; s->org_height = avctx->coded_height; + avctx->chroma_sample_location = AVCHROMA_LOC_CENTER; - build_vlc(&s->vlcs[0][0], bits_dc_luminance, val_dc_luminance, 12, 0, 0); - build_vlc(&s->vlcs[0][1], bits_dc_chrominance, val_dc_chrominance, 12, 0, 0); - build_vlc(&s->vlcs[1][0], bits_ac_luminance, val_ac_luminance, 251, 0, 1); - build_vlc(&s->vlcs[1][1], bits_ac_chrominance, val_ac_chrominance, 251, 0, 1); + build_basic_mjpeg_vlc(s); if (avctx->flags & CODEC_FLAG_EXTERN_HUFF) { av_log(avctx, AV_LOG_INFO, "mjpeg: using external huffman table\n"); init_get_bits(&s->gb, avctx->extradata, avctx->extradata_size*8); - mjpeg_decode_dht(s); - /* should check for error - but dunno */ + if (ff_mjpeg_decode_dht(s)) { + av_log(avctx, AV_LOG_ERROR, "mjpeg: error using external huffman table, switching back to internal\n"); + build_basic_mjpeg_vlc(s); + } } if (avctx->extradata_size > 9 && AV_RL32(avctx->extradata + 4) == MKTAG('f','i','e','l')) { @@ -102,7 +111,7 @@ static int mjpeg_decode_init(AVCodecContext *avctx) /* quantize tables */ -static int mjpeg_decode_dqt(MJpegDecodeContext *s) +int ff_mjpeg_decode_dqt(MJpegDecodeContext *s) { int len, index, i, j; @@ -137,7 +146,7 @@ static int mjpeg_decode_dqt(MJpegDecodeContext *s) } /* decode huffman tables and build VLC decoders */ -static int mjpeg_decode_dht(MJpegDecodeContext *s) +int ff_mjpeg_decode_dht(MJpegDecodeContext *s) { int len, index, i, class, n, v, code_max; uint8_t bits_table[17]; @@ -183,7 +192,7 @@ static int mjpeg_decode_dht(MJpegDecodeContext *s) return 0; } -static int mjpeg_decode_sof(MJpegDecodeContext *s) +int ff_mjpeg_decode_sof(MJpegDecodeContext *s) { int len, nb_components, i, width, height, pix_fmt_id; @@ -276,28 +285,39 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s) return 0; /* XXX: not complete test ! */ - pix_fmt_id = (s->h_count[0] << 20) | (s->v_count[0] << 16) | - (s->h_count[1] << 12) | (s->v_count[1] << 8) | - (s->h_count[2] << 4) | s->v_count[2]; + pix_fmt_id = (s->h_count[0] << 28) | (s->v_count[0] << 24) | + (s->h_count[1] << 20) | (s->v_count[1] << 16) | + (s->h_count[2] << 12) | (s->v_count[2] << 8) | + (s->h_count[3] << 4) | s->v_count[3]; av_log(s->avctx, AV_LOG_DEBUG, "pix fmt id %x\n", pix_fmt_id); + if(!(pix_fmt_id & 0x10101010)) + pix_fmt_id-= (pix_fmt_id & 0xF0F0F0F0)>>1; + if(!(pix_fmt_id & 0x01010101)) + pix_fmt_id-= (pix_fmt_id & 0x0F0F0F0F)>>1; + switch(pix_fmt_id){ - case 0x222222: - case 0x111111: + case 0x11111100: if(s->rgb){ s->avctx->pix_fmt = PIX_FMT_RGB32; - }else if(s->nb_components==3) + }else s->avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV444P : PIX_FMT_YUVJ444P; - else - s->avctx->pix_fmt = PIX_FMT_GRAY8; + assert(s->nb_components==3); + break; + case 0x11000000: + s->avctx->pix_fmt = PIX_FMT_GRAY8; + break; + case 0x12111100: + s->avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV440P : PIX_FMT_YUVJ440P; break; - case 0x211111: - case 0x221212: + case 0x21111100: s->avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV422P : PIX_FMT_YUVJ422P; break; - default: - case 0x221111: + case 0x22111100: s->avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV420P : PIX_FMT_YUVJ420P; break; + default: + av_log(s->avctx, AV_LOG_ERROR, "Unhandled pixel format 0x%x\n", pix_fmt_id); + return -1; } if(s->ls){ if(s->nb_components > 1) @@ -316,7 +336,7 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s) av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return -1; } - s->picture.pict_type= I_TYPE; + s->picture.pict_type= FF_I_TYPE; s->picture.key_frame= 1; for(i=0; i<3; i++){ @@ -332,9 +352,17 @@ static int 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; inb_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; } @@ -413,27 +441,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; + s->dsp.clear_block(block); + 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; @@ -486,9 +516,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; @@ -641,11 +762,24 @@ 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]; + + 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)); + data[c] += (linesize[c] * (s->v_scount[i] * (8 * s->mb_height -((s->height/s->v_max)&7)) - 1 )); + linesize[c] *= -1; + } + } - 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) @@ -661,39 +795,40 @@ static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int ss, i x = 0; y = 0; for(j=0;jblock, 0, sizeof(s->block)); - if (!s->progressive && decode_block(s, s->block, i, + 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; + if(!s->progressive) { + s->dsp.clear_block(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; - } - 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_ERROR, "error y=%d x=%d\n", mb_y, mb_x); + return -1; + } + s->dsp.idct_put(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); - ptr = s->picture.data[c] + - (((s->linesize[c] * (v * mb_y + y) * 8) + - (h * mb_x + x) * 8) >> s->avctx->lowres); - 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); - if(!s->progressive) - s->dsp.idct_put(ptr, s->linesize[c], s->block); - else - s->dsp.idct_add(ptr, s->linesize[c], s->block); if (++x == h) { x = 0; y++; } } } - /* (< 1350) buggy workaround for Spectralfan.mov, should be fixed */ - if (s->restart_interval && (s->restart_interval < 1350) && - !--s->restart_count) { + + if (s->restart_interval && !--s->restart_count) { align_get_bits(&s->gb); skip_bits(&s->gb, 16); /* skip RSTn */ for (i=0; icomp_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<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; - int vmax, hmax, index, id; + int index, id; const int block_size= s->lossless ? 1 : 8; int ilv, prev_shift; @@ -719,8 +897,6 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s) av_log(s->avctx, AV_LOG_ERROR, "decode_sos: invalid len (%d)\n", len); return -1; } - vmax = 0; - hmax = 0; for(i=0;igb, 8) - 1; av_log(s->avctx, AV_LOG_DEBUG, "component: %d\n", id); @@ -799,11 +975,12 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s) skip_bits(&s->gb, 8); if(s->lossless){ - if(s->ls){ + if(CONFIG_JPEGLS_DECODER && s->ls){ // for(){ // reset_ls_coding_parameters(s, 0); - ff_jpegls_decode_picture(s, predictor, point_transform, ilv); + if(ff_jpegls_decode_picture(s, predictor, point_transform, ilv) < 0) + return -1; }else{ if(s->rgb){ if(ljpeg_decode_rgb_scan(s, predictor, point_transform) < 0) @@ -814,8 +991,13 @@ static int 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; @@ -856,7 +1038,7 @@ static int mjpeg_decode_app(MJpegDecodeContext *s) /* buggy AVID, it puts EOI only at every 10th frame */ /* also this fourcc is used by non-avid files too, it holds some informations, but it's always present in AVID creates files */ - if (id == ff_get_fourcc("AVI1")) + if (id == AV_RL32("AVI1")) { /* structure: 4bytes AVI1 @@ -884,7 +1066,7 @@ static int mjpeg_decode_app(MJpegDecodeContext *s) // len -= 2; - if (id == ff_get_fourcc("JFIF")) + if (id == AV_RL32("JFIF")) { int t_w, t_h, v1, v2; skip_bits(&s->gb, 8); /* the trailing zero-byte */ @@ -914,7 +1096,7 @@ static int mjpeg_decode_app(MJpegDecodeContext *s) goto out; } - if (id == ff_get_fourcc("Adob") && (get_bits(&s->gb, 8) == 'e')) + if (id == AV_RL32("Adob") && (get_bits(&s->gb, 8) == 'e')) { if (s->avctx->debug & FF_DEBUG_PICT_INFO) av_log(s->avctx, AV_LOG_INFO, "mjpeg: Adobe header found\n"); @@ -926,7 +1108,7 @@ static int mjpeg_decode_app(MJpegDecodeContext *s) goto out; } - if (id == ff_get_fourcc("LJIF")){ + if (id == AV_RL32("LJIF")){ if (s->avctx->debug & FF_DEBUG_PICT_INFO) av_log(s->avctx, AV_LOG_INFO, "Pegasus lossless jpeg header found\n"); skip_bits(&s->gb, 16); /* version ? */ @@ -955,7 +1137,7 @@ static int mjpeg_decode_app(MJpegDecodeContext *s) id = (get_bits(&s->gb, 16) << 16) | get_bits(&s->gb, 16); id = be2me_32(id); len -= 4; - if (id == ff_get_fourcc("mjpg")) /* Apple MJPEG-A */ + if (id == AV_RL32("mjpg")) /* Apple MJPEG-A */ { #if 0 skip_bits(&s->gb, 32); /* field size */ @@ -1042,9 +1224,9 @@ static int valid_marker_list[] = /* return the 8 bit start code value and update the search state. Return -1 if no start code found */ -static int find_marker(uint8_t **pbuf_ptr, uint8_t *buf_end) +static int find_marker(const uint8_t **pbuf_ptr, const uint8_t *buf_end) { - uint8_t *buf_ptr; + const uint8_t *buf_ptr; unsigned int v, v2; int val; #ifdef DEBUG @@ -1072,12 +1254,14 @@ found: return val; } -static int mjpeg_decode_frame(AVCodecContext *avctx, +int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *data_size, - uint8_t *buf, int buf_size) + AVPacket *avpkt) { + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; MJpegDecodeContext *s = avctx->priv_data; - uint8_t *buf_end, *buf_ptr; + const uint8_t *buf_end, *buf_ptr; int start_code; AVFrame *picture = data; @@ -1091,7 +1275,7 @@ static int mjpeg_decode_frame(AVCodecContext *avctx, if (start_code < 0) { goto the_end; } else { - av_log(avctx, AV_LOG_DEBUG, "marker=%x avail_size_in_buf=%d\n", start_code, buf_end - buf_ptr); + av_log(avctx, AV_LOG_DEBUG, "marker=%x avail_size_in_buf=%td\n", start_code, buf_end - buf_ptr); if ((buf_end - buf_ptr) > s->buffer_size) { @@ -1105,7 +1289,7 @@ static int mjpeg_decode_frame(AVCodecContext *avctx, /* unescape buffer of SOS, use special treatment for JPEG-LS */ if (start_code == SOS && !s->ls) { - uint8_t *src = buf_ptr; + const uint8_t *src = buf_ptr; uint8_t *dst = s->buffer; while (srcgb, s->buffer, (dst - s->buffer)*8); - av_log(avctx, AV_LOG_DEBUG, "escaping removed %d bytes\n", + av_log(avctx, AV_LOG_DEBUG, "escaping removed %td bytes\n", (buf_end - buf_ptr) - (dst - s->buffer)); } else if(start_code == SOS && s->ls){ - uint8_t *src = buf_ptr; + const uint8_t *src = buf_ptr; uint8_t *dst = s->buffer; int bit_count = 0; int t = 0, b = 0; @@ -1197,10 +1381,10 @@ static int mjpeg_decode_frame(AVCodecContext *avctx, /* nothing to do on SOI */ break; case DQT: - mjpeg_decode_dqt(s); + ff_mjpeg_decode_dqt(s); break; case DHT: - if(mjpeg_decode_dht(s) < 0){ + if(ff_mjpeg_decode_dht(s) < 0){ av_log(avctx, AV_LOG_ERROR, "huffman table decode error\n"); return -1; } @@ -1209,32 +1393,32 @@ static int mjpeg_decode_frame(AVCodecContext *avctx, s->lossless=0; s->ls=0; s->progressive=0; - if (mjpeg_decode_sof(s) < 0) + if (ff_mjpeg_decode_sof(s) < 0) return -1; break; case SOF2: s->lossless=0; s->ls=0; s->progressive=1; - if (mjpeg_decode_sof(s) < 0) + if (ff_mjpeg_decode_sof(s) < 0) return -1; break; case SOF3: s->lossless=1; s->ls=0; s->progressive=0; - if (mjpeg_decode_sof(s) < 0) + if (ff_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) + if (ff_mjpeg_decode_sof(s) < 0) return -1; break; case LSE: - if (ff_jpegls_decode_lse(s) < 0) + if (!CONFIG_JPEGLS_DECODER || ff_jpegls_decode_lse(s) < 0) return -1; break; case EOI: @@ -1253,7 +1437,7 @@ eoi_parser: *data_size = sizeof(AVFrame); if(!s->lossless){ - picture->quality= FFMAX(FFMAX(s->qscale[0], s->qscale[1]), s->qscale[2]); + picture->quality= FFMAX3(s->qscale[0], s->qscale[1], s->qscale[2]); picture->qstride= 0; picture->qscale_table= s->qscale_table; memset(picture->qscale_table, picture->quality, (s->width+15)/16); @@ -1266,7 +1450,7 @@ eoi_parser: } break; case SOS: - mjpeg_decode_sos(s); + ff_mjpeg_decode_sos(s); /* buggy avid puts EOI every 10-20th frame */ /* if restart period is over process EOI */ if ((s->buggy_avid && !s->interlaced) || s->restart_interval) @@ -1302,274 +1486,12 @@ not_the_end: } } the_end: - av_log(avctx, AV_LOG_DEBUG, "mjpeg decode frame unused %d bytes\n", buf_end - buf_ptr); + av_log(avctx, AV_LOG_DEBUG, "mjpeg decode frame unused %td bytes\n", buf_end - buf_ptr); // return buf_end - buf_ptr; return buf_ptr - buf; } -static int mjpegb_decode_frame(AVCodecContext *avctx, - void *data, int *data_size, - uint8_t *buf, int buf_size) -{ - MJpegDecodeContext *s = avctx->priv_data; - uint8_t *buf_end, *buf_ptr; - AVFrame *picture = data; - GetBitContext hgb; /* for the header */ - uint32_t dqt_offs, dht_offs, sof_offs, sos_offs, second_field_offs; - uint32_t field_size, sod_offs; - - buf_ptr = buf; - buf_end = buf + buf_size; - -read_header: - /* reset on every SOI */ - s->restart_interval = 0; - s->restart_count = 0; - s->mjpb_skiptosod = 0; - - init_get_bits(&hgb, buf_ptr, /*buf_size*/(buf_end - buf_ptr)*8); - - skip_bits(&hgb, 32); /* reserved zeros */ - - if (get_bits_long(&hgb, 32) != MKBETAG('m','j','p','g')) - { - av_log(avctx, AV_LOG_WARNING, "not mjpeg-b (bad fourcc)\n"); - return 0; - } - - field_size = get_bits_long(&hgb, 32); /* field size */ - av_log(avctx, AV_LOG_DEBUG, "field size: 0x%x\n", field_size); - skip_bits(&hgb, 32); /* padded field size */ - second_field_offs = get_bits_long(&hgb, 32); - av_log(avctx, AV_LOG_DEBUG, "second field offs: 0x%x\n", second_field_offs); - - dqt_offs = get_bits_long(&hgb, 32); - av_log(avctx, AV_LOG_DEBUG, "dqt offs: 0x%x\n", dqt_offs); - if (dqt_offs) - { - init_get_bits(&s->gb, buf+dqt_offs, (buf_end - (buf+dqt_offs))*8); - s->start_code = DQT; - mjpeg_decode_dqt(s); - } - - dht_offs = get_bits_long(&hgb, 32); - av_log(avctx, AV_LOG_DEBUG, "dht offs: 0x%x\n", dht_offs); - if (dht_offs) - { - init_get_bits(&s->gb, buf+dht_offs, (buf_end - (buf+dht_offs))*8); - s->start_code = DHT; - mjpeg_decode_dht(s); - } - - sof_offs = get_bits_long(&hgb, 32); - av_log(avctx, AV_LOG_DEBUG, "sof offs: 0x%x\n", sof_offs); - if (sof_offs) - { - init_get_bits(&s->gb, buf+sof_offs, (buf_end - (buf+sof_offs))*8); - s->start_code = SOF0; - if (mjpeg_decode_sof(s) < 0) - return -1; - } - - sos_offs = get_bits_long(&hgb, 32); - av_log(avctx, AV_LOG_DEBUG, "sos offs: 0x%x\n", sos_offs); - sod_offs = get_bits_long(&hgb, 32); - av_log(avctx, AV_LOG_DEBUG, "sod offs: 0x%x\n", sod_offs); - if (sos_offs) - { -// init_get_bits(&s->gb, buf+sos_offs, (buf_end - (buf+sos_offs))*8); - init_get_bits(&s->gb, buf+sos_offs, field_size*8); - s->mjpb_skiptosod = (sod_offs - sos_offs - show_bits(&s->gb, 16)); - s->start_code = SOS; - mjpeg_decode_sos(s); - } - - if (s->interlaced) { - s->bottom_field ^= 1; - /* if not bottom field, do not output image yet */ - if (s->bottom_field && second_field_offs) - { - buf_ptr = buf + second_field_offs; - second_field_offs = 0; - goto read_header; - } - } - - //XXX FIXME factorize, this looks very similar to the EOI code - - *picture= s->picture; - *data_size = sizeof(AVFrame); - - if(!s->lossless){ - picture->quality= FFMAX(FFMAX(s->qscale[0], s->qscale[1]), s->qscale[2]); - picture->qstride= 0; - picture->qscale_table= s->qscale_table; - memset(picture->qscale_table, picture->quality, (s->width+15)/16); - if(avctx->debug & FF_DEBUG_QP) - av_log(avctx, AV_LOG_DEBUG, "QP: %d\n", picture->quality); - picture->quality*= FF_QP2LAMBDA; - } - - return buf_ptr - buf; -} - -#include "sp5x.h" - -static int sp5x_decode_frame(AVCodecContext *avctx, - void *data, int *data_size, - uint8_t *buf, int buf_size) -{ -#if 0 - MJpegDecodeContext *s = avctx->priv_data; -#endif - const int qscale = 5; - uint8_t *buf_ptr, *buf_end, *recoded; - int i = 0, j = 0; - - if (!avctx->width || !avctx->height) - return -1; - - buf_ptr = buf; - buf_end = buf + buf_size; - -#if 1 - recoded = av_mallocz(buf_size + 1024); - if (!recoded) - return -1; - - /* SOI */ - recoded[j++] = 0xFF; - recoded[j++] = 0xD8; - - memcpy(recoded+j, &sp5x_data_dqt[0], sizeof(sp5x_data_dqt)); - memcpy(recoded+j+5, &sp5x_quant_table[qscale * 2], 64); - memcpy(recoded+j+70, &sp5x_quant_table[(qscale * 2) + 1], 64); - j += sizeof(sp5x_data_dqt); - - memcpy(recoded+j, &sp5x_data_dht[0], sizeof(sp5x_data_dht)); - j += sizeof(sp5x_data_dht); - - memcpy(recoded+j, &sp5x_data_sof[0], sizeof(sp5x_data_sof)); - recoded[j+5] = (avctx->coded_height >> 8) & 0xFF; - recoded[j+6] = avctx->coded_height & 0xFF; - recoded[j+7] = (avctx->coded_width >> 8) & 0xFF; - recoded[j+8] = avctx->coded_width & 0xFF; - j += sizeof(sp5x_data_sof); - - memcpy(recoded+j, &sp5x_data_sos[0], sizeof(sp5x_data_sos)); - j += sizeof(sp5x_data_sos); - - for (i = 14; i < buf_size && j < buf_size+1024-2; i++) - { - recoded[j++] = buf[i]; - if (buf[i] == 0xff) - recoded[j++] = 0; - } - - /* EOI */ - recoded[j++] = 0xFF; - recoded[j++] = 0xD9; - - i = mjpeg_decode_frame(avctx, data, data_size, recoded, j); - - av_free(recoded); - -#else - /* SOF */ - s->bits = 8; - s->width = avctx->coded_width; - s->height = avctx->coded_height; - s->nb_components = 3; - s->component_id[0] = 0; - s->h_count[0] = 2; - s->v_count[0] = 2; - s->quant_index[0] = 0; - s->component_id[1] = 1; - s->h_count[1] = 1; - s->v_count[1] = 1; - s->quant_index[1] = 1; - s->component_id[2] = 2; - s->h_count[2] = 1; - s->v_count[2] = 1; - s->quant_index[2] = 1; - s->h_max = 2; - s->v_max = 2; - - s->qscale_table = av_mallocz((s->width+15)/16); - avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV420P : PIX_FMT_YUVJ420; - s->interlaced = 0; - - s->picture.reference = 0; - if (avctx->get_buffer(avctx, &s->picture) < 0) - { - av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); - return -1; - } - - s->picture.pict_type = I_TYPE; - s->picture.key_frame = 1; - - for (i = 0; i < 3; i++) - s->linesize[i] = s->picture.linesize[i] << s->interlaced; - - /* DQT */ - for (i = 0; i < 64; i++) - { - j = s->scantable.permutated[i]; - s->quant_matrixes[0][j] = sp5x_quant_table[(qscale * 2) + i]; - } - s->qscale[0] = FFMAX( - s->quant_matrixes[0][s->scantable.permutated[1]], - s->quant_matrixes[0][s->scantable.permutated[8]]) >> 1; - - for (i = 0; i < 64; i++) - { - j = s->scantable.permutated[i]; - s->quant_matrixes[1][j] = sp5x_quant_table[(qscale * 2) + 1 + i]; - } - s->qscale[1] = FFMAX( - s->quant_matrixes[1][s->scantable.permutated[1]], - s->quant_matrixes[1][s->scantable.permutated[8]]) >> 1; - - /* DHT */ - - /* SOS */ - s->comp_index[0] = 0; - s->nb_blocks[0] = s->h_count[0] * s->v_count[0]; - s->h_scount[0] = s->h_count[0]; - s->v_scount[0] = s->v_count[0]; - s->dc_index[0] = 0; - s->ac_index[0] = 0; - - s->comp_index[1] = 1; - s->nb_blocks[1] = s->h_count[1] * s->v_count[1]; - s->h_scount[1] = s->h_count[1]; - s->v_scount[1] = s->v_count[1]; - s->dc_index[1] = 1; - s->ac_index[1] = 1; - - s->comp_index[2] = 2; - s->nb_blocks[2] = s->h_count[2] * s->v_count[2]; - s->h_scount[2] = s->h_count[2]; - s->v_scount[2] = s->v_count[2]; - s->dc_index[2] = 1; - s->ac_index[2] = 1; - - for (i = 0; i < 3; i++) - s->last_dc[i] = 1024; - - s->mb_width = (s->width * s->h_max * 8 -1) / (s->h_max * 8); - s->mb_height = (s->height * s->v_max * 8 -1) / (s->v_max * 8); - - init_get_bits(&s->gb, buf+14, (buf_size-14)*8); - - return mjpeg_decode_scan(s); -#endif - - return i; -} - -static int mjpeg_decode_end(AVCodecContext *avctx) +av_cold int ff_mjpeg_decode_end(AVCodecContext *avctx) { MJpegDecodeContext *s = avctx->priv_data; int i, j; @@ -1581,61 +1503,10 @@ static int mjpeg_decode_end(AVCodecContext *avctx) for(j=0;j<4;j++) free_vlc(&s->vlcs[i][j]); } - return 0; -} - -static int mjpega_dump_header(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args, - uint8_t **poutbuf, int *poutbuf_size, - const uint8_t *buf, int buf_size, int keyframe) -{ - uint8_t *poutbufp; - int i; - - if (avctx->codec_id != CODEC_ID_MJPEG) { - av_log(avctx, AV_LOG_ERROR, "mjpega bitstream filter only applies to mjpeg codec\n"); - return 0; + for(i=0; iblocks[i]); + av_freep(&s->last_nnz[i]); } - - *poutbuf_size = 0; - *poutbuf = av_malloc(buf_size + 44 + FF_INPUT_BUFFER_PADDING_SIZE); - poutbufp = *poutbuf; - bytestream_put_byte(&poutbufp, 0xff); - bytestream_put_byte(&poutbufp, SOI); - bytestream_put_byte(&poutbufp, 0xff); - bytestream_put_byte(&poutbufp, APP1); - bytestream_put_be16(&poutbufp, 42); /* size */ - bytestream_put_be32(&poutbufp, 0); - bytestream_put_buffer(&poutbufp, "mjpg", 4); - bytestream_put_be32(&poutbufp, buf_size + 44); /* field size */ - bytestream_put_be32(&poutbufp, buf_size + 44); /* pad field size */ - bytestream_put_be32(&poutbufp, 0); /* next ptr */ - - for (i = 0; i < buf_size - 1; i++) { - if (buf[i] == 0xff) { - switch (buf[i + 1]) { - case DQT: /* quant off */ - case DHT: /* huff off */ - case SOF0: /* image off */ - bytestream_put_be32(&poutbufp, i + 46); - break; - case SOS: - bytestream_put_be32(&poutbufp, i + 46); /* scan off */ - bytestream_put_be32(&poutbufp, i + 46 + AV_RB16(buf + i + 2)); /* data off */ - bytestream_put_buffer(&poutbufp, buf + 2, buf_size - 2); /* skip already written SOI */ - *poutbuf_size = poutbufp - *poutbuf; - return 1; - case APP1: - if (i + 8 < buf_size && AV_RL32(buf + i + 8) == ff_get_fourcc("mjpg")) { - av_log(avctx, AV_LOG_ERROR, "bitstream already formatted\n"); - memcpy(*poutbuf, buf, buf_size); - *poutbuf_size = buf_size; - return 1; - } - } - } - } - av_freep(poutbuf); - av_log(avctx, AV_LOG_ERROR, "could not find SOS marker in bitstream\n"); return 0; } @@ -1644,12 +1515,13 @@ AVCodec mjpeg_decoder = { CODEC_TYPE_VIDEO, CODEC_ID_MJPEG, sizeof(MJpegDecodeContext), - mjpeg_decode_init, + ff_mjpeg_decode_init, NULL, - mjpeg_decode_end, - mjpeg_decode_frame, + ff_mjpeg_decode_end, + ff_mjpeg_decode_frame, CODEC_CAP_DR1, - NULL + NULL, + .long_name = NULL_IF_CONFIG_SMALL("MJPEG (Motion JPEG)"), }; AVCodec thp_decoder = { @@ -1657,44 +1529,11 @@ AVCodec thp_decoder = { CODEC_TYPE_VIDEO, CODEC_ID_THP, sizeof(MJpegDecodeContext), - mjpeg_decode_init, + ff_mjpeg_decode_init, NULL, - mjpeg_decode_end, - mjpeg_decode_frame, + ff_mjpeg_decode_end, + ff_mjpeg_decode_frame, CODEC_CAP_DR1, - NULL -}; - -AVCodec mjpegb_decoder = { - "mjpegb", - CODEC_TYPE_VIDEO, - CODEC_ID_MJPEGB, - sizeof(MJpegDecodeContext), - mjpeg_decode_init, - NULL, - mjpeg_decode_end, - mjpegb_decode_frame, - CODEC_CAP_DR1, - NULL -}; - -AVCodec sp5x_decoder = { - "sp5x", - CODEC_TYPE_VIDEO, - CODEC_ID_SP5X, - sizeof(MJpegDecodeContext), - mjpeg_decode_init, NULL, - mjpeg_decode_end, - sp5x_decode_frame, - CODEC_CAP_DR1, - NULL + .long_name = NULL_IF_CONFIG_SMALL("Nintendo Gamecube THP video"), }; - -#ifdef CONFIG_MJPEGA_DUMP_HEADER_BSF -AVBitStreamFilter mjpega_dump_header_bsf = { - "mjpegadump", - 0, - mjpega_dump_header, -}; -#endif