📄 mjpeg.c
字号:
/* ugly way to get the idct & scantable FIXME */ memset(&s2, 0, sizeof(MpegEncContext)); s2.flags= avctx->flags; s2.avctx= avctx;// s2->out_format = FMT_MJPEG; s2.width = 8; s2.height = 8; if (MPV_common_init(&s2) < 0) return -1; s->scantable= s2.intra_scantable; s->idct_put= s2.dsp.idct_put; MPV_common_end(&s2); s->mpeg_enc_ctx_allocated = 0; s->buffer_size = 102400; /* smaller buffer should be enough, but photojpg files could ahive bigger sizes */ s->buffer = av_malloc(s->buffer_size); if (!s->buffer) return -1; s->start_code = -1; s->first_picture = 1; s->org_width = avctx->width; s->org_height = avctx->height; build_vlc(&s->vlcs[0][0], bits_dc_luminance, val_dc_luminance, 12); build_vlc(&s->vlcs[0][1], bits_dc_chrominance, val_dc_chrominance, 12); build_vlc(&s->vlcs[1][0], bits_ac_luminance, val_ac_luminance, 251); build_vlc(&s->vlcs[1][1], bits_ac_chrominance, val_ac_chrominance, 251); 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;}/* 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){ 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); 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; } 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 s->avctx->pix_fmt = PIX_FMT_YUV444P; break; case 0x21: s->avctx->pix_fmt = PIX_FMT_YUV422P; break; default: case 0x22: s->avctx->pix_fmt = PIX_FMT_YUV420P; 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"); return -1; } quant_matrix = s->quant_matrixes[quant_index]; val = val * quant_matrix[0] + s->last_dc[component]; s->last_dc[component] = val; block[0] = val; /* AC coefs */ ac_vlc = &s->vlcs[1][ac_index]; i = 1; for(;;) { code = get_vlc2(&s->gb, s->vlcs[1][ac_index].table, 9, 2); if (code < 0) { dprintf("error ac\n"); return -1; } /* EOB */ if (code == 0) break; if (code == 0xf0) { i += 16; } else { level = get_xbits(&s->gb, code & 0xf); i += code >> 4; if (i >= 64) { dprintf("error count: %d\n", i); return -1; } j = s->scantable.permutated[i]; block[j] = level * quant_matrix[j]; i++; if (i >= 64) break; } } return 0;}static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int predictor, int point_transform){ int i, mb_x, mb_y; uint16_t buffer[2048][4]; int left[3], top[3], topleft[3]; const int linesize= s->linesize[0]; const int mask= (1<<s->bits)-1; 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); if (s->interlaced && s->bottom_field) ptr += linesize >> 1; for(i=0; i<3; i++){ top[i]= left[i]= topleft[i]= buffer[0][i]; } for(mb_x = 0; mb_x < s->mb_width; mb_x++) { if (s->restart_interval && !s->restart_count) s->restart_count = s->restart_interval; for(i=0;i<3;i++) { int pred; topleft[i]= top[i]; top[i]= buffer[mb_x][i]; PREDICT(pred, topleft[i], top[i], left[i], modified_predictor); left[i]= buffer[mb_x][i]= mask & (pred + (mjpeg_decode_dc(s, s->dc_index[i]) << point_transform)); } if (s->restart_interval && !--s->restart_count) { align_get_bits(&s->gb); skip_bits(&s->gb, 16); /* skip RSTn */ } } if(s->rct){ for(mb_x = 0; mb_x < s->mb_width; mb_x++) { ptr[4*mb_x+1] = buffer[mb_x][0] - ((buffer[mb_x][1] + buffer[mb_x][2] - 0x200)>>2); ptr[4*mb_x+0] = buffer[mb_x][1] + ptr[4*mb_x+1]; ptr[4*mb_x+2] = buffer[mb_x][2] + ptr[4*mb_x+1]; } }else if(s->pegasus_rct){ for(mb_x = 0; mb_x < s->mb_width; mb_x++) { ptr[4*mb_x+1] = buffer[mb_x][0] - ((buffer[mb_x][1] + buffer[mb_x][2])>>2); ptr[4*mb_x+0] = buffer[mb_x][1] + ptr[4*mb_x+1]; ptr[4*mb_x+2] = buffer[mb_x][2] + ptr[4*mb_x+1]; } }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+1] = buffer[mb_x][1]; ptr[4*mb_x+2] = buffer[mb_x][2]; } } } return 0;}static int ljpeg_decode_yuv_scan(MJpegDecodeContext *s, int predictor, int point_transform){ int i, mb_x, mb_y; const int nb_components=3; 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) s->restart_count = s->restart_interval; if(mb_x==0 || mb_y==0 || s->interlaced){ for(i=0;i<nb_components;i++) { uint8_t *ptr; int n, h, v, x, y, c, j, linesize; n = s->nb_blocks[i]; c = s->comp_index[i]; h = s->h_scount[i]; v = s->v_scount[i]; x = 0; y = 0; linesize= s->linesize[c]; for(j=0; j<n; j++) { int pred; ptr = s->picture.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; }else{ pred= ptr[-1]; } }else{ if(x==0 && mb_x==0){ pred= ptr[-linesize]; }else{ PREDICT(pred, ptr[-linesize-1], ptr[-linesize], ptr[-1], predictor); } } if (s->interlaced && s->bottom_field) ptr += linesize >> 1; *ptr= pred + (mjpeg_decode_dc(s, s->dc_index[i]) << point_transform); if (++x == h) { x = 0; y++; } } } }else{ for(i=0;i<nb_components;i++) { uint8_t *ptr; int n, h, v, x, y, c, j, linesize; n = s->nb_blocks[i]; c = s->comp_index[i]; h = s->h_scount[i]; v = s->v_scount[i]; x = 0; y = 0; linesize= s->linesize[c];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -