X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fmjpegdec.c;h=0a1236c225dde2c23998c1106a75be7fdde94821;hb=8d61eef917f736ebd4bc23c36d1b0cb3934e7dd6;hp=91549dc5bac3e97e7e5284f565c6994edb819d39;hpb=5acd8d9e773d0b7dff256e8ed1128b96a6a77a6d;p=ffmpeg diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 91549dc5bac..0a1236c225d 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -1,38 +1,40 @@ /* * 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 * - * This file is part of FFmpeg. + * Support for external huffman table, various fixes (AVID workaround), + * aspecting, new decode_frame mechanism and apple mjpeg-b support + * by Alex Beregszaszi * - * FFmpeg is free software; you can redistribute it and/or + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * FFmpeg is distributed in the hope that it will be useful, + * Libav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software + * License along with Libav; 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 * MJPEG decoder. */ //#define DEBUG #include +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" #include "avcodec.h" #include "dsputil.h" #include "mjpeg.h" @@ -40,34 +42,49 @@ #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) { - uint8_t huff_size[256+16]; - uint16_t huff_code[256+16]; + uint8_t huff_size[256]; + uint16_t huff_code[256]; + uint16_t huff_sym[256]; + int i; assert(nb_codes <= 256); memset(huff_size, 0, sizeof(huff_size)); 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); - memmove(huff_code+16, huff_code, sizeof(uint16_t)*nb_codes); - memset(huff_size, 0, sizeof(uint8_t)*16); - memset(huff_code, 0, sizeof(uint16_t)*16); - nb_codes += 16; - } + for(i=0; i<256; i++) + huff_sym[i]= i + 16*is_ac; - return init_vlc(vlc, 9, nb_codes, huff_size, 1, 1, huff_code, 2, 2, use_static); + if(is_ac) huff_sym[0]= 16*256; + + return init_vlc_sparse(vlc, 9, nb_codes, huff_size, 1, 1, huff_code, 2, 2, huff_sym, 2, 2, use_static); +} + +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); + build_vlc(&s->vlcs[2][0], ff_mjpeg_bits_ac_luminance, + ff_mjpeg_val_ac_luminance, 251, 0, 0); + build_vlc(&s->vlcs[2][1], ff_mjpeg_bits_ac_chrominance, + ff_mjpeg_val_ac_chrominance, 251, 0, 0); } -int ff_mjpeg_decode_init(AVCodecContext *avctx) +av_cold int ff_mjpeg_decode_init(AVCodecContext *avctx) { MJpegDecodeContext *s = avctx->priv_data; + if (!s->picture_ptr) + s->picture_ptr = &s->picture; + s->avctx = avctx; dsputil_init(&s->dsp, avctx); ff_init_scantable(s->dsp.idct_permutation, &s->scantable, ff_zigzag_direct); @@ -76,22 +93,22 @@ int ff_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], ff_mjpeg_bits_dc_luminance, - ff_mjpeg_val_dc_luminance, 12, 0, 0); - build_vlc(&s->vlcs[0][1], ff_mjpeg_bits_dc_chrominance, - ff_mjpeg_val_dc_chrominance, 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); + build_basic_mjpeg_vlc(s); +#if FF_API_MJPEG_GLOBAL_OPTS if (avctx->flags & CODEC_FLAG_EXTERN_HUFF) + s->extern_huff = 1; +#endif + if (s->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\n"); + return AVERROR_INVALIDDATA; + } } if (avctx->extradata_size > 9 && AV_RL32(avctx->extradata + 4) == MKTAG('f','i','e','l')) { @@ -100,13 +117,15 @@ int ff_mjpeg_decode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_DEBUG, "mjpeg bottom field first\n"); } } + if (avctx->codec->id == CODEC_ID_AMV) + s->flipped = 1; return 0; } /* quantize tables */ -static int mjpeg_decode_dqt(MJpegDecodeContext *s) +int ff_mjpeg_decode_dqt(MJpegDecodeContext *s) { int len, index, i, j; @@ -141,7 +160,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,11 +202,18 @@ static int mjpeg_decode_dht(MJpegDecodeContext *s) if(build_vlc(&s->vlcs[class][index], bits_table, val_table, code_max + 1, 0, class > 0) < 0){ return -1; } + + if(class>0){ + free_vlc(&s->vlcs[2][index]); + if(build_vlc(&s->vlcs[2][index], bits_table, val_table, code_max + 1, 0, 0) < 0){ + return -1; + } + } } 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; @@ -211,7 +237,7 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s) height= s->height; av_log(s->avctx, AV_LOG_DEBUG, "sof0: picture: %dx%d\n", width, height); - if(avcodec_check_dimensions(s->avctx, width, height)) + if(av_image_check_size(width, height, 0, s->avctx)) return -1; nb_components = get_bits(&s->gb, 8); @@ -264,8 +290,8 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s) s->height < ((s->org_height * 3) / 4)) { s->interlaced = 1; s->bottom_field = s->interlace_polarity; - s->picture.interlaced_frame = 1; - s->picture.top_field_first = !s->interlace_polarity; + s->picture_ptr->interlaced_frame = 1; + s->picture_ptr->top_field_first = !s->interlace_polarity; height *= 2; } @@ -280,28 +306,40 @@ 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); + //NOTE we do not allocate pictures large enough for the possible padding of h/v_count being 4 + if(!(pix_fmt_id & 0xD0D0D0D0)) + pix_fmt_id-= (pix_fmt_id & 0xF0F0F0F0)>>1; + if(!(pix_fmt_id & 0x0D0D0D0D)) + 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) + s->avctx->pix_fmt = PIX_FMT_BGRA; + }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 0x211111: - case 0x221212: + case 0x12111100: + s->avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV440P : PIX_FMT_YUVJ440P; + break; + 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) @@ -312,19 +350,19 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s) s->avctx->pix_fmt = PIX_FMT_GRAY16; } - if(s->picture.data[0]) - s->avctx->release_buffer(s->avctx, &s->picture); + if(s->picture_ptr->data[0]) + s->avctx->release_buffer(s->avctx, s->picture_ptr); - s->picture.reference= 0; - if(s->avctx->get_buffer(s->avctx, &s->picture) < 0){ + if(s->avctx->get_buffer(s->avctx, s->picture_ptr) < 0){ av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return -1; } - s->picture.pict_type= I_TYPE; - s->picture.key_frame= 1; + s->picture_ptr->pict_type= AV_PICTURE_TYPE_I; + s->picture_ptr->key_frame= 1; + s->got_picture = 1; for(i=0; i<3; i++){ - s->linesize[i]= s->picture.linesize[i] << s->interlaced; + s->linesize[i]= s->picture_ptr->linesize[i] << s->interlaced; } // printf("%d %d %d %d %d %d\n", s->width, s->height, s->linesize[0], s->linesize[1], s->interlaced, s->avctx->height); @@ -336,9 +374,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; } @@ -377,19 +423,16 @@ static int decode_block(MJpegDecodeContext *s, DCTELEM *block, block[0] = val; /* AC coefs */ i = 0; - {OPEN_READER(re, &s->gb) - for(;;) { + {OPEN_READER(re, &s->gb); + do { UPDATE_CACHE(re, &s->gb); - GET_VLC(code, re, &s->gb, s->vlcs[1][ac_index].table, 9, 2) + GET_VLC(code, re, &s->gb, s->vlcs[1][ac_index].table, 9, 2); - /* EOB */ - if (code == 0x10) - break; i += ((unsigned)code) >> 4; - if(code != 0x100){ code &= 0xf; + if(code){ if(code > MIN_CACHE_BITS - 16){ - UPDATE_CACHE(re, &s->gb) + UPDATE_CACHE(re, &s->gb); } { int cache=GET_CACHE(re,&s->gb); @@ -397,62 +440,59 @@ static int decode_block(MJpegDecodeContext *s, DCTELEM *block, level = (NEG_USR32(sign ^ cache,code) ^ sign) - sign; } - LAST_SKIP_BITS(re, &s->gb, code) + LAST_SKIP_BITS(re, &s->gb, code); - if (i >= 63) { - if(i == 63){ - j = s->scantable.permutated[63]; - block[j] = level * quant_matrix[j]; - break; - } + if (i > 63) { av_log(s->avctx, AV_LOG_ERROR, "error count: %d\n", i); return -1; } j = s->scantable.permutated[i]; block[j] = level * quant_matrix[j]; } - } - CLOSE_READER(re, &s->gb)} + }while(i<63); + CLOSE_READER(re, &s->gb);} 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; } - {OPEN_READER(re, &s->gb) + {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; + GET_VLC(code, re, &s->gb, s->vlcs[2][ac_index].table, 9, 2); + + run = ((unsigned) code) >> 4; + code &= 0xF; + if(code) { + i += run; if(code > MIN_CACHE_BITS - 16){ - UPDATE_CACHE(re, &s->gb) + UPDATE_CACHE(re, &s->gb); } { int cache=GET_CACHE(re,&s->gb); @@ -460,7 +500,7 @@ static int decode_block_progressive(MJpegDecodeContext *s, DCTELEM *block, level = (NEG_USR32(sign ^ cache,code) ^ sign) - sign; } - LAST_SKIP_BITS(re, &s->gb, code) + LAST_SKIP_BITS(re, &s->gb, code); if (i >= se) { if(i == se){ @@ -474,42 +514,135 @@ static int decode_block_progressive(MJpegDecodeContext *s, DCTELEM *block, 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; + if (i >= se) { + av_log(s->avctx, AV_LOG_ERROR, "ZRL overflow: %d\n", i); + return -1; + } }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; + val = (1 << run); + if(run){ + UPDATE_CACHE(re, &s->gb); + val += NEG_USR32(GET_CACHE(re, &s->gb), run); + LAST_SKIP_BITS(re, &s->gb, run); + } + *EOBRUN = val - 1; break; } } } - CLOSE_READER(re, &s->gb)} + 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[2][ac_index].table, 9, 2); + + 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; - uint16_t buffer[32768][4]; + uint16_t (*buffer)[4]; int left[3], top[3], topleft[3]; const int linesize= s->linesize[0]; const int mask= (1<bits)-1; - if((unsigned)s->mb_width > 32768) //dynamic alloc - return -1; + av_fast_malloc(&s->ljpeg_buffer, &s->ljpeg_buffer_size, (unsigned)s->mb_width * 4 * sizeof(s->ljpeg_buffer[0][0])); + buffer= s->ljpeg_buffer; for(i=0; i<3; i++){ buffer[0][i]= 1 << (s->bits + point_transform - 1); } for(mb_y = 0; mb_y < s->mb_height; mb_y++) { const int modified_predictor= mb_y ? predictor : 1; - uint8_t *ptr = s->picture.data[0] + (linesize * mb_y); + uint8_t *ptr = s->picture_ptr->data[0] + (linesize * mb_y); if (s->interlaced && s->bottom_field) ptr += linesize >> 1; @@ -553,9 +686,9 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int predictor, int point } }else{ for(mb_x = 0; mb_x < s->mb_width; mb_x++) { - ptr[4*mb_x+0] = buffer[mb_x][0]; + ptr[4*mb_x+0] = buffer[mb_x][2]; ptr[4*mb_x+1] = buffer[mb_x][1]; - ptr[4*mb_x+2] = buffer[mb_x][2]; + ptr[4*mb_x+2] = buffer[mb_x][0]; } } } @@ -586,7 +719,7 @@ static int ljpeg_decode_yuv_scan(MJpegDecodeContext *s, int predictor, int point for(j=0; jpicture.data[c] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap + ptr = s->picture_ptr->data[c] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap if(y==0 && mb_y==0){ if(x==0 && mb_x==0){ pred= 128 << point_transform; @@ -626,7 +759,7 @@ static int ljpeg_decode_yuv_scan(MJpegDecodeContext *s, int predictor, int point for(j=0; jpicture.data[c] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap + ptr = s->picture_ptr->data[c] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap PREDICT(pred, ptr[-linesize-1], ptr[-linesize], ptr[-1], predictor); *ptr= pred + (mjpeg_decode_dc(s, s->dc_index[i]) << point_transform); if (++x == h) { @@ -645,19 +778,67 @@ 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 av_always_inline void mjpeg_copy_block(uint8_t *dst, const uint8_t *src, + int linesize, int lowres) +{ + switch (lowres) { + case 0: copy_block8(dst, src, linesize, linesize, 8); + break; + case 1: copy_block4(dst, src, linesize, linesize, 4); + break; + case 2: copy_block2(dst, src, linesize, linesize, 2); + break; + case 3: *dst = *src; + break; + } +} + +static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int Ah, int Al, + const uint8_t *mb_bitmask, const AVFrame *reference){ int i, mb_x, mb_y; - int EOBRUN = 0; + uint8_t* data[MAX_COMPONENTS]; + const uint8_t *reference_data[MAX_COMPONENTS]; + int linesize[MAX_COMPONENTS]; + GetBitContext mb_bitmask_gb; + + if (mb_bitmask) { + init_get_bits(&mb_bitmask_gb, mb_bitmask, s->mb_width*s->mb_height); + } + + if(s->flipped && s->avctx->flags & CODEC_FLAG_EMU_EDGE) { + av_log(s->avctx, AV_LOG_ERROR, "Can not flip image with CODEC_FLAG_EMU_EDGE set!\n"); + s->flipped = 0; + } + for(i=0; i < nb_components; i++) { + int c = s->comp_index[i]; + data[c] = s->picture_ptr->data[c]; + reference_data[c] = reference ? reference->data[c] : NULL; + linesize[c]=s->linesize[c]; + s->coefs_finished[c] |= 1; + if(s->flipped) { + //picture should be flipped upside-down for this codec + int offset = (linesize[c] * (s->v_scount[i] * (8 * s->mb_height -((s->height/s->v_max)&7)) - 1 )); + data[c] += offset; + reference_data[c] += offset; + 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++) { + const int copy_mb = mb_bitmask && !get_bits1(&mb_bitmask_gb); + if (s->restart_interval && !s->restart_count) s->restart_count = s->restart_interval; + if(get_bits_count(&s->gb)>s->gb.size_in_bits){ + av_log(s->avctx, AV_LOG_ERROR, "overread %d\n", get_bits_count(&s->gb) - s->gb.size_in_bits); + return -1; + } for(i=0;inb_blocks[i]; c = s->comp_index[i]; h = s->h_scount[i]; @@ -665,41 +846,50 @@ 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, + block_offset = (((linesize[c] * (v * mb_y + y) * 8) + + (h * mb_x + x) * 8) >> s->avctx->lowres); + + if(s->interlaced && s->bottom_field) + block_offset += linesize[c] >> 1; + ptr = data[c] + block_offset; + if(!s->progressive) { + if (copy_mb) { + mjpeg_copy_block(ptr, reference_data[c] + block_offset, linesize[c], s->avctx->lowres); + } else { + 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 && show_bits(&s->gb, 8) == 0xFF){ /* skip RSTn */ + --s->restart_count; align_get_bits(&s->gb); - skip_bits(&s->gb, 16); /* skip RSTn */ + while(show_bits(&s->gb, 8) == 0xFF) + skip_bits(&s->gb, 8); + skip_bits(&s->gb, 8); for (i=0; ilast_dc[i] = 1024; } @@ -708,23 +898,89 @@ static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int ss, i return 0; } -static int mjpeg_decode_sos(MJpegDecodeContext *s) +static int mjpeg_decode_scan_progressive_ac(MJpegDecodeContext *s, int ss, int se, int Ah, int Al, + const uint8_t *mb_bitmask, const AVFrame *reference){ + int mb_x, mb_y; + int EOBRUN = 0; + int c = s->comp_index[0]; + uint8_t* data = s->picture_ptr->data[c]; + const uint8_t *reference_data = reference ? reference->data[c] : NULL; + int linesize = s->linesize[c]; + int last_scan = 0; + int16_t *quant_matrix = s->quant_matrixes[ s->quant_index[c] ]; + GetBitContext mb_bitmask_gb; + + if (mb_bitmask) { + init_get_bits(&mb_bitmask_gb, mb_bitmask, s->mb_width*s->mb_height); + } + + if(!Al) { + s->coefs_finished[c] |= (1LL<<(se+1))-(1LL<coefs_finished[c]; + } + + if(s->interlaced && s->bottom_field) { + int offset = linesize >> 1; + data += offset; + reference_data += offset; + } + + for(mb_y = 0; mb_y < s->mb_height; mb_y++) { + int block_offset = (mb_y*linesize*8 >> s->avctx->lowres); + uint8_t *ptr = data + block_offset; + 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++) { + const int copy_mb = mb_bitmask && !get_bits1(&mb_bitmask_gb); + + if (!copy_mb) { + 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) { + if (copy_mb) { + mjpeg_copy_block(ptr, reference_data + block_offset, linesize, s->avctx->lowres); + } else { + s->dsp.idct_put(ptr, linesize, *block); + ptr += 8 >> s->avctx->lowres; + } + } + } + } + return 0; +} + +int ff_mjpeg_decode_sos(MJpegDecodeContext *s, + const uint8_t *mb_bitmask, const AVFrame *reference) { 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; /* XXX: verify len field validity */ len = get_bits(&s->gb, 16); nb_components = get_bits(&s->gb, 8); + if (nb_components == 0 || nb_components > MAX_COMPONENTS){ + av_log(s->avctx, AV_LOG_ERROR, "decode_sos: nb_components (%d) unsupported\n", nb_components); + return -1; + } if (len != 6+2*nb_components) { 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); @@ -737,6 +993,10 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s) av_log(s->avctx, AV_LOG_ERROR, "decode_sos: index(%d) out of components\n", index); return -1; } + /* Metasoft MJPEG codec has Cb and Cr swapped */ + if (s->avctx->codec_tag == MKTAG('M', 'T', 'S', 'J') + && nb_components == 3 && s->nb_components == 3 && i) + index = 3 - i; s->comp_index[i] = index; @@ -750,24 +1010,8 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s) if (s->dc_index[i] < 0 || s->ac_index[i] < 0 || s->dc_index[i] >= 4 || s->ac_index[i] >= 4) goto out_of_range; -#if 0 //buggy - switch(s->start_code) - { - case SOF0: - if (dc_index[i] > 1 || ac_index[i] > 1) - goto out_of_range; - break; - case SOF1: - case SOF2: - if (dc_index[i] > 3 || ac_index[i] > 3) - goto out_of_range; - break; - case SOF3: - if (dc_index[i] > 3 || ac_index[i] != 0) - goto out_of_range; - break; - } -#endif + if (!s->vlcs[0][s->dc_index[i]].table || !s->vlcs[1][s->ac_index[i]].table) + goto out_of_range; } predictor= get_bits(&s->gb, 8); /* JPEG Ss / lossless JPEG predictor /JPEG-LS NEAR */ @@ -793,7 +1037,7 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s) } if(s->avctx->debug & FF_DEBUG_PICT_INFO) - av_log(s->avctx, AV_LOG_DEBUG, "%s %s p:%d >>:%d ilv:%d bits:%d %s\n", s->lossless ? "lossless" : "sequencial DCT", s->rgb ? "RGB" : "", + av_log(s->avctx, AV_LOG_DEBUG, "%s %s p:%d >>:%d ilv:%d bits:%d %s\n", s->lossless ? "lossless" : "sequential DCT", s->rgb ? "RGB" : "", predictor, point_transform, ilv, s->bits, s->pegasus_rct ? "PRCT" : (s->rct ? "RCT" : "")); @@ -803,11 +1047,12 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s) skip_bits(&s->gb, 8); if(s->lossless){ - if(ENABLE_JPEGLS_DECODER && 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) @@ -818,8 +1063,15 @@ 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, + mb_bitmask, reference) < 0) + return -1; + } else { + if(mjpeg_decode_scan(s, nb_components, prev_shift, point_transform, + mb_bitmask, reference) < 0) + return -1; + } } emms_c(); return 0; @@ -849,8 +1101,8 @@ static int mjpeg_decode_app(MJpegDecodeContext *s) if(8*len + get_bits_count(&s->gb) > s->gb.size_in_bits) return -1; - id = (get_bits(&s->gb, 16) << 16) | get_bits(&s->gb, 16); - id = be2me_32(id); + id = get_bits_long(&s->gb, 32); + id = av_be2ne32(id); len -= 6; if(s->avctx->debug & FF_DEBUG_STARTCODE){ @@ -860,7 +1112,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 @@ -888,7 +1140,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 */ @@ -918,7 +1170,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"); @@ -930,7 +1182,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 ? */ @@ -956,10 +1208,10 @@ static int mjpeg_decode_app(MJpegDecodeContext *s) /* Apple MJPEG-A */ if ((s->start_code == APP1) && (len > (0x28 - 8))) { - id = (get_bits(&s->gb, 16) << 16) | get_bits(&s->gb, 16); - id = be2me_32(id); + id = get_bits_long(&s->gb, 32); + id = av_be2ne32(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 */ @@ -1013,6 +1265,10 @@ static int mjpeg_decode_com(MJpegDecodeContext *s) else if(!strcmp(cbuf, "CS=ITU601")){ s->cs_itu601= 1; } + else if((len > 20 && !strncmp(cbuf, "Intel(R) JPEG Library", 21)) || + (len > 19 && !strncmp(cbuf, "Metasoft MJPEG Codec", 20))){ + s->flipped = 1; + } av_free(cbuf); } @@ -1021,34 +1277,11 @@ static int mjpeg_decode_com(MJpegDecodeContext *s) return 0; } -#if 0 -static int valid_marker_list[] = -{ - /* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f */ -/* 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/* 1 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/* 2 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/* 3 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/* 4 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/* 5 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/* 6 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/* 7 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/* 8 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/* 9 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/* a */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/* b */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/* c */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -/* d */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -/* e */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -/* f */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, -} -#endif - /* 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 @@ -1069,47 +1302,31 @@ static int find_marker(uint8_t **pbuf_ptr, uint8_t *buf_end) } val = -1; found: -#ifdef DEBUG - av_log(NULL, AV_LOG_VERBOSE, "find_marker skipped %d bytes\n", skipped); -#endif + av_dlog(NULL, "find_marker skipped %d bytes\n", skipped); *pbuf_ptr = buf_ptr; return val; } -int ff_mjpeg_decode_frame(AVCodecContext *avctx, - void *data, int *data_size, - uint8_t *buf, int buf_size) +int ff_mjpeg_find_marker(MJpegDecodeContext *s, + const uint8_t **buf_ptr, const uint8_t *buf_end, + const uint8_t **unescaped_buf_ptr, int *unescaped_buf_size) { - MJpegDecodeContext *s = avctx->priv_data; - uint8_t *buf_end, *buf_ptr; int start_code; - AVFrame *picture = data; - - buf_ptr = buf; - buf_end = buf + buf_size; - while (buf_ptr < buf_end) { - /* find start next marker */ - start_code = find_marker(&buf_ptr, buf_end); - { - /* EOF */ - 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); + start_code = find_marker(buf_ptr, buf_end); - if ((buf_end - buf_ptr) > s->buffer_size) + if ((buf_end - *buf_ptr) > s->buffer_size) { av_free(s->buffer); - s->buffer_size = buf_end-buf_ptr; + s->buffer_size = buf_end - *buf_ptr; s->buffer = av_malloc(s->buffer_size + FF_INPUT_BUFFER_PADDING_SIZE); - av_log(avctx, AV_LOG_DEBUG, "buffer too small, expanding to %d bytes\n", + av_log(s->avctx, AV_LOG_DEBUG, "buffer too small, expanding to %d bytes\n", s->buffer_size); } /* 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 (srccodec_id != CODEC_ID_THP) + if (s->avctx->codec_id != CODEC_ID_THP) { if (x == 0xff) { while (src < buf_end && x == 0xff) @@ -1130,13 +1347,14 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, } } } - init_get_bits(&s->gb, s->buffer, (dst - s->buffer)*8); + *unescaped_buf_ptr = s->buffer; + *unescaped_buf_size = dst - s->buffer; - av_log(avctx, AV_LOG_DEBUG, "escaping removed %d bytes\n", - (buf_end - buf_ptr) - (dst - s->buffer)); + av_log(s->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; @@ -1172,10 +1390,46 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, } flush_put_bits(&pb); - init_get_bits(&s->gb, dst, bit_count); + *unescaped_buf_ptr = dst; + *unescaped_buf_size = (bit_count + 7) >> 3; } else - init_get_bits(&s->gb, buf_ptr, (buf_end - buf_ptr)*8); + { + *unescaped_buf_ptr = *buf_ptr; + *unescaped_buf_size = buf_end - *buf_ptr; + } + + return start_code; +} + +int ff_mjpeg_decode_frame(AVCodecContext *avctx, + void *data, int *data_size, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + MJpegDecodeContext *s = avctx->priv_data; + const uint8_t *buf_end, *buf_ptr; + const uint8_t *unescaped_buf_ptr; + int unescaped_buf_size; + int start_code; + AVFrame *picture = data; + + s->got_picture = 0; // picture from previous image can not be reused + buf_ptr = buf; + buf_end = buf + buf_size; + while (buf_ptr < buf_end) { + /* find start next marker */ + start_code = ff_mjpeg_find_marker(s, &buf_ptr, buf_end, + &unescaped_buf_ptr, &unescaped_buf_size); + { + /* EOF */ + if (start_code < 0) { + goto the_end; + } else { + av_log(avctx, AV_LOG_DEBUG, "marker=%x avail_size_in_buf=%td\n", start_code, buf_end - buf_ptr); + + init_get_bits(&s->gb, unescaped_buf_ptr, unescaped_buf_size*8); s->start_code = start_code; if(s->avctx->debug & FF_DEBUG_STARTCODE){ @@ -1201,44 +1455,45 @@ int ff_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; } break; case SOF0: + case SOF1: 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 (!ENABLE_JPEGLS_DECODER || ff_jpegls_decode_lse(s) < 0) + if (!CONFIG_JPEGLS_DECODER || ff_jpegls_decode_lse(s) < 0) return -1; break; case EOI: @@ -1246,31 +1501,38 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, if ((s->buggy_avid && !s->interlaced) || s->restart_interval) break; eoi_parser: - { - if (s->interlaced) { - s->bottom_field ^= 1; - /* if not bottom field, do not output image yet */ - if (s->bottom_field == !s->interlace_polarity) - goto not_the_end; - } - *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; - } - - goto the_end; + if (!s->got_picture) { + av_log(avctx, AV_LOG_WARNING, "Found EOI before any SOF, ignoring\n"); + break; } - break; + if (s->interlaced) { + s->bottom_field ^= 1; + /* if not bottom field, do not output image yet */ + if (s->bottom_field == !s->interlace_polarity) + goto not_the_end; + } + *picture = *s->picture_ptr; + *data_size = sizeof(AVFrame); + + if(!s->lossless){ + 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); + if(avctx->debug & FF_DEBUG_QP) + av_log(avctx, AV_LOG_DEBUG, "QP: %d\n", picture->quality); + picture->quality*= FF_QP2LAMBDA; + } + + goto the_end; case SOS: - mjpeg_decode_sos(s); + if (!s->got_picture) { + av_log(avctx, AV_LOG_WARNING, "Can not process SOS before SOF, skipping\n"); + break; + } + if (ff_mjpeg_decode_sos(s, NULL, NULL) < 0 && + (avctx->err_recognition & AV_EF_EXPLODE)) + return AVERROR_INVALIDDATA; /* buggy avid puts EOI every 10-20th frame */ /* if restart period is over process EOI */ if ((s->buggy_avid && !s->interlaced) || s->restart_interval) @@ -1279,7 +1541,6 @@ eoi_parser: case DRI: mjpeg_decode_dri(s); break; - case SOF1: case SOF5: case SOF6: case SOF7: @@ -1305,337 +1566,79 @@ not_the_end: } } } + if (s->got_picture) { + av_log(avctx, AV_LOG_WARNING, "EOI missing, emulating\n"); + goto eoi_parser; + } + av_log(avctx, AV_LOG_FATAL, "No JPEG data found in image\n"); + return -1; 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 = ff_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; -} - -int ff_mjpeg_decode_end(AVCodecContext *avctx) +av_cold int ff_mjpeg_decode_end(AVCodecContext *avctx) { MJpegDecodeContext *s = avctx->priv_data; int i, j; + if (s->picture_ptr && s->picture_ptr->data[0]) + avctx->release_buffer(avctx, s->picture_ptr); + av_free(s->buffer); av_free(s->qscale_table); + av_freep(&s->ljpeg_buffer); + s->ljpeg_buffer_size=0; - for(i=0;i<2;i++) { + for(i=0;i<3;i++) { for(j=0;j<4;j++) free_vlc(&s->vlcs[i][j]); } + for(i=0; iblocks[i]); + av_freep(&s->last_nnz[i]); + } return 0; } -AVCodec mjpeg_decoder = { - "mjpeg", - CODEC_TYPE_VIDEO, - CODEC_ID_MJPEG, - sizeof(MJpegDecodeContext), - ff_mjpeg_decode_init, - NULL, - ff_mjpeg_decode_end, - ff_mjpeg_decode_frame, - CODEC_CAP_DR1, - NULL +#define OFFSET(x) offsetof(MJpegDecodeContext, x) +#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM +static const AVOption options[] = { + { "extern_huff", "Use external huffman table.", OFFSET(extern_huff), AV_OPT_TYPE_INT, { 0 }, 0, 1, VD }, + { NULL }, }; -AVCodec thp_decoder = { - "thp", - CODEC_TYPE_VIDEO, - CODEC_ID_THP, - sizeof(MJpegDecodeContext), - ff_mjpeg_decode_init, - NULL, - ff_mjpeg_decode_end, - ff_mjpeg_decode_frame, - CODEC_CAP_DR1, - NULL +static const AVClass mjpegdec_class = { + .class_name = "MJPEG decoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, }; -AVCodec mjpegb_decoder = { - "mjpegb", - CODEC_TYPE_VIDEO, - CODEC_ID_MJPEGB, - sizeof(MJpegDecodeContext), - ff_mjpeg_decode_init, - NULL, - ff_mjpeg_decode_end, - mjpegb_decode_frame, - CODEC_CAP_DR1, - NULL +AVCodec ff_mjpeg_decoder = { + .name = "mjpeg", + .type = AVMEDIA_TYPE_VIDEO, + .id = CODEC_ID_MJPEG, + .priv_data_size = sizeof(MJpegDecodeContext), + .init = ff_mjpeg_decode_init, + .close = ff_mjpeg_decode_end, + .decode = ff_mjpeg_decode_frame, + .capabilities = CODEC_CAP_DR1, + .max_lowres = 3, + .long_name = NULL_IF_CONFIG_SMALL("MJPEG (Motion JPEG)"), + .priv_class = &mjpegdec_class, }; -AVCodec sp5x_decoder = { - "sp5x", - CODEC_TYPE_VIDEO, - CODEC_ID_SP5X, - sizeof(MJpegDecodeContext), - ff_mjpeg_decode_init, - NULL, - ff_mjpeg_decode_end, - sp5x_decode_frame, - CODEC_CAP_DR1, - NULL +AVCodec ff_thp_decoder = { + .name = "thp", + .type = AVMEDIA_TYPE_VIDEO, + .id = CODEC_ID_THP, + .priv_data_size = sizeof(MJpegDecodeContext), + .init = ff_mjpeg_decode_init, + .close = ff_mjpeg_decode_end, + .decode = ff_mjpeg_decode_frame, + .capabilities = CODEC_CAP_DR1, + .max_lowres = 3, + .long_name = NULL_IF_CONFIG_SMALL("Nintendo Gamecube THP video"), };