openexrdec: Don't start scanning for the header from the start again each time

This will be incredible slow if the upstream block size is very small. Instead
continue scanning for the header where we previously stopped.

For the standard filesrc block-size this made decoding a file about
3 times faster.

https://bugzilla.gnome.org/show_bug.cgi?id=719890
This commit is contained in:
Sebastian Dröge 2014-01-18 13:56:28 +01:00
parent 1f9c305694
commit 7548d5f7f9

View file

@ -190,32 +190,38 @@ gst_openexr_dec_parse (GstVideoDecoder * decoder,
GstVideoCodecFrame * frame, GstAdapter * adapter, gboolean at_eos) GstVideoCodecFrame * frame, GstAdapter * adapter, gboolean at_eos)
{ {
guint8 data[8]; guint8 data[8];
gsize size; gsize size, parsed_size;
guint32 magic, flags; guint32 magic, flags;
gssize offset; gssize offset;
size = gst_adapter_available (adapter); size = gst_adapter_available (adapter);
parsed_size = gst_video_decoder_get_pending_frame_size (decoder);
GST_DEBUG_OBJECT (decoder, "Parsing OpenEXR image data %" G_GSIZE_FORMAT, GST_DEBUG_OBJECT (decoder, "Parsing OpenEXR image data %" G_GSIZE_FORMAT,
size); size);
if (size < 8) if (parsed_size == 0 && size < 8)
goto need_more_data; goto need_more_data;
gst_adapter_copy (adapter, data, 0, 8); /* If we did not parse anything yet, check if the frame starts with the header */
if (parsed_size == 0) {
gst_adapter_copy (adapter, data, 0, 8);
magic = GST_READ_UINT32_LE (data); magic = GST_READ_UINT32_LE (data);
flags = GST_READ_UINT32_LE (data + 4); flags = GST_READ_UINT32_LE (data + 4);
if (magic != 0x01312f76 || ((flags & 0xff) != 1 && (flags & 0xff) != 2) || ((flags & 0x200) && (flags & 0x1800))) { if (magic != 0x01312f76 || ((flags & 0xff) != 1 && (flags & 0xff) != 2) || ((flags & 0x200) && (flags & 0x1800))) {
offset = gst_adapter_masked_scan_uint32_peek (adapter, 0xffffffff, 0x762f3101, 0, size, NULL); offset = gst_adapter_masked_scan_uint32_peek (adapter, 0xffffffff, 0x762f3101, 0, size, NULL);
if (offset == -1) { if (offset == -1) {
gst_adapter_flush (adapter, size - 4); gst_adapter_flush (adapter, size - 4);
goto need_more_data;
}
/* come back into this function after flushing some data */
gst_adapter_flush (adapter, offset);
goto need_more_data; goto need_more_data;
} }
} else {
/* come back into this function after flushing some data */
gst_adapter_flush (adapter, offset);
goto need_more_data;
} }
/* valid header, now let's try to find the next one unless we're EOS */ /* valid header, now let's try to find the next one unless we're EOS */
@ -224,8 +230,10 @@ gst_openexr_dec_parse (GstVideoDecoder * decoder,
while (!found) { while (!found) {
offset = gst_adapter_masked_scan_uint32_peek (adapter, 0xffffffff, 0x762f3101, 8, size - 8 - 4, NULL); offset = gst_adapter_masked_scan_uint32_peek (adapter, 0xffffffff, 0x762f3101, 8, size - 8 - 4, NULL);
if (offset == -1) if (offset == -1) {
gst_video_decoder_add_to_frame (decoder, size - 7);
goto need_more_data; goto need_more_data;
}
gst_adapter_copy (adapter, data, offset, 8); gst_adapter_copy (adapter, data, offset, 8);
magic = GST_READ_UINT32_LE (data); magic = GST_READ_UINT32_LE (data);
@ -236,7 +244,7 @@ gst_openexr_dec_parse (GstVideoDecoder * decoder,
size = offset; size = offset;
} }
GST_DEBUG_OBJECT (decoder, "Have complete image of size %" G_GSSIZE_FORMAT, size); GST_DEBUG_OBJECT (decoder, "Have complete image of size %" G_GSSIZE_FORMAT, size + parsed_size);
gst_video_decoder_add_to_frame (decoder, size); gst_video_decoder_add_to_frame (decoder, size);