mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 06:54:49 +00:00
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:
parent
c7296fe79a
commit
8342c0cc96
4 changed files with 100 additions and 25 deletions
16
ChangeLog
16
ChangeLog
|
@ -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>
|
2008-03-08 Sebastian Dröge <slomo@circular-chaos.org>
|
||||||
|
|
||||||
Patch by: Olivier Crete <tester at tester dot ca>
|
Patch by: Olivier Crete <tester at tester dot ca>
|
||||||
|
|
|
@ -26,5 +26,6 @@ libgstmatroska_la_LIBADD = \
|
||||||
$(GST_PLUGINS_BASE_LIBS) \
|
$(GST_PLUGINS_BASE_LIBS) \
|
||||||
$(GST_LIBS) \
|
$(GST_LIBS) \
|
||||||
-lgstriff-@GST_MAJORMINOR@ \
|
-lgstriff-@GST_MAJORMINOR@ \
|
||||||
$(ZLIB_LIBS)
|
$(ZLIB_LIBS) \
|
||||||
|
$(LIBM)
|
||||||
libgstmatroska_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
libgstmatroska_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||||
|
|
|
@ -44,6 +44,7 @@ G_BEGIN_DECLS
|
||||||
|
|
||||||
/* general EBML types */
|
/* general EBML types */
|
||||||
#define GST_EBML_ID_VOID 0xEC
|
#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 */
|
/* EbmlDate offset from the unix epoch in seconds, 2001/01/01 00:00:00 UTC */
|
||||||
#define GST_EBML_DATE_OFFSET 978307200
|
#define GST_EBML_DATE_OFFSET 978307200
|
||||||
|
|
|
@ -28,6 +28,8 @@
|
||||||
#include "ebml-read.h"
|
#include "ebml-read.h"
|
||||||
#include "ebml-ids.h"
|
#include "ebml-ids.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_STATIC (ebmlread_debug);
|
GST_DEBUG_CATEGORY_STATIC (ebmlread_debug);
|
||||||
#define GST_CAT_DEFAULT ebmlread_debug
|
#define GST_CAT_DEFAULT ebmlread_debug
|
||||||
|
|
||||||
|
@ -71,16 +73,35 @@ gst_ebml_read_get_type (void)
|
||||||
return gst_ebml_read_type;
|
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
|
static void
|
||||||
gst_ebml_read_class_init (GstEbmlReadClass * klass)
|
gst_ebml_read_class_init (GstEbmlReadClass * klass)
|
||||||
{
|
{
|
||||||
GstElementClass *gstelement_class = (GstElementClass *) klass;
|
GstElementClass *gstelement_class = (GstElementClass *) klass;
|
||||||
|
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||||
|
|
||||||
parent_class = g_type_class_peek_parent (klass);
|
parent_class = g_type_class_peek_parent (klass);
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_INIT (ebmlread_debug, "ebmlread",
|
GST_DEBUG_CATEGORY_INIT (ebmlread_debug, "ebmlread",
|
||||||
0, "EBML stream helper class");
|
0, "EBML stream helper class");
|
||||||
|
|
||||||
|
gobject_class->finalize = gst_ebml_finalize;
|
||||||
|
|
||||||
gstelement_class->change_state =
|
gstelement_class->change_state =
|
||||||
GST_DEBUG_FUNCPTR (gst_ebml_read_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;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME, seems silly to require this */
|
/* Not possible to get enough data, try a last time with
|
||||||
if (!p_buf)
|
* requesting exactly the size we need */
|
||||||
return GST_FLOW_ERROR;
|
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) {
|
if (ret != GST_FLOW_OK) {
|
||||||
GST_DEBUG ("pull_range returned %d", ret);
|
GST_DEBUG ("pull_range returned %d", ret);
|
||||||
|
if (p_buf)
|
||||||
|
*p_buf = NULL;
|
||||||
|
if (bytes)
|
||||||
|
*bytes = NULL;
|
||||||
return ret;
|
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 %"
|
GST_WARNING_OBJECT (ebml, "Dropping short buffer at offset %"
|
||||||
G_GUINT64_FORMAT ": wanted %u bytes, got %u bytes", ebml->offset,
|
G_GUINT64_FORMAT ": wanted %u bytes, got %u bytes", ebml->offset,
|
||||||
size, GST_BUFFER_SIZE (*p_buf));
|
size, GST_BUFFER_SIZE (ebml->cached_buffer));
|
||||||
gst_buffer_unref (*p_buf);
|
|
||||||
*p_buf = NULL;
|
gst_buffer_unref (ebml->cached_buffer);
|
||||||
|
ebml->cached_buffer = NULL;
|
||||||
|
if (p_buf)
|
||||||
|
*p_buf = NULL;
|
||||||
if (bytes)
|
if (bytes)
|
||||||
*bytes = NULL;
|
*bytes = NULL;
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p_buf)
|
||||||
|
*p_buf = gst_buffer_create_sub (ebml->cached_buffer, 0, size);
|
||||||
if (bytes)
|
if (bytes)
|
||||||
*bytes = GST_BUFFER_DATA (*p_buf);
|
*bytes = GST_BUFFER_DATA (*p_buf);
|
||||||
|
|
||||||
|
@ -402,11 +435,10 @@ gst_ebml_read_get_length (GstEbmlRead * ebml)
|
||||||
GstFormat fmt = GST_FORMAT_BYTES;
|
GstFormat fmt = GST_FORMAT_BYTES;
|
||||||
gint64 end;
|
gint64 end;
|
||||||
|
|
||||||
if (!gst_pad_query_duration (GST_PAD_PEER (ebml->sinkpad), &fmt, &end))
|
/* FIXME: what to do if we don't get the upstream length */
|
||||||
g_return_val_if_reached (0); ///// FIXME /////////
|
if (!gst_pad_query_peer_duration (ebml->sinkpad, &fmt, &end) ||
|
||||||
|
fmt != GST_FORMAT_BYTES || end < 0)
|
||||||
if (fmt != GST_FORMAT_BYTES || end < 0)
|
g_return_val_if_reached (0);
|
||||||
g_return_val_if_reached (0); ///// FIXME /////////
|
|
||||||
|
|
||||||
return end;
|
return end;
|
||||||
}
|
}
|
||||||
|
@ -592,6 +624,36 @@ gst_ebml_read_sint (GstEbmlRead * ebml, guint32 * id, gint64 * num)
|
||||||
return ret;
|
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.
|
* 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;
|
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) {
|
if (size == 4) {
|
||||||
gfloat f;
|
gfloat f;
|
||||||
|
|
||||||
|
@ -634,7 +690,7 @@ gst_ebml_read_float (GstEbmlRead * ebml, guint32 * id, gdouble * num)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
*num = f;
|
*num = f;
|
||||||
} else {
|
} else if (size == 8) {
|
||||||
gdouble d;
|
gdouble d;
|
||||||
|
|
||||||
#if (G_BYTE_ORDER == G_BIG_ENDIAN)
|
#if (G_BYTE_ORDER == G_BIG_ENDIAN)
|
||||||
|
@ -647,6 +703,8 @@ gst_ebml_read_float (GstEbmlRead * ebml, guint32 * id, gdouble * num)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
*num = d;
|
*num = d;
|
||||||
|
} else {
|
||||||
|
*num = _ext2dbl (data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -835,7 +893,7 @@ gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version)
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
return ret;
|
return ret;
|
||||||
g_assert (id == GST_EBML_ID_EBMLMAXSIZELENGTH);
|
g_assert (id == GST_EBML_ID_EBMLMAXSIZELENGTH);
|
||||||
if (num != sizeof (guint64)) {
|
if (num > sizeof (guint64)) {
|
||||||
GST_ELEMENT_ERROR (ebml, STREAM, WRONG_TYPE, (NULL), (NULL));
|
GST_ELEMENT_ERROR (ebml, STREAM, WRONG_TYPE, (NULL), (NULL));
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -850,7 +908,7 @@ gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version)
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
return ret;
|
return ret;
|
||||||
g_assert (id == GST_EBML_ID_EBMLMAXIDLENGTH);
|
g_assert (id == GST_EBML_ID_EBMLMAXIDLENGTH);
|
||||||
if (num != sizeof (guint32)) {
|
if (num > sizeof (guint32)) {
|
||||||
GST_ELEMENT_ERROR (ebml, STREAM, WRONG_TYPE, (NULL), (NULL));
|
GST_ELEMENT_ERROR (ebml, STREAM, WRONG_TYPE, (NULL), (NULL));
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -865,8 +923,7 @@ gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version)
|
||||||
return ret;
|
return ret;
|
||||||
g_assert (id == GST_EBML_ID_DOCTYPE);
|
g_assert (id == GST_EBML_ID_DOCTYPE);
|
||||||
if (doctype) {
|
if (doctype) {
|
||||||
if (doctype)
|
g_free (*doctype);
|
||||||
g_free (*doctype);
|
|
||||||
*doctype = text;
|
*doctype = text;
|
||||||
} else
|
} else
|
||||||
g_free (text);
|
g_free (text);
|
||||||
|
|
Loading…
Reference in a new issue