📄 mjpeg.c
字号:
#define MAX_COMPONENTS 4typedef struct MJpegDecodeContext { AVCodecContext *avctx; GetBitContext gb; int mpeg_enc_ctx_allocated; /* true if decoding context allocated */ int start_code; /* current start code */ int buffer_size; uint8_t *buffer; int16_t quant_matrixes[4][64]; VLC vlcs[2][4]; int qscale[4]; ///< quantizer scale calculated from quant_matrixes int org_height; /* size given at codec init */ int first_picture; /* true if decoding first picture */ int interlaced; /* true if interlaced */ int bottom_field; /* true if bottom field */ int lossless; int ls; int rgb; int rct; /* standard rct */ int pegasus_rct; /* pegasus reversible colorspace transform */ int bits; /* bits per component */ int maxval; int near; ///< near lossless bound (si 0 for lossless) int t1,t2,t3; int reset; ///< context halfing intervall ?rename int width, height; int mb_width, mb_height; int nb_components; int component_id[MAX_COMPONENTS]; int h_count[MAX_COMPONENTS]; /* horizontal and vertical count for each component */ int v_count[MAX_COMPONENTS]; int comp_index[MAX_COMPONENTS]; int dc_index[MAX_COMPONENTS]; int ac_index[MAX_COMPONENTS]; int nb_blocks[MAX_COMPONENTS]; int h_scount[MAX_COMPONENTS]; int v_scount[MAX_COMPONENTS]; int h_max, v_max; /* maximum h and v counts */ int quant_index[4]; /* quant table index for each component */ int last_dc[MAX_COMPONENTS]; /* last DEQUANTIZED dc (XXX: am I right to do that ?) */ AVFrame picture; /* picture structure */ int linesize[MAX_COMPONENTS]; ///< linesize << interlaced int8_t *qscale_table; __align8(DCTELEM,block[64]); ScanTable scantable; void (*idct_put)(uint8_t *dest/*align 8*/, int line_size, DCTELEM *block/*align 16*/); int restart_interval; int restart_count; int buggy_avid; int cs_itu601; int interlace_polarity; int mjpb_skiptosod; uint16_t RGBbuffer[32768][4];} MJpegDecodeContext;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){ uint8_t huff_size[256]; uint16_t huff_code[256]; memset(huff_size, 0, sizeof(huff_size)); build_huffman_codes(huff_size, huff_code, bits_table, val_table); return init_vlc(vlc, 9, nb_codes, huff_size, 1, 1, huff_code, 2, 2, use_static);}static int mjpeg_decode_init(AVCodecContext *avctx){ MJpegDecodeContext *s = avctx->priv_data; MpegEncContext s2; memset(s, 0, sizeof(MJpegDecodeContext)); s->avctx = avctx; /* ugly way to get the idct & scantable FIXME */ memset(&s2, 0, sizeof(MpegEncContext)); s2.avctx= avctx;// s2->out_format = FMT_MJPEG; dsputil_init(&s2.dsp, avctx); DCT_common_init(&s2); s->scantable= s2.intra_scantable; s->idct_put= s2.dsp.idct_put; s->mpeg_enc_ctx_allocated = 0; s->buffer_size = 0; s->buffer = NULL; s->start_code = -1; s->first_picture = 1; s->org_height = avctx->coded_height; build_vlc(&s->vlcs[0][0], bits_dc_luminance, val_dc_luminance, 12, 0); build_vlc(&s->vlcs[0][1], bits_dc_chrominance, val_dc_chrominance, 12, 0); build_vlc(&s->vlcs[1][0], bits_ac_luminance, val_ac_luminance, 251, 0); build_vlc(&s->vlcs[1][1], bits_ac_chrominance, val_ac_chrominance, 251, 0); 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 */ } return 0;}/** * finds the end of the current frame in the bitstream. * @return the position of the first byte of the next frame, or -1 */static int find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size){ int vop_found, i; uint16_t state; vop_found= pc->frame_start_found; state= pc->state; i=0; if(!vop_found){ for(i=0; i<buf_size; i++){ state= (state<<8) | buf[i]; if(state == 0xFFD8){ i++; vop_found=1; break; } } } if(vop_found){ /* EOF considered as end of frame */ if (buf_size == 0) return 0; for(; i<buf_size; i++){ state= (state<<8) | buf[i]; if(state == 0xFFD8){ pc->frame_start_found=0; pc->state=0; return i-1; } } } pc->frame_start_found= vop_found; pc->state= state; return END_NOT_FOUND;}static int jpeg_parse(AVCodecParserContext *s, AVCodecContext *avctx, uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size){ ParseContext *pc = s->priv_data; int next; next= find_frame_end(pc, buf, buf_size); if (ff_combine_frame(pc, next, (uint8_t **)&buf, &buf_size) < 0) { *poutbuf = NULL; *poutbuf_size = 0; return buf_size; } *poutbuf = (uint8_t *)buf; *poutbuf_size = buf_size; return next;}/* quantize tables */static int mjpeg_decode_dqt(MJpegDecodeContext *s){ int len, index, i, j; len = get_bits(&s->gb, 16) - 2; while (len >= 65) { /* only 8 bit precision handled */ if (get_bits(&s->gb, 4) != 0) { dprintf("dqt: 16bit precision\n"); return -1; } index = get_bits(&s->gb, 4); if (index >= 4) return -1; dprintf("index=%d\n", index); /* read quant table */ for(i=0;i<64;i++) { j = s->scantable.permutated[i]; s->quant_matrixes[index][j] = get_bits(&s->gb, 8); } //XXX FIXME finetune, and perhaps add dc too s->qscale[index]= FFMAX( s->quant_matrixes[index][s->scantable.permutated[1]], s->quant_matrixes[index][s->scantable.permutated[8]]) >> 1; dprintf("qscale[%d]: %d\n", index, s->qscale[index]); len -= 65; } return 0;}/* decode huffman tables and build VLC decoders */static int mjpeg_decode_dht(MJpegDecodeContext *s){ int len, index, i, class, n, v, code_max; uint8_t bits_table[17]; uint8_t val_table[256]; len = get_bits(&s->gb, 16) - 2; while (len > 0) { if (len < 17) return -1; class = get_bits(&s->gb, 4); if (class >= 2) return -1; index = get_bits(&s->gb, 4); if (index >= 4) return -1; n = 0; for(i=1;i<=16;i++) { bits_table[i] = get_bits(&s->gb, 8); n += bits_table[i]; } len -= 17; if (len < n || n > 256) return -1; code_max = 0; for(i=0;i<n;i++) { v = get_bits(&s->gb, 8); if (v > code_max) code_max = v; val_table[i] = v; } len -= n; /* build VLC and flush previous vlc if present */ free_vlc(&s->vlcs[class][index]); dprintf("class=%d index=%d nb_codes=%d\n", class, index, code_max + 1); if(build_vlc(&s->vlcs[class][index], bits_table, val_table, code_max + 1, 0) < 0){ return -1; } } return 0;}static int mjpeg_decode_sof(MJpegDecodeContext *s){ int len, nb_components, i, width, height; /* XXX: verify len field validity */ len = get_bits(&s->gb, 16); s->bits= get_bits(&s->gb, 8); if(s->pegasus_rct) s->bits=9; if(s->bits==9 && !s->pegasus_rct) s->rct=1; //FIXME ugly if (s->bits != 8 && !s->lossless){ av_log(s->avctx, AV_LOG_ERROR, "only 8 bits/component accepted\n"); return -1; } height = get_bits(&s->gb, 16); width = get_bits(&s->gb, 16); dprintf("sof0: picture: %dx%d\n", width, height); if(avcodec_check_dimensions(s->avctx, width, height)) return -1; nb_components = get_bits(&s->gb, 8); if (nb_components <= 0 || nb_components > MAX_COMPONENTS) return -1; s->nb_components = nb_components; s->h_max = 1; s->v_max = 1; for(i=0;i<nb_components;i++) { /* component id */ s->component_id[i] = get_bits(&s->gb, 8) - 1; s->h_count[i] = get_bits(&s->gb, 4); s->v_count[i] = get_bits(&s->gb, 4); /* compute hmax and vmax (only used in interleaved case) */ if (s->h_count[i] > s->h_max) s->h_max = s->h_count[i]; if (s->v_count[i] > s->v_max) s->v_max = s->v_count[i]; s->quant_index[i] = get_bits(&s->gb, 8); if (s->quant_index[i] >= 4) return -1; dprintf("component %d %d:%d id: %d quant:%d\n", i, s->h_count[i], s->v_count[i], s->component_id[i], s->quant_index[i]); } if(s->v_max==1 && s->h_max==1 && s->lossless==1) s->rgb=1; /* if different size, realloc/alloc picture */ /* XXX: also check h_count and v_count */ if (width != s->width || height != s->height) { av_freep(&s->qscale_table); s->width = width; s->height = height; /* test interlaced mode */ if (s->first_picture && s->org_height != 0 && s->height < ((s->org_height * 3) / 4)) { s->interlaced = 1;// s->bottom_field = (s->interlace_polarity) ? 1 : 0; s->bottom_field = 0; height *= 2; } avcodec_set_dimensions(s->avctx, width, height); s->qscale_table= av_mallocz((s->width+15)/16); s->first_picture = 0; } if(s->interlaced && s->bottom_field) return 0; /* XXX: not complete test ! */ switch((s->h_count[0] << 4) | s->v_count[0]) { case 0x11: if(s->rgb){ s->avctx->pix_fmt = PIX_FMT_RGBA32; }else if(s->nb_components==3) s->avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV444P : PIX_FMT_YUVJ444P; else s->avctx->pix_fmt = PIX_FMT_GRAY8; break; case 0x21: s->avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV422P : PIX_FMT_YUVJ422P; break; default: case 0x22: s->avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV420P : PIX_FMT_YUVJ420P; break; } if(s->picture.data[0]) s->avctx->release_buffer(s->avctx, &s->picture); s->picture.reference= 0; if(s->avctx->get_buffer(s->avctx, &s->picture) < 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; for(i=0; i<3; i++){ s->linesize[i]= s->picture.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); if (len != (8+(3*nb_components))) { dprintf("decode_sof0: error, len(%d) mismatch\n", len); } return 0;}static inline int mjpeg_decode_dc(MJpegDecodeContext *s, int dc_index){ int code; code = get_vlc2(&s->gb, s->vlcs[0][dc_index].table, 9, 2); if (code < 0) { dprintf("mjpeg_decode_dc: bad vlc: %d:%d (%p)\n", 0, dc_index, &s->vlcs[0][dc_index]); return 0xffff; } if(code) return get_xbits(&s->gb, code); else return 0;}/* decode block and dequantize */static int decode_block(MJpegDecodeContext *s, DCTELEM *block, int component, int dc_index, int ac_index, int quant_index){ int code, i, j, level, val; VLC *ac_vlc; int16_t *quant_matrix; /* DC coef */ val = mjpeg_decode_dc(s, dc_index); if (val == 0xffff) { dprintf("error dc\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -