gst/matroska/ebml-ids.h: Add ID for EBML CRC32 elements.

Original commit message from CVS:
* gst/matroska/ebml-ids.h:
Add ID for EBML CRC32 elements.
* gst/matroska/Makefile.am:
* gst/matroska/ebml-read.c: (gst_ebml_finalize),
(gst_ebml_read_class_init), (gst_ebml_read_peek_bytes),
(gst_ebml_read_get_length), (_ext2dbl), (gst_ebml_read_float),
(gst_ebml_read_header):
Support reading 80bit floats, add finalize method to clean up
in any case, support reading length/id elements with any length
as long as it's smaller than our supported maximum, don't leak
buffers if reading as much data as we wanted failed and some
smaller cleanup.
This commit is contained in:
Sebastian Dröge 2008-03-08 04:40:32 +00:00
parent c7296fe79a
commit 8342c0cc96
4 changed files with 100 additions and 25 deletions

View file

@ -1,3 +1,19 @@
2008-03-08 Sebastian Dröge <slomo@circular-chaos.org>
* gst/matroska/ebml-ids.h:
Add ID for EBML CRC32 elements.
* gst/matroska/Makefile.am:
* gst/matroska/ebml-read.c: (gst_ebml_finalize),
(gst_ebml_read_class_init), (gst_ebml_read_peek_bytes),
(gst_ebml_read_get_length), (_ext2dbl), (gst_ebml_read_float),
(gst_ebml_read_header):
Support reading 80bit floats, add finalize method to clean up
in any case, support reading length/id elements with any length
as long as it's smaller than our supported maximum, don't leak
buffers if reading as much data as we wanted failed and some
smaller cleanup.
2008-03-08 Sebastian Dröge <slomo@circular-chaos.org>
Patch by: Olivier Crete <tester at tester dot ca>

View file

@ -26,5 +26,6 @@ libgstmatroska_la_LIBADD = \
$(GST_PLUGINS_BASE_LIBS) \
$(GST_LIBS) \
-lgstriff-@GST_MAJORMINOR@ \
$(ZLIB_LIBS)
$(ZLIB_LIBS) \
$(LIBM)
libgstmatroska_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)

View file

@ -44,6 +44,7 @@ G_BEGIN_DECLS
/* general EBML types */
#define GST_EBML_ID_VOID 0xEC
#define GST_EBML_ID_CRC32 0xBF
/* EbmlDate offset from the unix epoch in seconds, 2001/01/01 00:00:00 UTC */
#define GST_EBML_DATE_OFFSET 978307200

View file

