diff options
Diffstat (limited to 'src/libffmpeg/libavcodec/mjpeg.c')
-rw-r--r-- | src/libffmpeg/libavcodec/mjpeg.c | 201 |
1 files changed, 151 insertions, 50 deletions
diff --git a/src/libffmpeg/libavcodec/mjpeg.c b/src/libffmpeg/libavcodec/mjpeg.c index 4e2305aef..4c2b4793b 100644 --- a/src/libffmpeg/libavcodec/mjpeg.c +++ b/src/libffmpeg/libavcodec/mjpeg.c @@ -1,6 +1,8 @@ /* * MJPEG encoder and decoder * Copyright (c) 2000, 2001 Fabrice Bellard. + * Copyright (c) 2003 Alex Beregszaszi + * Copyright (c) 2003-2004 Michael Niedermayer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -398,6 +400,19 @@ static void jpeg_put_comments(MpegEncContext *s) ptr[0] = size >> 8; ptr[1] = size; } + + if( s->avctx->pix_fmt == PIX_FMT_YUV420P + ||s->avctx->pix_fmt == PIX_FMT_YUV422P + ||s->avctx->pix_fmt == PIX_FMT_YUV444P){ + put_marker(p, COM); + flush_put_bits(p); + ptr = pbBufPtr(p); + put_bits(p, 16, 0); /* patched later */ + put_string(p, "CS=ITU601", 1); + size = strlen("CS=ITU601")+3; + ptr[0] = size >> 8; + ptr[1] = size; + } } void mjpeg_picture_header(MpegEncContext *s) @@ -657,11 +672,11 @@ static int encode_picture_lossless(AVCodecContext *avctx, unsigned char *buf, in mjpeg_picture_header(s); s->header_bits= put_bits_count(&s->pb); - + if(avctx->pix_fmt == PIX_FMT_RGBA32){ int x, y, i; const int linesize= p->linesize[0]; - uint16_t buffer[2048][4]; + uint16_t (*buffer)[4]= (void *) s->rd_scratchpad; int left[3], top[3], topleft[3]; for(i=0; i<3; i++){ @@ -672,6 +687,11 @@ static int encode_picture_lossless(AVCodecContext *avctx, unsigned char *buf, in const int modified_predictor= y ? predictor : 1; uint8_t *ptr = p->data[0] + (linesize * y); + if(s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb)>>3) < width*3*4){ + av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); + return -1; + } + for(i=0; i<3; i++){ top[i]= left[i]= topleft[i]= buffer[0][i]; } @@ -705,6 +725,10 @@ static int encode_picture_lossless(AVCodecContext *avctx, unsigned char *buf, in const int mb_height = (height + s->mjpeg_vsample[0] - 1) / s->mjpeg_vsample[0]; for(mb_y = 0; mb_y < mb_height; mb_y++) { + if(s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb)>>3) < mb_width * 4 * 3 * s->mjpeg_hsample[0] * s->mjpeg_vsample[0]){ + av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); + return -1; + } for(mb_x = 0; mb_x < mb_width; mb_x++) { if(mb_x==0 || mb_y==0){ for(i=0;i<3;i++) { @@ -825,7 +849,7 @@ typedef struct MJpegDecodeContext { 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 - uint8_t *qscale_table; + int8_t *qscale_table; DCTELEM block[64] __align8; ScanTable scantable; void (*idct_put)(uint8_t *dest/*align 8*/, int line_size, DCTELEM *block/*align 16*/); @@ -834,13 +858,16 @@ typedef struct MJpegDecodeContext { int restart_count; int buggy_avid; + int cs_itu601; int interlace_polarity; + + int mjpb_skiptosod; } 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 nb_codes, int use_static) { uint8_t huff_size[256]; uint16_t huff_code[256]; @@ -848,7 +875,7 @@ static int build_vlc(VLC *vlc, const uint8_t *bits_table, const uint8_t *val_tab 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); + return init_vlc(vlc, 9, nb_codes, huff_size, 1, 1, huff_code, 2, 2, use_static); } static int mjpeg_decode_init(AVCodecContext *avctx) @@ -876,12 +903,12 @@ static int mjpeg_decode_init(AVCodecContext *avctx) return -1; s->start_code = -1; s->first_picture = 1; - s->org_height = avctx->height; + s->org_height = avctx->coded_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); + 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) { @@ -894,6 +921,69 @@ static int mjpeg_decode_init(AVCodecContext *avctx) 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) { @@ -969,7 +1059,7 @@ static int mjpeg_decode_dht(MJpegDecodeContext *s) 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){ + if(build_vlc(&s->vlcs[class][index], bits_table, val_table, code_max + 1, 0) < 0){ return -1; } } @@ -993,7 +1083,10 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s) } 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 || @@ -1028,8 +1121,7 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s) s->width = width; s->height = height; - s->avctx->width = s->width; - s->avctx->height = s->height; + avcodec_set_dimensions(s->avctx, width, height); /* test interlaced mode */ if (s->first_picture && @@ -1055,16 +1147,16 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s) if(s->rgb){ s->avctx->pix_fmt = PIX_FMT_RGBA32; }else if(s->nb_components==3) - s->avctx->pix_fmt = PIX_FMT_YUV444P; + 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 = PIX_FMT_YUV422P; + s->avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV422P : PIX_FMT_YUVJ422P; break; default: case 0x22: - s->avctx->pix_fmt = PIX_FMT_YUV420P; + s->avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV420P : PIX_FMT_YUVJ420P; break; } @@ -1162,11 +1254,14 @@ static int decode_block(MJpegDecodeContext *s, DCTELEM *block, static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int predictor, int point_transform){ int i, mb_x, mb_y; - uint16_t buffer[2048][4]; + uint16_t buffer[32768][4]; int left[3], top[3], topleft[3]; const int linesize= s->linesize[0]; const int mask= (1<<s->bits)-1; + if((unsigned)s->mb_width > 32768) //dynamic alloc + return -1; + for(i=0; i<3; i++){ buffer[0][i]= 1 << (s->bits + point_transform - 1); } @@ -1336,8 +1431,8 @@ static int mjpeg_decode_scan(MJpegDecodeContext *s){ } // dprintf("mb: %d %d processed\n", mb_y, mb_x); ptr = s->picture.data[c] + - (s->linesize[c] * (v * mb_y + y) * 8) + - (h * mb_x + x) * 8; + (((s->linesize[c] * (v * mb_y + y) * 8) + + (h * mb_x + x) * 8) >> s->avctx->lowres); if (s->interlaced && s->bottom_field) ptr += s->linesize[c] >> 1; //av_log(NULL, AV_LOG_DEBUG, "%d %d %d %d %d %d %d %d \n", mb_x, mb_y, x, y, c, s->bottom_field, (v * mb_y + y) * 8, (h * mb_x + x) * 8); @@ -1453,6 +1548,10 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s) if(s->avctx->debug & FF_DEBUG_PICT_INFO) av_log(s->avctx, AV_LOG_DEBUG, "%s %s p:%d >>:%d\n", s->lossless ? "lossless" : "sequencial DCT", s->rgb ? "RGB" : "", predictor, point_transform); + /* mjpeg-b can have padding bytes between sos and image data, skip them */ + for (i = s->mjpb_skiptosod; i > 0; i--) + skip_bits(&s->gb, 8); + if(s->lossless){ if(s->rgb){ if(ljpeg_decode_rgb_scan(s, predictor, point_transform) < 0) @@ -1652,6 +1751,9 @@ static int mjpeg_decode_com(MJpegDecodeContext *s) // if (s->first_picture) // printf("mjpeg: workarounding buggy AVID\n"); } + else if(!strcmp(cbuf, "CS=ITU601")){ + s->cs_itu601= 1; + } av_free(cbuf); } @@ -1724,10 +1826,6 @@ static int mjpeg_decode_frame(AVCodecContext *avctx, int start_code; AVFrame *picture = data; - /* no supplementary picture */ - if (buf_size == 0) - return 0; - buf_ptr = buf; buf_end = buf + buf_size; while (buf_ptr < buf_end) { @@ -1762,9 +1860,9 @@ static int mjpeg_decode_frame(AVCodecContext *avctx, *(dst++) = x; if (x == 0xff) { - while(*src == 0xff) src++; + while(src<buf_end && x == 0xff) + x = *(src++); - x = *(src++); if (x >= 0xd0 && x <= 0xd7) *(dst++) = x; else if (x) @@ -1898,11 +1996,7 @@ static int mjpegb_decode_frame(AVCodecContext *avctx, 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; - - /* no supplementary picture */ - if (buf_size == 0) - return 0; + uint32_t field_size, sod_offs; buf_ptr = buf; buf_end = buf + buf_size; @@ -1910,26 +2004,27 @@ static int mjpegb_decode_frame(AVCodecContext *avctx, read_header: /* reset on every SOI */ s->restart_interval = 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(&hgb, 32) != be2me_32(ff_get_fourcc("mjpg"))) + 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(&hgb, 32); /* field size */ + 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(&hgb, 32); + 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(&hgb, 32); + dqt_offs = get_bits_long(&hgb, 32); dprintf("dqt offs: 0x%x\n", dqt_offs); if (dqt_offs) { @@ -1938,7 +2033,7 @@ read_header: mjpeg_decode_dqt(s); } - dht_offs = get_bits(&hgb, 32); + dht_offs = get_bits_long(&hgb, 32); dprintf("dht offs: 0x%x\n", dht_offs); if (dht_offs) { @@ -1947,7 +2042,7 @@ read_header: mjpeg_decode_dht(s); } - sof_offs = get_bits(&hgb, 32); + sof_offs = get_bits_long(&hgb, 32); dprintf("sof offs: 0x%x\n", sof_offs); if (sof_offs) { @@ -1957,18 +2052,19 @@ read_header: return -1; } - sos_offs = get_bits(&hgb, 32); + 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); } - skip_bits(&hgb, 32); /* start of data offset */ - if (s->interlaced) { s->bottom_field ^= 1; /* if not bottom field, do not output image yet */ @@ -2011,10 +2107,6 @@ static int sp5x_decode_frame(AVCodecContext *avctx, uint8_t *buf_ptr, *buf_end, *recoded; int i = 0, j = 0; - /* no supplementary picture */ - if (buf_size == 0) - return 0; - if (!avctx->width || !avctx->height) return -1; @@ -2039,10 +2131,10 @@ static int sp5x_decode_frame(AVCodecContext *avctx, j += sizeof(sp5x_data_dht); memcpy(recoded+j, &sp5x_data_sof[0], sizeof(sp5x_data_sof)); - recoded[j+5] = (avctx->height >> 8) & 0xFF; - recoded[j+6] = avctx->height & 0xFF; - recoded[j+7] = (avctx->width >> 8) & 0xFF; - recoded[j+8] = avctx->width & 0xFF; + recoded[j+5] = (avctx->coded_height >> 8) & 0xFF; + recoded[j+6] = avctx->coded_height & 0xFF; + recoded[j+7] = (avctx->coded_width >> 8) & 0xFF; + recoded[j+8] = avctx->coded_width & 0xFF; j += sizeof(sp5x_data_sof); memcpy(recoded+j, &sp5x_data_sos[0], sizeof(sp5x_data_sos)); @@ -2066,8 +2158,8 @@ static int sp5x_decode_frame(AVCodecContext *avctx, #else /* SOF */ s->bits = 8; - s->width = avctx->width; - s->height = avctx->height; + s->width = avctx->coded_width; + s->height = avctx->coded_height; s->nb_components = 3; s->component_id[0] = 0; s->h_count[0] = 2; @@ -2085,7 +2177,7 @@ static int sp5x_decode_frame(AVCodecContext *avctx, s->v_max = 2; s->qscale_table = av_mallocz((s->width+15)/16); - avctx->pix_fmt = PIX_FMT_YUV420P; + avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV420P : PIX_FMT_YUVJ420; s->interlaced = 0; s->picture.reference = 0; @@ -2223,3 +2315,12 @@ AVCodec ljpeg_encoder = { //FIXME avoid MPV_* lossless jpeg shouldnt need them MPV_encode_end, }; #endif + +AVCodecParser mjpeg_parser = { + { CODEC_ID_MJPEG }, + sizeof(ParseContext), + NULL, + jpeg_parse, + ff_parse_close, +}; + |