summaryrefslogtreecommitdiff
path: root/src/libffmpeg/libavcodec/mjpeg.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libffmpeg/libavcodec/mjpeg.c')
-rw-r--r--src/libffmpeg/libavcodec/mjpeg.c489
1 files changed, 427 insertions, 62 deletions
diff --git a/src/libffmpeg/libavcodec/mjpeg.c b/src/libffmpeg/libavcodec/mjpeg.c
index 1eb35d2b8..577e9d884 100644
--- a/src/libffmpeg/libavcodec/mjpeg.c
+++ b/src/libffmpeg/libavcodec/mjpeg.c
@@ -1,28 +1,36 @@
/*
* 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 <alex@naxine.org>
*/
//#define DEBUG
-#include "config.h"
-
#include "avcodec.h"
#include "dsputil.h"
#include "mpegvideo.h"
-#include "xine-utils/xineutils.h"
+
+#ifdef USE_FASTMEMCPY
+#include "fastmemcpy.h"
+#endif
+
+/* use two quantizer table (one for luminance and one for chrominance) */
+/* not yet working */
+#undef TWOMATRIXES
typedef struct MJpegContext {
UINT8 huff_size_dc_luminance[12];
@@ -36,12 +44,87 @@ typedef struct MJpegContext {
UINT16 huff_code_ac_chrominance[256];
} MJpegContext;
-#define SOF0 0xc0
-#define SOI 0xd8
-#define EOI 0xd9
-#define DQT 0xdb
-#define DHT 0xc4
-#define SOS 0xda
+/* JPEG marker codes */
+typedef enum {
+ /* start of frame */
+ SOF0 = 0xc0, /* baseline */
+ SOF1 = 0xc1, /* extended sequential, huffman */
+ SOF2 = 0xc2, /* progressive, huffman */
+ SOF3 = 0xc3, /* lossless, huffman */
+
+ SOF5 = 0xc5, /* differential sequential, huffman */
+ SOF6 = 0xc6, /* differential progressive, huffman */
+ SOF7 = 0xc7, /* differential lossless, huffman */
+ JPG = 0xc8, /* reserved for JPEG extension */
+ SOF9 = 0xc9, /* extended sequential, arithmetic */
+ SOF10 = 0xca, /* progressive, arithmetic */
+ SOF11 = 0xcb, /* lossless, arithmetic */
+
+ SOF13 = 0xcd, /* differential sequential, arithmetic */
+ SOF14 = 0xce, /* differential progressive, arithmetic */
+ SOF15 = 0xcf, /* differential lossless, arithmetic */
+
+ DHT = 0xc4, /* define huffman tables */
+
+ DAC = 0xcc, /* define arithmetic-coding conditioning */
+
+ /* restart with modulo 8 count "m" */
+ RST0 = 0xd0,
+ RST1 = 0xd1,
+ RST2 = 0xd2,
+ RST3 = 0xd3,
+ RST4 = 0xd4,
+ RST5 = 0xd5,
+ RST6 = 0xd6,
+ RST7 = 0xd7,
+
+ SOI = 0xd8, /* start of image */
+ EOI = 0xd9, /* end of image */
+ SOS = 0xda, /* start of scan */
+ DQT = 0xdb, /* define quantization tables */
+ DNL = 0xdc, /* define number of lines */
+ DRI = 0xdd, /* define restart interval */
+ DHP = 0xde, /* define hierarchical progression */
+ EXP = 0xdf, /* expand reference components */
+
+ APP0 = 0xe0,
+ APP1 = 0xe1,
+ APP2 = 0xe2,
+ APP3 = 0xe3,
+ APP4 = 0xe4,
+ APP5 = 0xe5,
+ APP6 = 0xe6,
+ APP7 = 0xe7,
+ APP8 = 0xe8,
+ APP9 = 0xe9,
+ APP10 = 0xea,
+ APP11 = 0xeb,
+ APP12 = 0xec,
+ APP13 = 0xed,
+ APP14 = 0xee,
+ APP15 = 0xef,
+
+ JPG0 = 0xf0,
+ JPG1 = 0xf1,
+ JPG2 = 0xf2,
+ JPG3 = 0xf3,
+ JPG4 = 0xf4,
+ JPG5 = 0xf5,
+ JPG6 = 0xf6,
+ JPG7 = 0xf7,
+ JPG8 = 0xf8,
+ JPG9 = 0xf9,
+ JPG10 = 0xfa,
+ JPG11 = 0xfb,
+ JPG12 = 0xfc,
+ JPG13 = 0xfd,
+
+ COM = 0xfe, /* comment */
+
+ TEM = 0x01, /* temporary private use for arithmetic coding */
+
+ /* 0x02 -> 0xbf reserved */
+} JPEG_MARKER;
#if 0
/* These are the sample quantization tables given in JPEG spec section K.1.
@@ -135,7 +218,6 @@ static const UINT8 val_ac_chrominance[] =
0xf9, 0xfa
};
-
/* isn't this function nicer than the one in the libjpeg ? */
static void build_huffman_codes(UINT8 *huff_size, UINT16 *huff_code,
const UINT8 *bits_table, const UINT8 *val_table)
@@ -160,9 +242,13 @@ int mjpeg_init(MpegEncContext *s)
{
MJpegContext *m;
- m = malloc(sizeof(MJpegContext));
+ m = av_malloc(sizeof(MJpegContext));
if (!m)
return -1;
+
+ s->min_qcoeff=-1023;
+ s->max_qcoeff= 1023;
+ s->intra_quant_bias= 1<<(QUANT_BIAS_SHIFT-1); //(a + x/2)/x
/* build all the huffman tables */
build_huffman_codes(m->huff_size_dc_luminance,
@@ -188,7 +274,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)
@@ -227,14 +313,18 @@ static void jpeg_table_header(MpegEncContext *s)
/* quant matrixes */
put_marker(p, DQT);
+#ifdef TWOMATRIXES
+ put_bits(p, 16, 2 + 2 * (1 + 64));
+#else
put_bits(p, 16, 2 + 1 * (1 + 64));
+#endif
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];
put_bits(p, 8, s->intra_matrix[j]);
}
-#if 0
+#ifdef TWOMATRIXES
put_bits(p, 4, 0); /* 8 bit precision */
put_bits(p, 4, 1); /* table 1 */
for(i=0;i<64;i++) {
@@ -258,10 +348,46 @@ static void jpeg_table_header(MpegEncContext *s)
ptr[1] = size;
}
+static void jpeg_put_comments(MpegEncContext *s)
+{
+ PutBitContext *p = &s->pb;
+ int size;
+ UINT8 *ptr;
+
+#if 0
+ /* 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, 8, 0); /* units type: 0 - aspect ratio */
+ put_bits(p, 16, 1); /* aspect: 1:1 */
+ put_bits(p, 16, 1);
+ 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;
+}
+
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);
put_marker(&s->pb, SOF0);
@@ -282,13 +408,22 @@ void mjpeg_picture_header(MpegEncContext *s)
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);
@@ -312,7 +447,7 @@ void mjpeg_picture_header(MpegEncContext *s)
put_bits(&s->pb, 8, 0); /* Ss (not used) */
put_bits(&s->pb, 8, 63); /* Se (not used) */
- put_bits(&s->pb, 8, 0); /* (not used) */
+ put_bits(&s->pb, 8, 0); /* Ah/Al (not used) */
}
void mjpeg_picture_trailer(MpegEncContext *s)
@@ -321,8 +456,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;
@@ -361,11 +496,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;
}
@@ -429,6 +564,7 @@ void mjpeg_encode_mb(MpegEncContext *s,
#define MAX_COMPONENTS 4
typedef struct MJpegDecodeContext {
+ AVCodecContext *avctx;
GetBitContext gb;
UINT32 header_state;
int start_code; /* current start code */
@@ -455,8 +591,21 @@ typedef struct MJpegDecodeContext {
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;
} 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, UINT8 *buf, int buf_size);
+
static void build_vlc(VLC *vlc, const UINT8 *bits_table, const UINT8 *val_table,
int nb_codes)
{
@@ -473,6 +622,8 @@ static int mjpeg_decode_init(AVCodecContext *avctx)
{
MJpegDecodeContext *s = avctx->priv_data;
+ s->avctx = avctx;
+
s->header_state = 0;
s->mpeg_enc_ctx_allocated = 0;
s->buffer_size = PICTURE_BUFFER_SIZE - 1; /* minus 1 to take into
@@ -487,6 +638,13 @@ static int mjpeg_decode_init(AVCodecContext *avctx)
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);
+ /* should check for error - but dunno */
+ }
return 0;
}
@@ -496,14 +654,16 @@ 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);
- len -= 2;
+
+ 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;
@@ -511,10 +671,13 @@ static int mjpeg_decode_dqt(MJpegDecodeContext *s,
/* read quant table */
for(i=0;i<64;i++) {
j = zigzag_direct[i];
- s->quant_matrixes[index][j] = get_bits(&s->gb, 8);
+ s->quant_matrixes[index][j] = get_bits(&s->gb, 8);
}
len -= 65;
}
+
+ SKIP_REMAINING(&s->gb, len);
+
return 0;
}
@@ -581,6 +744,7 @@ static int mjpeg_decode_sof0(MJpegDecodeContext *s,
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 ||
@@ -602,16 +766,15 @@ static int mjpeg_decode_sof0(MJpegDecodeContext *s,
s->quant_index[i] = get_bits(&s->gb, 8);
if (s->quant_index[i] >= 4)
return -1;
- dprintf("component %d %d:%d\n", i, s->h_count[i], s->v_count[i]);
+ dprintf("component %d %d:%d id: %d quant:%d\n", i, s->h_count[i],
+ s->v_count[i], s->component_id[i], s->quant_index[i]);
}
/* if different size, realloc/alloc picture */
/* XXX: also check h_count and v_count */
if (width != s->width || height != s->height) {
- for(i=0;i<MAX_COMPONENTS;i++) {
- free(s->current_picture[i]);
- s->current_picture[i] = NULL;
- }
+ for(i=0;i<MAX_COMPONENTS;i++)
+ av_freep(&s->current_picture[i]);
s->width = width;
s->height = height;
/* test interlaced mode */
@@ -619,7 +782,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 = 0;
+ s->bottom_field = 0;
}
for(i=0;i<nb_components;i++) {
@@ -636,19 +799,26 @@ static int mjpeg_decode_sof0(MJpegDecodeContext *s,
}
s->first_picture = 0;
}
+
+ if (len != (8+(3*nb_components)))
+ {
+ dprintf("decode_sof0: error, len(%d) mismatch\n", len);
+ }
return 0;
}
-static inline int decode_dc(MJpegDecodeContext *s, int dc_index)
+static inline int mjpeg_decode_dc(MJpegDecodeContext *s, int dc_index)
{
- VLC *dc_vlc;
int code, diff;
- dc_vlc = &s->vlcs[0][dc_index];
- code = get_vlc(&s->gb, dc_vlc);
+ code = get_vlc(&s->gb, &s->vlcs[0][dc_index]);
if (code < 0)
+ {
+ dprintf("mjpeg_decode_dc: bad vlc: %d:%d (%p)\n", 0, dc_index,
+ &s->vlcs[0][dc_index]);
return 0xffff;
+ }
if (code == 0) {
diff = 0;
} else {
@@ -668,13 +838,13 @@ static int decode_block(MJpegDecodeContext *s, DCTELEM *block,
VLC *ac_vlc;
INT16 *quant_matrix;
- quant_matrix = s->quant_matrixes[quant_index];
/* DC coef */
- val = decode_dc(s, dc_index);
+ val = mjpeg_decode_dc(s, dc_index);
if (val == 0xffff) {
dprintf("error dc\n");
return -1;
}
+ quant_matrix = s->quant_matrixes[quant_index];
val = val * quant_matrix[0] + s->last_dc[component];
s->last_dc[component] = val;
block[0] = val;
@@ -731,17 +901,24 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s,
nb_components = get_bits(&s->gb, 8);
/* XXX: only interleaved scan accepted */
if (nb_components != 3)
+ {
+ dprintf("decode_sos: components(%d) mismatch\n", nb_components);
return -1;
+ }
vmax = 0;
hmax = 0;
for(i=0;i<nb_components;i++) {
id = get_bits(&s->gb, 8) - 1;
+ dprintf("component: %d\n", id);
/* find component index */
for(index=0;index<s->nb_components;index++)
if (id == s->component_id[index])
break;
if (index == s->nb_components)
+ {
+ dprintf("decode_sos: index(%d) out of components\n", index);
return -1;
+ }
comp_index[i] = index;
nb_blocks[i] = s->h_count[index] * s->v_count[index];
@@ -749,15 +926,31 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s,
v_count[i] = s->v_count[index];
dc_index[i] = get_bits(&s->gb, 4);
- if (dc_index[i] >= 4)
- return -1;
ac_index[i] = get_bits(&s->gb, 4);
- if (ac_index[i] >= 4)
- return -1;
+
+ if (dc_index[i] < 0 || ac_index[i] < 0 ||
+ dc_index[i] >= 4 || ac_index[i] >= 4)
+ goto out_of_range;
+ switch(s->start_code)
+ {
+ case SOF0:
+ if (dc_index[i] > 1 || ac_index[i] > 1)
+ goto out_of_range;
+ break;
+ case SOF1:
+ case SOF2:
+ if (dc_index[i] > 3 || ac_index[i] > 3)
+ goto out_of_range;
+ break;
+ case SOF3:
+ if (dc_index[i] > 3 || ac_index[i] != 0)
+ goto out_of_range;
+ break;
+ }
}
- get_bits(&s->gb, 8); /* Ss */
- get_bits(&s->gb, 8); /* Se */
- get_bits(&s->gb, 8); /* not used */
+ skip_bits(&s->gb, 8); /* Ss */
+ skip_bits(&s->gb, 8); /* Se */
+ skip_bits(&s->gb, 8); /* Ah and Al (each are 4 bits) */
for(i=0;i<nb_components;i++)
s->last_dc[i] = 1024;
@@ -787,22 +980,24 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s,
v = v_count[i];
x = 0;
y = 0;
+ if (s->restart_interval && !s->restart_count)
+ s->restart_count = s->restart_interval;
for(j=0;j<n;j++) {
memset(s->block, 0, sizeof(s->block));
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;
}
- ff_idct (s->block);
+// dprintf("mb: %d %d processed\n", mb_y, mb_x);
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]);
+ ff_idct_put(ptr, s->linesize[c], s->block);
if (++x == h) {
x = 0;
y++;
@@ -815,6 +1010,139 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s,
the_end:
emms_c();
return ret;
+ out_of_range:
+ dprintf("decode_sos: ac/dc index out of range\n");
+ return -1;
+}
+
+static int mjpeg_decode_dri(MJpegDecodeContext *s,
+ UINT8 *buf, int buf_size)
+{
+ 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);
+
+ 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)
+{
+ 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);
+ 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'))
+ {
+ /* structure:
+ 4bytes AVI1
+ 1bytes polarity
+ 1bytes always zero
+ 4bytes field_size
+ 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 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);
+ goto out;
+ }
+
+ len -= 2;
+
+ if (id == FOURCC('J','F','I','F'))
+ {
+ 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));
+ goto out;
+ }
+
+ /* Apple MJPEG-A */
+ if ((start_code == APP1) && (len > (0x28 - 8)))
+ {
+ id = (get_bits(&s->gb, 16) << 16) | get_bits(&s->gb, 16);
+ len -= 4;
+ if (id == FOURCC('m','j','p','g')) /* 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->first_picture)
+ printf("mjpeg: Apple MJPEG-A header found\n");
+ }
+ }
+
+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)
+{
+ 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 = av_malloc(len+1);
+
+ for (i = 0; i < len; i++)
+ cbuf[i] = get_bits(&s->gb, 8);
+ if (cbuf[i-1] == '\n')
+ cbuf[i-1] = 0;
+ else
+ cbuf[i] = 0;
+
+ printf("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");
+ }
+
+ av_free(cbuf);
+
+ return 0;
}
/* return the 8 bit start code value and update the search
@@ -858,8 +1186,9 @@ static int mjpeg_decode_frame(AVCodecContext *avctx,
{
MJpegDecodeContext *s = avctx->priv_data;
UINT8 *buf_end, *buf_ptr, *buf_start;
- int len, code, start_code, input_size, i;
+ int len, code, input_size, i;
AVPicture *picture = data;
+ unsigned int start_code;
*data_size = 0;
@@ -883,10 +1212,13 @@ static int mjpeg_decode_frame(AVCodecContext *avctx,
} 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 */
- if (code == 0) {
+ if (code < 0) {
+ /* nothing to do: wait next marker */
+ } else if (code == 0 || code == 0xff) {
+ /* if we got FF 00, we copy FF to the stream to unescape FF 00 */
+ /* valid marker code is between 00 and ff - alex */
s->buf_ptr--;
- } else if (code > 0) {
+ } else {
/* prepare data for next start code */
input_size = s->buf_ptr - s->buffer;
start_code = s->start_code;
@@ -895,6 +1227,7 @@ static int mjpeg_decode_frame(AVCodecContext *avctx,
dprintf("marker=%x\n", start_code);
switch(start_code) {
case SOI:
+ s->restart_interval = 0;
/* nothing to do on SOI */
break;
case DQT:
@@ -908,7 +1241,7 @@ static int mjpeg_decode_frame(AVCodecContext *avctx,
break;
case SOS:
mjpeg_decode_sos(s, s->buffer, input_size);
- if (s->start_code == EOI) {
+ if (s->start_code == EOI || s->buggy_avid || s->restart_interval) {
int l;
if (s->interlaced) {
s->bottom_field ^= 1;
@@ -943,11 +1276,41 @@ static int mjpeg_decode_frame(AVCodecContext *avctx,
}
/* dummy quality */
/* XXX: infer it with matrix */
- avctx->quality = 3;
+ avctx->quality = 3;
goto the_end;
}
break;
+ case DRI:
+ mjpeg_decode_dri(s, s->buffer, input_size);
+ 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);
+ return -1;
}
+#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
}
}
}
@@ -961,7 +1324,7 @@ static int mjpeg_decode_end(AVCodecContext *avctx)
int i, j;
for(i=0;i<MAX_COMPONENTS;i++)
- free(s->current_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]);
@@ -978,4 +1341,6 @@ AVCodec mjpeg_decoder = {
NULL,
mjpeg_decode_end,
mjpeg_decode_frame,
+ 0,
+ NULL
};