@ -28,6 +28,8 @@
#include "ebml-read.h"
#include "ebml-ids.h"
#include <math.h>
GST_DEBUG_CATEGORY_STATIC (ebmlread_debug);
#define GST_CAT_DEFAULT ebmlread_debug
@ -71,16 +73,35 @@ gst_ebml_read_get_type (void)
return gst_ebml_read_type;
}
static void
gst_ebml_finalize (GObject * obj)
{
GstEbmlRead *ebml = GST_EBML_READ (obj);
g_list_foreach (ebml->level, (GFunc) g_free, NULL);
g_list_free (ebml->level);
ebml->level = NULL;
if (ebml->cached_buffer) {
gst_buffer_unref (ebml->cached_buffer);
ebml->cached_buffer = NULL;
}
G_OBJECT_CLASS (parent_class)->finalize (obj);
}
static void
gst_ebml_read_class_init (GstEbmlReadClass * klass)
{
GstElementClass *gstelement_class = (GstElementClass *) klass;
GObjectClass *gobject_class = (GObjectClass *) klass;
parent_class = g_type_class_peek_parent (klass);
GST_DEBUG_CATEGORY_INIT (ebmlread_debug, "ebmlread",
0, "EBML stream helper class");
gobject_class->finalize = gst_ebml_finalize;
gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_ebml_read_change_state);
}
@ -205,27 +226,39 @@ gst_ebml_read_peek_bytes (GstEbmlRead * ebml, guint size, GstBuffer ** p_buf,
return GST_FLOW_OK;
}
/* FIXME, seems silly to require this */
if (!p_buf)
return GST_FLOW_ERROR;
/* Not possible to get enough data, try a last time with
* requesting exactly the size we need */
gst_buffer_unref (ebml->cached_buffer);
ebml->cached_buffer = NULL;
ret = gst_pad_pull_range (ebml->sinkpad, ebml->offset, size, p_buf);
ret =
gst_pad_pull_range (ebml->sinkpad, ebml->offset, size,
&ebml->cached_buffer);
if (ret != GST_FLOW_OK) {
GST_DEBUG ("pull_range returned %d", ret);
if (p_buf)
*p_buf = NULL;
if (bytes)
*bytes = NULL;
return ret;
}
if (GST_BUFFER_SIZE (*p_buf) < size) {
if (GST_BUFFER_SIZE (ebml->cached_buffer) < size) {
GST_WARNING_OBJECT (ebml, "Dropping short buffer at offset %"
G_GUINT64_FORMAT ": wanted %u bytes, got %u bytes", ebml->offset,
size, GST_BUFFER_SIZE (*p_buf));
gst_buffer_unref (*p_buf);
*p_buf = NULL;
size, GST_BUFFER_SIZE (ebml->cached_buffer));
gst_buffer_unref (ebml->cached_buffer);
ebml->cached_buffer = NULL;
if (p_buf)
*p_buf = NULL;
if (bytes)
*bytes = NULL;
return GST_FLOW_ERROR;
}
if (p_buf)
*p_buf = gst_buffer_create_sub (ebml->cached_buffer, 0, size);
if (bytes)
*bytes = GST_BUFFER_DATA (*p_buf);
@ -402,11 +435,10 @@ gst_ebml_read_get_length (GstEbmlRead * ebml)
GstFormat fmt = GST_FORMAT_BYTES;
gint64 end;
if (!gst_pad_query_duration (GST_PAD_PEER (ebml->sinkpad), &fmt, &end))
g_return_val_if_reached (0); ///// FIXME /////////
if (fmt != GST_FORMAT_BYTES || end < 0)
g_return_val_if_reached (0); ///// FIXME /////////
/* FIXME: what to do if we don't get the upstream length */
if (!gst_pad_query_peer_duration (ebml->sinkpad, &fmt, &end) ||
fmt != GST_FORMAT_BYTES || end < 0)
g_return_val_if_reached (0);
return end;
}
@ -592,6 +624,36 @@ gst_ebml_read_sint (GstEbmlRead * ebml, guint32 * id, gint64 * num)
return ret;
}
/* Convert 80 bit extended precision float in big endian format to double.
* Code taken from libavutil/intfloat_readwrite.c from ffmpeg,
* licensed under LGPL */
struct _ext_float
{
guint8 exponent[2];
guint8 mantissa[8];
};
static gdouble
_ext2dbl (guint8 * data)
{
struct _ext_float *ext = (struct _ext_float *) data;
guint64 m = 0;
gint e, i;
for (i = 0; i < 8; i++)
m = (m << 8) + ext->mantissa[i];
e = (((gint) ext->exponent[0] & 0x7f) << 8) | ext->exponent[1];
if (e == 0x7fff && m)
return 0.0 / 0.0;
e -= 16383 + 63; /* In IEEE 80 bits, the whole (i.e. 1.xxxx)
* mantissa bit is written as opposed to the
* single and double precision formats */
if (ext->exponent[0] & 0x80)
m = -m;
return ldexp (m, e);
}
/*
* Read the next element as a float.
*/
@ -615,12 +677,6 @@ gst_ebml_read_float (GstEbmlRead * ebml, guint32 * id, gdouble * num)
return GST_FLOW_ERROR;
}
if (size == 10) {
GST_ELEMENT_ERROR (ebml, CORE, NOT_IMPLEMENTED, (NULL),
("FIXME! 10-byte floats unimplemented"));
return GST_FLOW_NOT_SUPPORTED;
}
if (size == 4) {
gfloat f;
@ -634,7 +690,7 @@ gst_ebml_read_float (GstEbmlRead * ebml, guint32 * id, gdouble * num)
#endif
*num = f;
} else {
} else if (size == 8) {
gdouble d;
#if (G_BYTE_ORDER == G_BIG_ENDIAN)
@ -647,6 +703,8 @@ gst_ebml_read_float (GstEbmlRead * ebml, guint32 * id, gdouble * num)
#endif
*num = d;
} else {
*num = _ext2dbl (data);
}
return ret;
@ -835,7 +893,7 @@ gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version)
if (ret != GST_FLOW_OK)
return ret;
g_assert (id == GST_EBML_ID_EBMLMAXSIZELENGTH);
if (num != sizeof (guint64)) {
if (num > sizeof (guint64)) {
GST_ELEMENT_ERROR (ebml, STREAM, WRONG_TYPE, (NULL), (NULL));
return GST_FLOW_ERROR;
}
@ -850,7 +908,7 @@ gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version)
if (ret != GST_FLOW_OK)
return ret;
g_assert (id == GST_EBML_ID_EBMLMAXIDLENGTH);
if (num != sizeof (guint32)) {
if (num > sizeof (guint32)) {
GST_ELEMENT_ERROR (ebml, STREAM, WRONG_TYPE, (NULL), (NULL));
return GST_FLOW_ERROR;
}
@ -865,8 +923,7 @@ gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version)
return ret;
g_assert (id == GST_EBML_ID_DOCTYPE);
if (doctype) {
if (doctype)
g_free (*doctype);
g_free (*doctype);
*doctype = text;
} else
g_free (text);