📄 mjpeg.c
字号:
skip_bits(&s->gb, 16); /* unknwon always 0? */ skip_bits(&s->gb, 16); /* unknwon always 0? */ switch( get_bits(&s->gb, 8)){ case 1: s->rgb= 1; s->pegasus_rct=0; break; case 2: s->rgb= 1; s->pegasus_rct=1; break; default: av_log(s->avctx, AV_LOG_ERROR, "unknown colorspace\n"); } len -= 9; goto out; } /* 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); len -= 4; if (id == ff_get_fourcc("mjpg")) /* Apple MJPEG-A */ {#if 0 skip_bits(&s->gb, 32); /* field size */ skip_bits(&s->gb, 32); /* pad field size */ skip_bits(&s->gb, 32); /* next off */ skip_bits(&s->gb, 32); /* quant off */ skip_bits(&s->gb, 32); /* huff off */ skip_bits(&s->gb, 32); /* image off */ skip_bits(&s->gb, 32); /* scan off */ skip_bits(&s->gb, 32); /* data off */#endif if (s->avctx->debug & FF_DEBUG_PICT_INFO) av_log(s->avctx, AV_LOG_INFO, "mjpeg: Apple MJPEG-A header found\n"); } }out: /* slow but needed for extreme adobe jpegs */ if (len < 0) av_log(s->avctx, AV_LOG_ERROR, "mjpeg: error, decode_app parser read over the end\n"); while(--len > 0) skip_bits(&s->gb, 8); return 0;}static int mjpeg_decode_com(MJpegDecodeContext *s){ int len = get_bits(&s->gb, 16); if (len >= 2 && 8*len - 16 + get_bits_count(&s->gb) <= s->gb.size_in_bits) { uint8_t *cbuf = av_malloc(len - 1); if (cbuf) { int i; for (i = 0; i < len - 2; i++) cbuf[i] = get_bits(&s->gb, 8); if (i > 0 && cbuf[i-1] == '\n') cbuf[i-1] = 0; else cbuf[i] = 0; if(s->avctx->debug & FF_DEBUG_PICT_INFO) av_log(s->avctx, AV_LOG_INFO, "mjpeg comment: '%s'\n", cbuf); /* buggy avid, it puts EOI only at every 10th frame */ if (!strcmp(cbuf, "AVID")) { s->buggy_avid = 1; // if (s->first_picture) // printf("mjpeg: workarounding buggy AVID\n"); } else if(!strcmp(cbuf, "CS=ITU601")){ s->cs_itu601= 1; } av_free(cbuf); } } return 0;}#if 0static 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){ uint8_t *buf_ptr; unsigned int v, v2; int val;#ifdef DEBUG int skipped=0;#endif buf_ptr = *pbuf_ptr; while (buf_ptr < buf_end) { v = *buf_ptr++; v2 = *buf_ptr; if ((v == 0xff) && (v2 >= 0xc0) && (v2 <= 0xfe) && buf_ptr < buf_end) { val = *buf_ptr++; goto found; }#ifdef DEBUG skipped++;#endif } val = -1;found:#ifdef DEBUG dprintf("find_marker skipped %d bytes\n", skipped);#endif *pbuf_ptr = buf_ptr; return val;}static int mjpeg_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; 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 { dprintf("marker=%x avail_size_in_buf=%d\n", start_code, buf_end - buf_ptr); if ((buf_end - buf_ptr) > s->buffer_size) { av_free(s->buffer); s->buffer_size = buf_end-buf_ptr; s->buffer = av_malloc(s->buffer_size + FF_INPUT_BUFFER_PADDING_SIZE); dprintf("buffer too small, expanding to %d bytes\n", s->buffer_size); } /* unescape buffer of SOS */ if (start_code == SOS) { uint8_t *src = buf_ptr; uint8_t *dst = s->buffer; while (src<buf_end) { uint8_t x = *(src++); *(dst++) = x; if (x == 0xff) { while(src<buf_end && x == 0xff) x = *(src++); if (x >= 0xd0 && x <= 0xd7) *(dst++) = x; else if (x) break; } } init_get_bits(&s->gb, s->buffer, (dst - s->buffer)*8); dprintf("escaping removed %d bytes\n", (buf_end - buf_ptr) - (dst - s->buffer)); } else init_get_bits(&s->gb, buf_ptr, (buf_end - buf_ptr)*8); s->start_code = start_code; if(s->avctx->debug & FF_DEBUG_STARTCODE){ av_log(s->avctx, AV_LOG_DEBUG, "startcode: %X\n", start_code); } /* process markers */ if (start_code >= 0xd0 && start_code <= 0xd7) { dprintf("restart marker: %d\n", start_code&0x0f); /* APP fields */ } else if (start_code >= APP0 && start_code <= APP15) { mjpeg_decode_app(s); /* Comment */ } else if (start_code == COM){ mjpeg_decode_com(s); } switch(start_code) { case SOI: s->restart_interval = 0; s->restart_count = 0; /* nothing to do on SOI */ break; case DQT: mjpeg_decode_dqt(s); break; case DHT: if(mjpeg_decode_dht(s) < 0){ av_log(s->avctx, AV_LOG_ERROR, "huffman table decode error\n"); return -1; } break; case SOF0: s->lossless=0; if (mjpeg_decode_sof(s) < 0) return -1; break; case SOF3: s->lossless=1; if (mjpeg_decode_sof(s) < 0) return -1; break; case EOI: 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) 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(s->avctx, AV_LOG_DEBUG, "QP: %d\n", picture->quality); picture->quality*= FF_QP2LAMBDA; } goto the_end; } break; case SOS: 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) goto eoi_parser; break; case DRI: mjpeg_decode_dri(s); break; case SOF1: case SOF2: case SOF5: case SOF6: case SOF7: case SOF9: case SOF10: case SOF11: case SOF13: case SOF14: case SOF15: case JPG: av_log(s->avctx, AV_LOG_ERROR, "mjpeg: unsupported coding type (%x)\n", start_code); break;// default:// printf("mjpeg: unsupported marker (%x)\n", start_code);// break; }not_the_end: /* eof process start code */ buf_ptr += (get_bits_count(&s->gb)+7)/8; dprintf("marker parser used %d bytes (%d bits)\n", (get_bits_count(&s->gb)+7)/8, get_bits_count(&s->gb)); } } }the_end: dprintf("mjpeg decode frame unused %d 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) != be2me_32(ff_get_fourcc("mjpg"))) { dprintf("not mjpeg-b (bad fourcc)\n"); return 0; } field_size = get_bits_long(&hgb, 32); /* field size */ dprintf("field size: 0x%x\n", field_size); skip_bits(&hgb, 32); /* padded field size */ second_field_offs = get_bits_long(&hgb, 32); dprintf("second field offs: 0x%x\n", second_field_offs); if (second_field_offs) s->interlaced = 1; dqt_offs = get_bits_long(&hgb, 32); dprintf("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); dprintf("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); dprintf("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); dprintf("sos offs: 0x%x\n", sos_offs); sod_offs = get_bits_long(&hgb, 32); dprintf("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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -