|
|
|
@ -17,10 +17,10 @@ |
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
|
|
|
* |
|
|
|
|
* Support for external huffman table, various fixes (AVID workaround), |
|
|
|
|
* aspecting and various markers support |
|
|
|
|
* aspecting and new decode_frame mechanism |
|
|
|
|
* by Alex Beregszaszi <alex@naxine.org> |
|
|
|
|
*/ |
|
|
|
|
//#define DEBUG
|
|
|
|
|
#define DEBUG |
|
|
|
|
#include "avcodec.h" |
|
|
|
|
#include "dsputil.h" |
|
|
|
|
#include "mpegvideo.h" |
|
|
|
@ -29,7 +29,7 @@ |
|
|
|
|
#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 |
|
|
|
|
|
|
|
|
@ -590,11 +590,12 @@ void mjpeg_encode_mb(MpegEncContext *s, |
|
|
|
|
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]; |
|
|
|
|
|
|
|
|
@ -614,7 +615,6 @@ 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; |
|
|
|
@ -624,13 +624,7 @@ typedef struct MJpegDecodeContext { |
|
|
|
|
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, UINT8 *buf, int buf_size); |
|
|
|
|
static int mjpeg_decode_dht(MJpegDecodeContext *s); |
|
|
|
|
|
|
|
|
|
static void build_vlc(VLC *vlc, const UINT8 *bits_table, const UINT8 *val_table,
|
|
|
|
|
int nb_codes) |
|
|
|
@ -664,12 +658,11 @@ static int mjpeg_decode_init(AVCodecContext *avctx) |
|
|
|
|
s->idct_put= s2.idct_put; |
|
|
|
|
MPV_common_end(&s2); |
|
|
|
|
|
|
|
|
|
s->header_state = 0; |
|
|
|
|
s->mpeg_enc_ctx_allocated = 0; |
|
|
|
|
s->buffer_size = PICTURE_BUFFER_SIZE - 1; /* minus 1 to take into
|
|
|
|
|
account FF 00 case */ |
|
|
|
|
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; |
|
|
|
@ -678,22 +671,22 @@ 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); |
|
|
|
|
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; |
|
|
|
|
|
|
|
|
@ -716,23 +709,17 @@ static int mjpeg_decode_dqt(MJpegDecodeContext *s, |
|
|
|
|
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) |
|
|
|
@ -770,13 +757,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 */ |
|
|
|
@ -851,8 +835,12 @@ static int mjpeg_decode_sof0(MJpegDecodeContext *s, |
|
|
|
|
static inline int mjpeg_decode_dc(MJpegDecodeContext *s, int dc_index) |
|
|
|
|
{ |
|
|
|
|
int code, diff; |
|
|
|
|
|
|
|
|
|
#if 0 |
|
|
|
|
code = get_vlc2(&s->gb, s->vlc[0][dc_index].table, |
|
|
|
|
s->vlc[0][dc_index].bits, 1); |
|
|
|
|
#else |
|
|
|
|
code = get_vlc(&s->gb, &s->vlcs[0][dc_index]); |
|
|
|
|
#endif |
|
|
|
|
if (code < 0) |
|
|
|
|
{ |
|
|
|
|
dprintf("mjpeg_decode_dc: bad vlc: %d:%d (%p)\n", 0, dc_index, |
|
|
|
@ -892,7 +880,12 @@ static int decode_block(MJpegDecodeContext *s, DCTELEM *block, |
|
|
|
|
ac_vlc = &s->vlcs[1][ac_index]; |
|
|
|
|
i = 1; |
|
|
|
|
for(;;) { |
|
|
|
|
#if 0 |
|
|
|
|
code = get_vlc2(&s->gb, s->vlcs[1][ac_index].table, |
|
|
|
|
s->vlcs[1][ac_index].bits, 2); |
|
|
|
|
#else |
|
|
|
|
code = get_vlc(&s->gb, ac_vlc); |
|
|
|
|
#endif |
|
|
|
|
if (code < 0) { |
|
|
|
|
dprintf("error ac\n"); |
|
|
|
|
return -1; |
|
|
|
@ -923,8 +916,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; |
|
|
|
@ -935,10 +927,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) |
|
|
|
|
{ |
|
|
|
@ -1061,11 +1057,8 @@ 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); |
|
|
|
@ -1075,13 +1068,10 @@ static int mjpeg_decode_dri(MJpegDecodeContext *s, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#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 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) |
|
|
|
@ -1164,20 +1154,16 @@ 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 = av_malloc(len+1); |
|
|
|
@ -1195,8 +1181,8 @@ 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");
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
av_free(cbuf); |
|
|
|
@ -1204,41 +1190,58 @@ static int mjpeg_decode_com(MJpegDecodeContext *s, |
|
|
|
|
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; |
|
|
|
|
retry: |
|
|
|
|
if (state) { |
|
|
|
|
/* get marker */ |
|
|
|
|
found: |
|
|
|
|
if (buf_ptr < buf_end) { |
|
|
|
|
val = *buf_ptr++; |
|
|
|
|
state = 0; |
|
|
|
|
if ((val >= RST0) && (val <= RST7)) |
|
|
|
|
goto retry; |
|
|
|
|
} 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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1247,10 +1250,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; |
|
|
|
|
|
|
|
|
@ -1261,49 +1263,78 @@ 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 (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--; |
|
|
|
|
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); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* unescape buffer of SOS */ |
|
|
|
|
if (start_code == SOS) |
|
|
|
|
{ |
|
|
|
|
UINT8 *src = buf_ptr; |
|
|
|
|
UINT8 *dst = s->buffer; |
|
|
|
|
|
|
|
|
|
while (src<buf_end) |
|
|
|
|
{ |
|
|
|
|
unsigned char *x = *(src++); |
|
|
|
|
|
|
|
|
|
*(dst++) = x; |
|
|
|
|
if (x == 0xff) |
|
|
|
|
{ |
|
|
|
|
x = *(src++); |
|
|
|
|
if (x >= 0xd0 && x <= 0xd7) |
|
|
|
|
*(dst++) = x; |
|
|
|
|
else if (x) |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
memcpy(s->buffer, buf_ptr, buf_end - buf_ptr); |
|
|
|
|
init_get_bits(&s->gb, s->buffer, s->buffer_size); |
|
|
|
|
|
|
|
|
|
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, start_code); |
|
|
|
|
/* 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; |
|
|
|
@ -1313,10 +1344,15 @@ static int mjpeg_decode_frame(AVCodecContext *avctx, |
|
|
|
|
} |
|
|
|
|
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; |
|
|
|
@ -1341,9 +1377,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: |
|
|
|
@ -1359,26 +1402,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)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
not_the_end: |
|
|
|
|
; |
|
|
|
|
} |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1387,6 +1428,7 @@ 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++) { |
|
|
|
|