X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fmjpeg.c;h=292cd7d0fea44751369713bfd89f5e562f6dcb60;hb=6b72ac6323ec656fd0df6460ef844c83b5e76433;hp=d1d01273124e46120454bc37b0ab3e68287fd3a3;hpb=723106b279d9d78f5966f32bedfa33b88a702f69;p=ffmpeg diff --git a/libavcodec/mjpeg.c b/libavcodec/mjpeg.c index d1d01273124..292cd7d0fea 100644 --- a/libavcodec/mjpeg.c +++ b/libavcodec/mjpeg.c @@ -1,38 +1,31 @@ /* * MJPEG encoder and decoder - * Copyright (c) 2000, 2001 Gerard Lantau. + * Copyright (c) 2000, 2001 Fabrice Bellard. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. * - * This program is distributed in the hope that it will be useful, + * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * Support for external huffman table and various fixes (AVID workaround) by - * Alex Beregszaszi + * Support for external huffman table, various fixes (AVID workaround), + * aspecting and new decode_frame mechanism + * by Alex Beregszaszi */ //#define DEBUG #include "avcodec.h" #include "dsputil.h" #include "mpegvideo.h" -#include "common.h" -#include -#include - -#ifdef USE_FASTMEMCPY -#include "fastmemcpy.h" -#endif - -/* use two quantizer table (one for luminance and one for chrominance) */ +/* use two quantizer tables (one for luminance and one for chrominance) */ /* not yet working */ #undef TWOMATRIXES @@ -246,7 +239,7 @@ int mjpeg_init(MpegEncContext *s) { MJpegContext *m; - m = malloc(sizeof(MJpegContext)); + m = av_malloc(sizeof(MJpegContext)); if (!m) return -1; @@ -278,7 +271,7 @@ int mjpeg_init(MpegEncContext *s) void mjpeg_close(MpegEncContext *s) { - free(s->mjpeg_ctx); + av_free(s->mjpeg_ctx); } static inline void put_marker(PutBitContext *p, int code) @@ -325,14 +318,14 @@ static void jpeg_table_header(MpegEncContext *s) put_bits(p, 4, 0); /* 8 bit precision */ put_bits(p, 4, 0); /* table 0 */ for(i=0;i<64;i++) { - j = zigzag_direct[i]; + j = s->intra_scantable.permutated[i]; put_bits(p, 8, s->intra_matrix[j]); } #ifdef TWOMATRIXES put_bits(p, 4, 0); /* 8 bit precision */ put_bits(p, 4, 1); /* table 1 */ for(i=0;i<64;i++) { - j = zigzag_direct[i]; + j = s->intra_scantable.permutated[i]; put_bits(p, 8, s->chroma_intra_matrix[j]); } #endif @@ -358,36 +351,61 @@ static void jpeg_put_comments(MpegEncContext *s) int size; UINT8 *ptr; -#if 0 + if (s->aspect_ratio_info) + { /* JFIF header */ put_marker(p, APP0); put_bits(p, 16, 16); put_string(p, "JFIF"); /* this puts the trailing zero-byte too */ - put_bits(p, 16, 0x101); + put_bits(p, 16, 0x0201); /* v 1.02 */ put_bits(p, 8, 0); /* units type: 0 - aspect ratio */ - put_bits(p, 16, 1); /* aspect: 1:1 */ - put_bits(p, 16, 1); + switch(s->aspect_ratio_info) + { + case FF_ASPECT_4_3_625: + case FF_ASPECT_4_3_525: + put_bits(p, 16, 4); + put_bits(p, 16, 3); + break; + case FF_ASPECT_16_9_625: + case FF_ASPECT_16_9_525: + put_bits(p, 16, 16); + put_bits(p, 16, 9); + break; + case FF_ASPECT_EXTENDED: + put_bits(p, 16, s->aspected_width); + put_bits(p, 16, s->aspected_height); + break; + case FF_ASPECT_SQUARE: + default: + put_bits(p, 16, 1); /* aspect: 1:1 */ + put_bits(p, 16, 1); + break; + } put_bits(p, 8, 0); /* thumbnail width */ put_bits(p, 8, 0); /* thumbnail height */ -#endif + } /* comment */ - put_marker(p, COM); - flush_put_bits(p); - ptr = pbBufPtr(p); - put_bits(p, 16, 0); /* patched later */ -#define VERSION "FFmpeg" LIBAVCODEC_VERSION "b" LIBAVCODEC_BUILD_STR - put_string(p, VERSION); - size = strlen(VERSION)+3; -#undef VERSION - ptr[0] = size >> 8; - ptr[1] = size; + if(!ff_bit_exact){ + put_marker(p, COM); + flush_put_bits(p); + ptr = pbBufPtr(p); + put_bits(p, 16, 0); /* patched later */ +#define MJPEG_VERSION "FFmpeg" LIBAVCODEC_VERSION "b" LIBAVCODEC_BUILD_STR + put_string(p, MJPEG_VERSION); + size = strlen(MJPEG_VERSION)+3; +#undef MJPEG_VERSION + ptr[0] = size >> 8; + ptr[1] = size; + } } void mjpeg_picture_header(MpegEncContext *s) { put_marker(&s->pb, SOI); + if (!s->mjpeg_data_only_frames) + { jpeg_put_comments(s); if (s->mjpeg_write_tables) jpeg_table_header(s); @@ -425,6 +443,7 @@ void mjpeg_picture_header(MpegEncContext *s) #else put_bits(&s->pb, 8, 0); /* select matrix */ #endif + } /* scan header */ put_marker(&s->pb, SOS); @@ -457,8 +476,8 @@ void mjpeg_picture_trailer(MpegEncContext *s) put_marker(&s->pb, EOI); } -static inline void encode_dc(MpegEncContext *s, int val, - UINT8 *huff_size, UINT16 *huff_code) +static inline void mjpeg_encode_dc(MpegEncContext *s, int val, + UINT8 *huff_size, UINT16 *huff_code) { int mant, nbits; @@ -497,11 +516,11 @@ static void encode_block(MpegEncContext *s, DCTELEM *block, int n) dc = block[0]; /* overflow is impossible */ val = dc - s->last_dc[component]; if (n < 4) { - encode_dc(s, val, m->huff_size_dc_luminance, m->huff_code_dc_luminance); + 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 { - encode_dc(s, val, m->huff_size_dc_chrominance, m->huff_code_dc_chrominance); + 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; } @@ -512,7 +531,7 @@ static void encode_block(MpegEncContext *s, DCTELEM *block, int n) run = 0; last_index = s->block_last_index[n]; for(i=1;i<=last_index;i++) { - j = zigzag_direct[i]; + j = s->intra_scantable.permutated[i]; val = block[j]; if (val == 0) { run++; @@ -559,19 +578,17 @@ void mjpeg_encode_mb(MpegEncContext *s, /******************************************/ /* decoding */ -/* compressed picture size */ -#define PICTURE_BUFFER_SIZE 100000 - #define MAX_COMPONENTS 4 typedef struct MJpegDecodeContext { AVCodecContext *avctx; GetBitContext gb; - UINT32 header_state; + int mpeg_enc_ctx_allocated; /* true if decoding context allocated */ + int start_code; /* current start code */ - UINT8 *buf_ptr; int buffer_size; - int mpeg_enc_ctx_allocated; /* true if decoding context allocated */ + UINT8 *buffer; + INT16 quant_matrixes[4][64]; VLC vlcs[2][4]; @@ -591,19 +608,16 @@ typedef struct MJpegDecodeContext { UINT8 *current_picture[MAX_COMPONENTS]; /* picture structure */ int linesize[MAX_COMPONENTS]; DCTELEM block[64] __align8; - UINT8 buffer[PICTURE_BUFFER_SIZE]; int buggy_avid; int restart_interval; int restart_count; - int interleaved_rows; + int interlace_polarity; + ScanTable scantable; + void (*idct_put)(UINT8 *dest/*align 8*/, int line_size, DCTELEM *block/*align 16*/); } MJpegDecodeContext; -#define SKIP_REMAINING(gb, len) { \ - dprintf("reamining %d bytes in marker\n", len); \ - if (len) while (--len) \ - skip_bits(gb, 8); \ -} +static int mjpeg_decode_dht(MJpegDecodeContext *s); static void build_vlc(VLC *vlc, const UINT8 *bits_table, const UINT8 *val_table, int nb_codes) @@ -620,39 +634,52 @@ static void build_vlc(VLC *vlc, const UINT8 *bits_table, const UINT8 *val_table, static int mjpeg_decode_init(AVCodecContext *avctx) { MJpegDecodeContext *s = avctx->priv_data; + MpegEncContext s2; s->avctx = avctx; - s->header_state = 0; + /* 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 = PICTURE_BUFFER_SIZE - 1; /* minus 1 to take into - account FF 00 case */ + 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->buf_ptr = s->buffer; 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"); - mjpeg_decode_dht(s, avctx->extradata, avctx->extradata_size); + 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, - UINT8 *buf, int buf_size) +static int mjpeg_decode_dqt(MJpegDecodeContext *s) { int len, index, i, j; - init_get_bits(&s->gb, buf, buf_size); len = get_bits(&s->gb, 16) - 2; @@ -669,29 +696,23 @@ static int mjpeg_decode_dqt(MJpegDecodeContext *s, dprintf("index=%d\n", index); /* read quant table */ for(i=0;i<64;i++) { - j = zigzag_direct[i]; + j = s->scantable.permutated[i]; s->quant_matrixes[index][j] = get_bits(&s->gb, 8); } len -= 65; } - SKIP_REMAINING(&s->gb, len); - return 0; } /* decode huffman tables and build VLC decoders */ -static int mjpeg_decode_dht(MJpegDecodeContext *s, - UINT8 *buf, int buf_size) +static int mjpeg_decode_dht(MJpegDecodeContext *s) { int len, index, i, class, n, v, code_max; UINT8 bits_table[17]; UINT8 val_table[256]; - init_get_bits(&s->gb, buf, buf_size); - - len = get_bits(&s->gb, 16); - len -= 2; + len = get_bits(&s->gb, 16) - 2; while (len > 0) { if (len < 17) @@ -729,13 +750,10 @@ static int mjpeg_decode_dht(MJpegDecodeContext *s, return 0; } -static int mjpeg_decode_sof0(MJpegDecodeContext *s, - UINT8 *buf, int buf_size) +static int mjpeg_decode_sof0(MJpegDecodeContext *s) { int len, nb_components, i, width, height; - init_get_bits(&s->gb, buf, buf_size); - /* XXX: verify len field validity */ len = get_bits(&s->gb, 16); /* only 8 bits/component accepted */ @@ -772,10 +790,8 @@ static int mjpeg_decode_sof0(MJpegDecodeContext *s, /* if different size, realloc/alloc picture */ /* XXX: also check h_count and v_count */ if (width != s->width || height != s->height) { - for(i=0;icurrent_picture[i]); - s->current_picture[i] = NULL; - } + for(i=0;icurrent_picture[i]); s->width = width; s->height = height; /* test interlaced mode */ @@ -783,6 +799,7 @@ static int mjpeg_decode_sof0(MJpegDecodeContext *s, 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; } @@ -809,15 +826,18 @@ static int mjpeg_decode_sof0(MJpegDecodeContext *s, return 0; } -static inline int decode_dc(MJpegDecodeContext *s, int dc_index) +static inline int mjpeg_decode_dc(MJpegDecodeContext *s, int dc_index) { int code, diff; - +#if 1 + code = get_vlc2(&s->gb, s->vlcs[0][dc_index].table, 9, 2); +#else code = get_vlc(&s->gb, &s->vlcs[0][dc_index]); +#endif if (code < 0) { - dprintf("decode_dc: bad vlc: %d:%d (%x)\n", 0, dc_index, - &s->vlcs[0][dc_index]); + dprintf("mjpeg_decode_dc: bad vlc: %d:%d (%p)\n", 0, dc_index, + &s->vlcs[0][dc_index]); return 0xffff; } if (code == 0) { @@ -840,7 +860,7 @@ static int decode_block(MJpegDecodeContext *s, DCTELEM *block, INT16 *quant_matrix; /* DC coef */ - val = decode_dc(s, dc_index); + val = mjpeg_decode_dc(s, dc_index); if (val == 0xffff) { dprintf("error dc\n"); return -1; @@ -853,7 +873,11 @@ static int decode_block(MJpegDecodeContext *s, DCTELEM *block, ac_vlc = &s->vlcs[1][ac_index]; i = 1; for(;;) { +#if 1 + code = get_vlc2(&s->gb, s->vlcs[1][ac_index].table, 9, 2); +#else code = get_vlc(&s->gb, ac_vlc); +#endif if (code < 0) { dprintf("error ac\n"); return -1; @@ -874,7 +898,7 @@ static int decode_block(MJpegDecodeContext *s, DCTELEM *block, dprintf("error count: %d\n", i); return -1; } - j = zigzag_direct[i]; + j = s->scantable.permutated[i]; block[j] = level * quant_matrix[j]; i++; if (i >= 64) @@ -884,8 +908,7 @@ static int decode_block(MJpegDecodeContext *s, DCTELEM *block, return 0; } -static int mjpeg_decode_sos(MJpegDecodeContext *s, - UINT8 *buf, int buf_size) +static int mjpeg_decode_sos(MJpegDecodeContext *s) { int len, nb_components, i, j, n, h, v, ret; int mb_width, mb_height, mb_x, mb_y, vmax, hmax, index, id; @@ -896,10 +919,14 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s, int h_count[4]; int v_count[4]; - init_get_bits(&s->gb, buf, buf_size); /* XXX: verify len field validity */ len = get_bits(&s->gb, 16); nb_components = get_bits(&s->gb, 8); + if (len != 6+2*nb_components) + { + dprintf("decode_sos: invalid len (%d)\n", len); + return -1; + } /* XXX: only interleaved scan accepted */ if (nb_components != 3) { @@ -988,24 +1015,29 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s, if (decode_block(s, s->block, i, dc_index[i], ac_index[i], s->quant_index[c]) < 0) { - dprintf("error %d %d\n", mb_y, mb_x); + dprintf("error y=%d x=%d\n", mb_y, mb_x); ret = -1; goto the_end; } // dprintf("mb: %d %d processed\n", mb_y, mb_x); - ff_idct (s->block); ptr = s->current_picture[c] + (s->linesize[c] * (v * mb_y + y) * 8) + (h * mb_x + x) * 8; if (s->interlaced && s->bottom_field) ptr += s->linesize[c] >> 1; - put_pixels_clamped(s->block, ptr, s->linesize[c]); + s->idct_put(ptr, s->linesize[c], s->block); if (++x == h) { x = 0; y++; } } } + if ((s->restart_interval <= 8) && !--s->restart_count) { + align_get_bits(&s->gb); + skip_bits(&s->gb, 16); /* skip RSTn */ + for (j=0; jlast_dc[j] = 1024; + } } } ret = 0; @@ -1017,39 +1049,32 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s, return -1; } -static int mjpeg_decode_dri(MJpegDecodeContext *s, - UINT8 *buf, int buf_size) +static int mjpeg_decode_dri(MJpegDecodeContext *s) { - init_get_bits(&s->gb, buf, buf_size); - if (get_bits(&s->gb, 16) != 4) return -1; s->restart_interval = get_bits(&s->gb, 16); - printf("restart interval: %d\n", s->restart_interval); + dprintf("restart interval: %d\n", s->restart_interval); return 0; } -#define FOURCC(a,b,c,d) ((a << 24) | (b << 16) | (c << 8) | d) -static int mjpeg_decode_app(MJpegDecodeContext *s, - UINT8 *buf, int buf_size, int start_code) +static int mjpeg_decode_app(MJpegDecodeContext *s) { int len, id; - init_get_bits(&s->gb, buf, buf_size); - /* XXX: verify len field validity */ len = get_bits(&s->gb, 16); if (len < 5) return -1; - id = (get_bits(&s->gb, 16) << 16) | get_bits(&s->gb, 16); + id = be2me_32((get_bits(&s->gb, 16) << 16) | get_bits(&s->gb, 16)); len -= 6; /* buggy AVID, it puts EOI only at every 10th frame */ /* also this fourcc is used by non-avid files too, it means interleaving, but it's always present in AVID files */ - if (id == FOURCC('A','V','I','1')) + if (id == ff_get_fourcc("AVI1")) { /* structure: 4bytes AVI1 @@ -1059,36 +1084,49 @@ static int mjpeg_decode_app(MJpegDecodeContext *s, 4bytes field_size_less_padding */ s->buggy_avid = 1; - if (s->first_picture) - printf("mjpeg: workarounding buggy AVID\n"); - s->interleaved_rows = get_bits(&s->gb, 8); +// if (s->first_picture) +// printf("mjpeg: workarounding buggy AVID\n"); + s->interlace_polarity = get_bits(&s->gb, 8); #if 0 skip_bits(&s->gb, 8); skip_bits(&s->gb, 32); skip_bits(&s->gb, 32); len -= 10; #endif - if (s->interleaved_rows) - printf("mjpeg: interleaved rows: %d\n", s->interleaved_rows); +// if (s->interlace_polarity) +// printf("mjpeg: interlace polarity: %d\n", s->interlace_polarity); goto out; } len -= 2; - if (id == FOURCC('J','F','I','F')) + if (id == ff_get_fourcc("JFIF")) { skip_bits(&s->gb, 8); /* the trailing zero-byte */ printf("mjpeg: JFIF header found (version: %x.%x)\n", get_bits(&s->gb, 8), get_bits(&s->gb, 8)); + if (get_bits(&s->gb, 8) == 0) + { + s->avctx->aspect_ratio_info = FF_ASPECT_EXTENDED; + s->avctx->aspected_width = get_bits(&s->gb, 16); + s->avctx->aspected_height = get_bits(&s->gb, 16); + } + else + { + skip_bits(&s->gb, 16); + skip_bits(&s->gb, 16); + } + skip_bits(&s->gb, 8); + skip_bits(&s->gb, 8); goto out; } /* Apple MJPEG-A */ - if ((start_code == APP1) && (len > (0x28 - 8))) + if ((s->start_code == APP1) && (len > (0x28 - 8))) { - id = (get_bits(&s->gb, 16) << 16) | get_bits(&s->gb, 16); + id = be2me_32((get_bits(&s->gb, 16) << 16) | get_bits(&s->gb, 16)); len -= 4; - if (id == FOURCC('m','j','p','g')) /* Apple MJPEG-A */ + if (id == ff_get_fourcc("mjpg")) /* Apple MJPEG-A */ { #if 0 skip_bits(&s->gb, 32); /* field size */ @@ -1106,24 +1144,17 @@ static int mjpeg_decode_app(MJpegDecodeContext *s, } out: - /* should check for further values.. */ - SKIP_REMAINING(&s->gb, len); - return 0; } -#undef FOURCC -static int mjpeg_decode_com(MJpegDecodeContext *s, - UINT8 *buf, int buf_size) +static int mjpeg_decode_com(MJpegDecodeContext *s) { int len, i; UINT8 *cbuf; - init_get_bits(&s->gb, buf, buf_size); - /* XXX: verify len field validity */ len = get_bits(&s->gb, 16)-2; - cbuf = malloc(len+1); + cbuf = av_malloc(len+1); for (i = 0; i < len; i++) cbuf[i] = get_bits(&s->gb, 8); @@ -1138,47 +1169,67 @@ static int mjpeg_decode_com(MJpegDecodeContext *s, if (!strcmp(cbuf, "AVID")) { s->buggy_avid = 1; - if (s->first_picture) - printf("mjpeg: workarounding buggy AVID\n"); +// if (s->first_picture) +// printf("mjpeg: workarounding buggy AVID\n"); } - free(cbuf); + av_free(cbuf); return 0; } +#if 0 +static 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, - UINT32 *header_state) +static int find_marker(UINT8 **pbuf_ptr, UINT8 *buf_end) { UINT8 *buf_ptr; - unsigned int state, v; + unsigned int v, v2; int val; +#ifdef DEBUG + int skipped=0; +#endif - state = *header_state; buf_ptr = *pbuf_ptr; - if (state) { - /* get marker */ - found: - if (buf_ptr < buf_end) { - val = *buf_ptr++; - state = 0; - } else { - val = -1; - } - } else { - while (buf_ptr < buf_end) { - v = *buf_ptr++; - if (v == 0xff) { - state = 1; - goto found; - } + while (buf_ptr < buf_end) { + v = *buf_ptr++; + v2 = *buf_ptr; + if ((v == 0xff) && (v2 >= 0xc0) && (v2 <= 0xfe)) { + val = *buf_ptr++; + goto found; } - val = -1; +#ifdef DEBUG + skipped++; +#endif } + val = -1; +found: +#ifdef DEBUG + dprintf("find_marker skipped %d bytes\n", skipped); +#endif *pbuf_ptr = buf_ptr; - *header_state = state; return val; } @@ -1187,10 +1238,9 @@ static int mjpeg_decode_frame(AVCodecContext *avctx, UINT8 *buf, int buf_size) { MJpegDecodeContext *s = avctx->priv_data; - UINT8 *buf_end, *buf_ptr, *buf_start; - int len, code, input_size, i; + UINT8 *buf_end, *buf_ptr; + int i, start_code; AVPicture *picture = data; - unsigned int start_code; *data_size = 0; @@ -1201,60 +1251,98 @@ static int mjpeg_decode_frame(AVCodecContext *avctx, buf_ptr = buf; buf_end = buf + buf_size; while (buf_ptr < buf_end) { - buf_start = buf_ptr; /* find start next marker */ - code = find_marker(&buf_ptr, buf_end, &s->header_state); - /* copy to buffer */ - len = buf_ptr - buf_start; - if (len + (s->buf_ptr - s->buffer) > s->buffer_size) { - /* data too big : flush */ - s->buf_ptr = s->buffer; - if (code > 0) - s->start_code = code; - } else { - memcpy(s->buf_ptr, buf_start, len); - s->buf_ptr += len; - /* if we got FF 00, we copy FF to the stream to unescape FF 00 */ - /* valid marker code is between 00 and ff - alex */ - if (code <= 0 || code >= 0xff) { - s->buf_ptr--; + start_code = find_marker(&buf_ptr, buf_end); + { + /* EOF */ + if (start_code < 0) { + goto the_end; } else { - /* prepare data for next start code */ - input_size = s->buf_ptr - s->buffer; - start_code = s->start_code; - s->buf_ptr = s->buffer; - s->start_code = code; - dprintf("marker=%x\n", start_code); + 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= 0xd0 && x <= 0xd7) + *(dst++) = x; + else if (x) + break; + } + } + init_get_bits(&s->gb, s->buffer, 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, s->buffer, input_size); + mjpeg_decode_dqt(s); break; case DHT: - mjpeg_decode_dht(s, s->buffer, input_size); + mjpeg_decode_dht(s); break; case SOF0: - mjpeg_decode_sof0(s, s->buffer, input_size); + mjpeg_decode_sof0(s); break; - case SOS: - mjpeg_decode_sos(s, s->buffer, input_size); - if (s->start_code == EOI || s->buggy_avid || s->restart_interval) { + 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 the_end; + 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; @@ -1279,9 +1367,16 @@ static int mjpeg_decode_frame(AVCodecContext *avctx, 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, s->buffer, input_size); + mjpeg_decode_dri(s); break; case SOF1: case SOF2: @@ -1297,27 +1392,24 @@ static int mjpeg_decode_frame(AVCodecContext *avctx, case SOF15: case JPG: printf("mjpeg: unsupported coding type (%x)\n", start_code); - return -1; + break; +// default: +// printf("mjpeg: unsupported marker (%x)\n", start_code); +// break; } -#if 1 - 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, s->buffer, input_size, start_code); - /* Comment */ - else if (start_code == COM) - mjpeg_decode_com(s, s->buffer, input_size); - } -#endif + +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: +the_end: + + dprintf("mjpeg decode frame unused %d bytes\n", buf_end - buf_ptr); +// return buf_end - buf_ptr; return buf_ptr - buf; } @@ -1326,8 +1418,9 @@ static int mjpeg_decode_end(AVCodecContext *avctx) MJpegDecodeContext *s = avctx->priv_data; int i, j; + av_free(s->buffer); for(i=0;icurrent_picture[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]);