Newer
Older
/* XXX: only interleaved scan accepted */
if (nb_components != 3)
Arpi
committed
{
dprintf("decode_sos: components(%d) mismatch\n", nb_components);
Arpi
committed
}
vmax = 0;
hmax = 0;
for(i=0;i<nb_components;i++) {
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)
Arpi
committed
{
dprintf("decode_sos: index(%d) out of components\n", index);
Arpi
committed
}
comp_index[i] = index;
nb_blocks[i] = s->h_count[index] * s->v_count[index];
h_count[i] = s->h_count[index];
v_count[i] = s->v_count[index];
dc_index[i] = get_bits(&s->gb, 4);
ac_index[i] = get_bits(&s->gb, 4);
Arpi
committed
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;
}
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;
if (nb_components > 1) {
/* interleaved stream */
mb_width = (s->width + s->h_max * 8 - 1) / (s->h_max * 8);
mb_height = (s->height + s->v_max * 8 - 1) / (s->v_max * 8);
} else {
h = s->h_max / s->h_count[comp_index[0]];
v = s->v_max / s->v_count[comp_index[0]];
mb_width = (s->width + h * 8 - 1) / (h * 8);
mb_height = (s->height + v * 8 - 1) / (v * 8);
nb_blocks[0] = 1;
h_count[0] = 1;
v_count[0] = 1;
}
for(mb_y = 0; mb_y < mb_height; mb_y++) {
for(mb_x = 0; mb_x < mb_width; mb_x++) {
for(i=0;i<nb_components;i++) {
UINT8 *ptr;
int x, y, c;
n = nb_blocks[i];
c = comp_index[i];
h = h_count[i];
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 y=%d x=%d\n", mb_y, mb_x);
Fabrice Bellard
committed
ret = -1;
goto the_end;
Arpi
committed
// 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;
s->idct_put(ptr, s->linesize[c], s->block);
if (++x == h) {
x = 0;
y++;
}
}
}
/* (< 1350) buggy workaround for Spectralfan.mov, should be fixed */
if (s->restart_interval && (s->restart_interval < 1350) &&
!--s->restart_count) {
Leon van Stuivenberg
committed
align_get_bits(&s->gb);
skip_bits(&s->gb, 16); /* skip RSTn */
for (j=0; j<nb_components; j++) /* reset dc */
s->last_dc[j] = 1024;
}
Fabrice Bellard
committed
ret = 0;
the_end:
emms_c();
Fabrice Bellard
committed
return ret;
Arpi
committed
out_of_range:
dprintf("decode_sos: ac/dc index out of range\n");
return -1;
static int mjpeg_decode_dri(MJpegDecodeContext *s)
{
if (get_bits(&s->gb, 16) != 4)
return -1;
s->restart_interval = get_bits(&s->gb, 16);
dprintf("restart interval: %d\n", s->restart_interval);
return 0;
}
Alex Beregszaszi
committed
static int mjpeg_decode_app(MJpegDecodeContext *s)
{
int len, id;
/* 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(id);
len -= 6;
/* buggy AVID, it puts EOI only at every 10th frame */
/* also this fourcc is used by non-avid files too, it holds some
informations, but it's always present in AVID creates files */
Alex Beregszaszi
committed
if (id == ff_get_fourcc("AVI1"))
/* structure:
4bytes AVI1
1bytes polarity
1bytes always zero
4bytes field_size
4bytes field_size_less_padding
*/
s->buggy_avid = 1;
Alex Beregszaszi
committed
// 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
Alex Beregszaszi
committed
// if (s->interlace_polarity)
// printf("mjpeg: interlace polarity: %d\n", s->interlace_polarity);
goto out;
// len -= 2;
Alex Beregszaszi
committed
if (id == ff_get_fourcc("JFIF"))
int t_w, t_h;
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));
int x_density, y_density;
x_density = get_bits(&s->gb, 16);
y_density = get_bits(&s->gb, 16);
dprintf("x/y density: %d (%f), %d (%f)\n", x_density,
(float)x_density, y_density, (float)y_density);
#if 0
if(x_density)
// s->avctx->aspect_ratio= s->width*y_density/((float)s->height*x_density);
s->avctx->aspect_ratio = (float)x_density/y_density;
/* it's better, but every JFIF I have seen stores 1:1 */
else
s->avctx->aspect_ratio= 0.0;
}
else
{
skip_bits(&s->gb, 16);
skip_bits(&s->gb, 16);
}
t_w = get_bits(&s->gb, 8);
t_h = get_bits(&s->gb, 8);
if (t_w && t_h)
{
/* skip thumbnail */
if (len-10-(t_w*t_h*3) > 0)
len -= t_w*t_h*3;
}
len -= 10;
goto out;
}
if (id == ff_get_fourcc("Adob") && (get_bits(&s->gb, 8) == 'e'))
{
printf("mjpeg: Adobe header found\n");
skip_bits(&s->gb, 16); /* version */
skip_bits(&s->gb, 16); /* flags0 */
skip_bits(&s->gb, 16); /* flags1 */
skip_bits(&s->gb, 8); /* transform */
len -= 7;
goto out;
}
/* Apple MJPEG-A */
Alex Beregszaszi
committed
if ((s->start_code == APP1) && (len > (0x28 - 8)))
id = (get_bits(&s->gb, 16) << 16) | get_bits(&s->gb, 16);
id = be2me_32(id);
len -= 4;
Alex Beregszaszi
committed
if (id == ff_get_fourcc("mjpg")) /* 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:
/* slow but needed for extreme adobe jpegs */
if (len < 0)
printf("mjpeg: error, decode_app parser read over the end\n");
while(--len > 0)
skip_bits(&s->gb, 8);
static int mjpeg_decode_com(MJpegDecodeContext *s)
{
int len, i;
UINT8 *cbuf;
/* 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;
}
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
#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)
{
UINT8 *buf_ptr;
unsigned int v, v2;
#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;
/* no supplementary picture */
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;
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);
Alex Beregszaszi
committed
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)
{
*(dst++) = x;
if (x == 0xff)
{
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)
Alex Beregszaszi
committed
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:
case EOI:
eoi_parser:
{
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];
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;
}
Fabrice Bellard
committed
/* dummy quality */
/* XXX: infer it with matrix */
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;
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;
}
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
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;
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
}
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 */
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
};