📄 mjpeg.c
字号:
/* Y component */ put_bits(&s->pb, 8, 1); /* component number */ put_bits(&s->pb, 4, s->mjpeg_hsample[0]); /* H factor */ put_bits(&s->pb, 4, s->mjpeg_vsample[0]); /* V factor */ put_bits(&s->pb, 8, 0); /* select matrix */ /* Cb component */ put_bits(&s->pb, 8, 2); /* component number */ put_bits(&s->pb, 4, s->mjpeg_hsample[1]); /* H factor */ put_bits(&s->pb, 4, s->mjpeg_vsample[1]); /* V factor */#ifdef TWOMATRIXES put_bits(&s->pb, 8, 1); /* select matrix */#else put_bits(&s->pb, 8, 0); /* select matrix */#endif /* Cr component */ put_bits(&s->pb, 8, 3); /* component number */ put_bits(&s->pb, 4, s->mjpeg_hsample[2]); /* H factor */ put_bits(&s->pb, 4, s->mjpeg_vsample[2]); /* V factor */#ifdef TWOMATRIXES put_bits(&s->pb, 8, 1); /* select matrix */#else put_bits(&s->pb, 8, 0); /* select matrix */#endif } /* scan header */ put_marker(&s->pb, SOS); put_bits(&s->pb, 16, 12); /* length */ put_bits(&s->pb, 8, 3); /* 3 components */ /* Y component */ put_bits(&s->pb, 8, 1); /* index */ put_bits(&s->pb, 4, 0); /* DC huffman table index */ put_bits(&s->pb, 4, 0); /* AC huffman table index */ /* Cb component */ put_bits(&s->pb, 8, 2); /* index */ put_bits(&s->pb, 4, 1); /* DC huffman table index */ put_bits(&s->pb, 4, 1); /* AC huffman table index */ /* Cr component */ put_bits(&s->pb, 8, 3); /* index */ put_bits(&s->pb, 4, 1); /* DC huffman table index */ put_bits(&s->pb, 4, 1); /* AC huffman table index */ put_bits(&s->pb, 8, 0); /* Ss (not used) */ put_bits(&s->pb, 8, 63); /* Se (not used) */ put_bits(&s->pb, 8, 0); /* Ah/Al (not used) */}static void escape_FF(MpegEncContext *s, int start){ int size= get_bit_count(&s->pb) - start*8; int i, ff_count; uint8_t *buf= s->pb.buf + start; int align= (-(int)(buf))&3; assert((size&7) == 0); size >>= 3; ff_count=0; for(i=0; i<size && i<align; i++){ if(buf[i]==0xFF) ff_count++; } for(; i<size-15; i+=16){ int acc, v; v= *(uint32_t*)(&buf[i]); acc= (((v & (v>>4))&0x0F0F0F0F)+0x01010101)&0x10101010; v= *(uint32_t*)(&buf[i+4]); acc+=(((v & (v>>4))&0x0F0F0F0F)+0x01010101)&0x10101010; v= *(uint32_t*)(&buf[i+8]); acc+=(((v & (v>>4))&0x0F0F0F0F)+0x01010101)&0x10101010; v= *(uint32_t*)(&buf[i+12]); acc+=(((v & (v>>4))&0x0F0F0F0F)+0x01010101)&0x10101010; acc>>=4; acc+= (acc>>16); acc+= (acc>>8); ff_count+= acc&0xFF; } for(; i<size; i++){ if(buf[i]==0xFF) ff_count++; } if(ff_count==0) return; /* skip put bits */ for(i=0; i<ff_count-3; i+=4) put_bits(&s->pb, 32, 0); put_bits(&s->pb, (ff_count-i)*8, 0); flush_put_bits(&s->pb); for(i=size-1; ff_count; i--){ int v= buf[i]; if(v==0xFF){//printf("%d %d\n", i, ff_count); buf[i+ff_count]= 0; ff_count--; } buf[i+ff_count]= v; }}void mjpeg_picture_trailer(MpegEncContext *s){ int pad= (-get_bit_count(&s->pb))&7; put_bits(&s->pb, pad,0xFF>>(8-pad)); flush_put_bits(&s->pb); assert((s->header_bits&7)==0); escape_FF(s, s->header_bits>>3); put_marker(&s->pb, EOI);}static inline void mjpeg_encode_dc(MpegEncContext *s, int val, UINT8 *huff_size, UINT16 *huff_code){ int mant, nbits; if (val == 0) { put_bits(&s->pb, huff_size[0], huff_code[0]); } else { mant = val; if (val < 0) { val = -val; mant--; } /* compute the log (XXX: optimize) */ nbits = 0; while (val != 0) { val = val >> 1; nbits++; } put_bits(&s->pb, huff_size[nbits], huff_code[nbits]); put_bits(&s->pb, nbits, mant & ((1 << nbits) - 1)); }}static void encode_block(MpegEncContext *s, DCTELEM *block, int n){ int mant, nbits, code, i, j; int component, dc, run, last_index, val; MJpegContext *m = s->mjpeg_ctx; UINT8 *huff_size_ac; UINT16 *huff_code_ac; /* DC coef */ component = (n <= 3 ? 0 : n - 4 + 1); dc = block[0]; /* overflow is impossible */ val = dc - s->last_dc[component]; if (n < 4) { mjpeg_encode_dc(s, val, m->huff_size_dc_luminance, m->huff_code_dc_luminance); huff_size_ac = m->huff_size_ac_luminance; huff_code_ac = m->huff_code_ac_luminance; } else { mjpeg_encode_dc(s, val, m->huff_size_dc_chrominance, m->huff_code_dc_chrominance); huff_size_ac = m->huff_size_ac_chrominance; huff_code_ac = m->huff_code_ac_chrominance; } s->last_dc[component] = dc; /* AC coefs */ run = 0; last_index = s->block_last_index[n]; for(i=1;i<=last_index;i++) { j = s->intra_scantable.permutated[i]; val = block[j]; if (val == 0) { run++; } else { while (run >= 16) { put_bits(&s->pb, huff_size_ac[0xf0], huff_code_ac[0xf0]); run -= 16; } mant = val; if (val < 0) { val = -val; mant--; } /* compute the log (XXX: optimize) */ nbits = 0; while (val != 0) { val = val >> 1; nbits++; } code = (run << 4) | nbits; put_bits(&s->pb, huff_size_ac[code], huff_code_ac[code]); put_bits(&s->pb, nbits, mant & ((1 << nbits) - 1)); run = 0; } } /* output EOB only if not already 64 values */ if (last_index < 63 || run != 0) put_bits(&s->pb, huff_size_ac[0], huff_code_ac[0]);}void mjpeg_encode_mb(MpegEncContext *s, DCTELEM block[6][64]){ int i; for(i=0;i<6;i++) { encode_block(s, block[i], i); }}/******************************************//* decoding */#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 *buffer; INT16 quant_matrixes[4][64]; VLC vlcs[2][4]; int org_width, 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 width, 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 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 ?) */ UINT8 *current_picture[MAX_COMPONENTS]; /* picture structure */ int linesize[MAX_COMPONENTS]; DCTELEM block[64] __align8; ScanTable scantable; void (*idct_put)(UINT8 *dest/*align 8*/, int line_size, DCTELEM *block/*align 16*/); int restart_interval; int restart_count; int buggy_avid; int interlace_polarity;} MJpegDecodeContext;static int mjpeg_decode_dht(MJpegDecodeContext *s);static void build_vlc(VLC *vlc, const UINT8 *bits_table, const UINT8 *val_table, int nb_codes){ UINT8 huff_size[256]; UINT16 huff_code[256]; memset(huff_size, 0, sizeof(huff_size)); build_huffman_codes(huff_size, huff_code, bits_table, val_table); init_vlc(vlc, 9, nb_codes, huff_size, 1, 1, huff_code, 2, 2);}static int mjpeg_decode_init(AVCodecContext *avctx){ MJpegDecodeContext *s = avctx->priv_data; MpegEncContext s2; s->avctx = avctx; /* ugly way to get the idct & scantable */ 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.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); 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) { printf("mjpeg: using external huffman table\n"); init_get_bits(&s->gb, avctx->extradata, avctx->extradata_size); 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); } 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 bits_table[17]; UINT8 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); build_vlc(&s->vlcs[class][index], bits_table, val_table, code_max + 1); } return 0;}static int mjpeg_decode_sof0(MJpegDecodeContext *s){ int len, nb_components, i, width, height; /* XXX: verify len field validity */ len = get_bits(&s->gb, 16); /* only 8 bits/component accepted */ if (get_bits(&s->gb, 8) != 8) 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -