📄 mjpeg.c
字号:
/* 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"); } 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 **pbuf_ptr, UINT8 *buf_end){ UINT8 *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)) { 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 *buf, int buf_size){ MJpegDecodeContext *s = avctx->priv_data; UINT8 *buf_end, *buf_ptr; int i, start_code; AVPicture *picture = data; *data_size = 0; /* no supplementary picture */ if (buf_size == 0) return 0; 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); dprintf("buffer too small, expanding to %d bytes\n", s->buffer_size); } /* unescape buffer of SOS */ if (start_code == SOS) { UINT8 *src = buf_ptr; UINT8 *dst = s->buffer; while (src<buf_end) { UINT8 x = *(src++); *(dst++) = x; if (x == 0xff) { while(*src == 0xff) src++; x = *(src++); if (x >= 0xd0 && x <= 0xd7) *(dst++) = x; else if (x) break; } } init_get_bits(&s->gb, s->buffer, dst - s->buffer); 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); s->start_code = start_code; /* process markers */ if (start_code >= 0xd0 && start_code <= 0xd7) { dprintf("restart marker: %d\n", start_code&0x0f); } else if (s->first_picture) { /* APP fields */ if (start_code >= 0xe0 && start_code <= 0xef) mjpeg_decode_app(s); /* Comment */ else if (start_code == COM) mjpeg_decode_com(s); } switch(start_code) { case SOI: s->restart_interval = 0; /* nothing to do on SOI */ break; case DQT: mjpeg_decode_dqt(s); break; case DHT: mjpeg_decode_dht(s); break; case SOF0: mjpeg_decode_sof0(s); break; case EOI:eoi_parser: { int l; if (s->interlaced) { s->bottom_field ^= 1; /* if not bottom field, do not output image yet */ if (s->bottom_field) goto not_the_end; } for(i=0;i<3;i++) { picture->data[i] = s->current_picture[i];#if 1 l = s->linesize[i]; if (s->interlaced) l >>= 1; picture->linesize[i] = l;#else picture->linesize[i] = (s->interlaced) ? s->linesize[i] >> 1 : s->linesize[i];#endif } *data_size = sizeof(AVPicture); avctx->height = s->height; if (s->interlaced) avctx->height *= 2; avctx->width = s->width; /* XXX: not complete test ! */ switch((s->h_count[0] << 4) | s->v_count[0]) { case 0x11: avctx->pix_fmt = PIX_FMT_YUV444P; break; case 0x21: avctx->pix_fmt = PIX_FMT_YUV422P; break; default: case 0x22: avctx->pix_fmt = PIX_FMT_YUV420P; break; } /* dummy quality */ /* XXX: infer it with matrix */ avctx->quality = 3; 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 SOF3: case SOF5: case SOF6: case SOF7: case SOF9: case SOF10: case SOF11: case SOF13: case SOF14: case SOF15: case JPG: printf("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 *buf, int buf_size){ MJpegDecodeContext *s = avctx->priv_data; UINT8 *buf_end, *buf_ptr; int i; AVPicture *picture = data; GetBitContext hgb; /* for the header */ uint32_t dqt_offs, dht_offs, sof_offs, sos_offs, second_field_offs; uint32_t field_size; *data_size = 0; /* no supplementary picture */ if (buf_size == 0) return 0; buf_ptr = buf; buf_end = buf + buf_size; read_header: /* reset on every SOI */ s->restart_interval = 0; init_get_bits(&hgb, buf_ptr, /*buf_size*/buf_end - buf_ptr); skip_bits(&hgb, 32); /* reserved zeros */ if (get_bits(&hgb, 32) != be2me_32(ff_get_fourcc("mjpg"))) { dprintf("not mjpeg-b (bad fourcc)\n"); return 0; } field_size = get_bits(&hgb, 32); /* field size */ dprintf("field size: 0x%x\n", field_size); skip_bits(&hgb, 32); /* padded field size */ second_field_offs = get_bits(&hgb, 32); dprintf("second field offs: 0x%x\n", second_field_offs); if (second_field_offs) s->interlaced = 1; dqt_offs = get_bits(&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)); s->start_code = DQT; mjpeg_decode_dqt(s); } dht_offs = get_bits(&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)); s->start_code = DHT; mjpeg_decode_dht(s); } sof_offs = get_bits(&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)); s->start_code = SOF0; mjpeg_decode_sof0(s); } sos_offs = get_bits(&hgb, 32); dprintf("sos offs: 0x%x\n", sos_offs); if (sos_offs) {// init_get_bits(&s->gb, buf+sos_offs, buf_end - (buf+sos_offs)); init_get_bits(&s->gb, buf+sos_offs, field_size); s->start_code = SOS; mjpeg_decode_sos(s); } skip_bits(&hgb, 32); /* start of data offset */ 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; } } for(i=0;i<3;i++) { picture->data[i] = s->current_picture[i]; picture->linesize[i] = (s->interlaced) ? s->linesize[i] >> 1 : s->linesize[i]; } *data_size = sizeof(AVPicture); avctx->height = s->height; if (s->interlaced) avctx->height *= 2; avctx->width = s->width; /* XXX: not complete test ! */ switch((s->h_count[0] << 4) | s->v_count[0]) { case 0x11: avctx->pix_fmt = PIX_FMT_YUV444P; break; case 0x21: avctx->pix_fmt = PIX_FMT_YUV422P; break; default: case 0x22: avctx->pix_fmt = PIX_FMT_YUV420P; break; } /* dummy quality */ /* XXX: infer it with matrix */ avctx->quality = 3; return buf_ptr - buf;}static int mjpeg_decode_end(AVCodecContext *avctx){ MJpegDecodeContext *s = avctx->priv_data; int i, j; av_free(s->buffer); for(i=0;i<MAX_COMPONENTS;i++) av_free(s->current_picture[i]); for(i=0;i<2;i++) { for(j=0;j<4;j++) free_vlc(&s->vlcs[i][j]); } return 0;}AVCodec mjpeg_decoder = { "mjpeg", CODEC_TYPE_VIDEO, CODEC_ID_MJPEG, sizeof(MJpegDecodeContext), mjpeg_decode_init, NULL, mjpeg_decode_end, mjpeg_decode_frame, 0, NULL};AVCodec mjpegb_decoder = { "mjpegb", CODEC_TYPE_VIDEO, CODEC_ID_MJPEGB, sizeof(MJpegDecodeContext), mjpeg_decode_init, NULL, mjpeg_decode_end, mjpegb_decode_frame, 0, NULL};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -