jpegdec: optimise buffer scanning

Specifically, when needing more data, do not rescan from start next time
around, but resume from last position.

See also #583047.
This commit is contained in:
Mark Nauwelaerts 2010-04-29 16:26:49 +02:00
parent 761b883f2c
commit 52c71352e0
2 changed files with 45 additions and 10 deletions

View file

@ -414,6 +414,7 @@ gst_jpeg_dec_parse_image_data (GstJpegDec * dec)
{
guint8 *start, *data, *end;
guint size;
gboolean resync;
size = GST_BUFFER_SIZE (dec->tempbuf);
start = GST_BUFFER_DATA (dec->tempbuf);
@ -424,12 +425,14 @@ gst_jpeg_dec_parse_image_data (GstJpegDec * dec)
GST_DEBUG ("Parsing jpeg image data (%u bytes)", size);
/* skip start marker */
data += 2;
GST_DEBUG ("Parse state: offset=%d, resync=%d, entropy len=%d",
dec->parse_offset, dec->parse_resync, dec->parse_entropy_len);
/* resume from state offset (also skips start marker) */
data += (dec->parse_offset ? dec->parse_offset : 2);
while (1) {
guint frame_len;
gboolean resync;
/* do we need to resync? */
resync = (*data != 0xff);
@ -441,28 +444,33 @@ gst_jpeg_dec_parse_image_data (GstJpegDec * dec)
++data;
if (G_UNLIKELY (*data != 0xff)) {
GST_DEBUG ("at end of input and no next marker found, need more data");
return 0;
goto need_more_data;
}
}
/* may have marker, but could have been resyncng */
resync = resync || dec->parse_resync;
/* Skip over extra 0xff */
while (*data == 0xff && data < end)
++data;
/* enough bytes left for marker? (we need 0xNN after the 0xff) */
if (data >= end) {
GST_DEBUG ("at end of input and no EOI marker found, need more data");
return 0;
goto need_more_data1;
}
if (*data == 0xd9) {
GST_DEBUG ("0x%08" G_GINT64_MODIFIER "x: EOI marker",
(gint64) (data - start));
/* clear parse state */
dec->parse_resync = FALSE;
dec->parse_offset = 0;
return (data - start + 1);
}
if (*data >= 0xd0 && *data <= 0xd7)
frame_len = 0;
else if (data >= end - 2)
return 0;
goto need_more_data1;
else
frame_len = GST_READ_UINT16_BE (data + 1);
GST_DEBUG ("0x%08" G_GINT64_MODIFIER "x: tag %02x, frame_len=%u",
@ -478,22 +486,26 @@ gst_jpeg_dec_parse_image_data (GstJpegDec * dec)
/* theoretically we could have lost sync and not really need more
* data, but that's just tough luck and a broken image then */
GST_DEBUG ("at end of input and no EOI marker found, need more data");
return 0;
goto need_more_data1;
}
if (gst_jpeg_dec_parse_tag_has_entropy_segment (*data)) {
guint8 *d2 = data + 1 + frame_len;
guint eseglen = 0;
guint eseglen = dec->parse_entropy_len;
GST_DEBUG ("0x%08" G_GINT64_MODIFIER "x: finding entropy segment length",
(gint64) (data - start - 1));
while (1) {
if (d2 + eseglen >= end - 1)
return 0; /* need more data */
if (d2 + eseglen >= end - 1) {
/* need more data */
dec->parse_entropy_len = eseglen;
goto need_more_data1;
}
if (d2[eseglen] == 0xff && d2[eseglen + 1] != 0x00)
break;
++eseglen;
}
dec->parse_entropy_len = 0;
frame_len += eseglen;
GST_DEBUG ("entropy segment length=%u => frame_len=%u", eseglen,
frame_len);
@ -511,6 +523,21 @@ gst_jpeg_dec_parse_image_data (GstJpegDec * dec)
data += 1 + frame_len;
}
/* EXITS */
need_more_data:
{
dec->parse_offset = data - start;
dec->parse_resync = resync;
return 0;
}
need_more_data1:
{
/* step back one to point at marker */
dec->parse_offset = (data - start) - 1;
dec->parse_resync = resync;
return 0;
}
}
/* shamelessly ripped from jpegutils.c in mjpegtools */
@ -1605,6 +1632,9 @@ gst_jpeg_dec_change_state (GstElement * element, GstStateChange transition)
dec->packetized = FALSE;
dec->next_ts = 0;
dec->discont = TRUE;
dec->parse_offset = 0;
dec->parse_resync = FALSE;
dec->parse_entropy_len = FALSE;
gst_segment_init (&dec->segment, GST_FORMAT_UNDEFINED);
gst_jpeg_dec_reset_qos (dec);
default:

View file

@ -103,6 +103,11 @@ struct _GstJpegDec {
gint stride;
gint inc;
/* parse state */
gint parse_offset;
gint parse_entropy_len;
gint parse_resync;
/* properties */
gint idct_method;