diff options
Diffstat (limited to 'gst/matroska/ebml-read.c')
-rw-r--r-- | gst/matroska/ebml-read.c | 305 |
1 files changed, 186 insertions, 119 deletions
diff --git a/gst/matroska/ebml-read.c b/gst/matroska/ebml-read.c index 9c5ae4a6..5335c555 100644 --- a/gst/matroska/ebml-read.c +++ b/gst/matroska/ebml-read.c @@ -162,7 +162,7 @@ gst_ebml_read_element_level_up (GstEbmlRead * ebml) /* * Calls pull_range for (offset,size) without advancing our offset */ -static gboolean +static GstFlowReturn gst_ebml_read_peek_bytes (GstEbmlRead * ebml, guint size, GstBuffer ** p_buf, guint8 ** bytes) { @@ -182,29 +182,37 @@ gst_ebml_read_peek_bytes (GstEbmlRead * ebml, guint size, GstBuffer ** p_buf, if (bytes) *bytes = GST_BUFFER_DATA (ebml->cached_buffer) + ebml->offset - cache_offset; - return TRUE; + return GST_FLOW_OK; } + /* not enough data in the cache, free cache and get a new one */ gst_buffer_unref (ebml->cached_buffer); ebml->cached_buffer = NULL; } - if (gst_pad_pull_range (ebml->sinkpad, ebml->offset, MAX (size, 64 * 1024), - &ebml->cached_buffer) == GST_FLOW_OK && - GST_BUFFER_SIZE (ebml->cached_buffer) >= size) { + /* refill the cache */ + ret = gst_pad_pull_range (ebml->sinkpad, ebml->offset, MAX (size, 64 * 1024), + &ebml->cached_buffer); + if (ret != GST_FLOW_OK) { + ebml->cached_buffer = NULL; + return ret; + } + + if (GST_BUFFER_SIZE (ebml->cached_buffer) >= size) { if (p_buf) *p_buf = gst_buffer_create_sub (ebml->cached_buffer, 0, size); if (bytes) *bytes = GST_BUFFER_DATA (ebml->cached_buffer); - return TRUE; + return GST_FLOW_OK; } + /* FIXME, seems silly to require this */ if (!p_buf) - return FALSE; + return GST_FLOW_ERROR; ret = gst_pad_pull_range (ebml->sinkpad, ebml->offset, size, p_buf); if (ret != GST_FLOW_OK) { GST_DEBUG ("pull_range returned %d", ret); - return FALSE; + return ret; } if (GST_BUFFER_SIZE (*p_buf) < size) { @@ -215,27 +223,30 @@ gst_ebml_read_peek_bytes (GstEbmlRead * ebml, guint size, GstBuffer ** p_buf, *p_buf = NULL; if (bytes) *bytes = NULL; - return FALSE; + return GST_FLOW_ERROR; } if (bytes) *bytes = GST_BUFFER_DATA (*p_buf); - return TRUE; + return GST_FLOW_OK; } /* * Calls pull_range for (offset,size) and advances our offset by size */ -static gboolean +static GstFlowReturn gst_ebml_read_pull_bytes (GstEbmlRead * ebml, guint size, GstBuffer ** p_buf, guint8 ** bytes) { - if (!gst_ebml_read_peek_bytes (ebml, size, p_buf, bytes)) - return FALSE; + GstFlowReturn ret; + + ret = gst_ebml_read_peek_bytes (ebml, size, p_buf, bytes); + if (ret != GST_FLOW_OK) + return ret; ebml->offset += size; - return TRUE; + return GST_FLOW_OK; } /* @@ -243,16 +254,18 @@ gst_ebml_read_pull_bytes (GstEbmlRead * ebml, guint size, GstBuffer ** p_buf, * Return: FALSE on error. */ -static gboolean +static GstFlowReturn gst_ebml_read_element_id (GstEbmlRead * ebml, guint32 * id, guint * level_up) { guint8 *buf; gint len_mask = 0x80, read = 1, n = 1; guint32 total; guint8 b; + GstFlowReturn ret; - if (!gst_ebml_read_peek_bytes (ebml, 1, NULL, &buf)) - return FALSE; + ret = gst_ebml_read_peek_bytes (ebml, 1, NULL, &buf); + if (ret != GST_FLOW_OK) + return ret; b = GST_READ_UINT8 (buf); @@ -268,11 +281,12 @@ gst_ebml_read_element_id (GstEbmlRead * ebml, guint32 * id, guint * level_up) GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL), ("Invalid EBML ID size tag (0x%x) at position %" G_GUINT64_FORMAT " (0x%" G_GINT64_MODIFIER "x)", (guint) b, pos, pos)); - return FALSE; + return GST_FLOW_ERROR; } - if (!gst_ebml_read_peek_bytes (ebml, read, NULL, &buf)) - return FALSE; + ret = gst_ebml_read_peek_bytes (ebml, read, NULL, &buf); + if (ret != GST_FLOW_OK) + return ret; while (n < read) { b = GST_READ_UINT8 (buf + n); @@ -287,7 +301,7 @@ gst_ebml_read_element_id (GstEbmlRead * ebml, guint32 * id, guint * level_up) *level_up = gst_ebml_read_element_level_up (ebml); ebml->offset += read; - return TRUE; + return GST_FLOW_OK; } /* @@ -295,16 +309,19 @@ gst_ebml_read_element_id (GstEbmlRead * ebml, guint32 * id, guint * level_up) * Return: the number of bytes read or -1 on error. */ -static gint -gst_ebml_read_element_length (GstEbmlRead * ebml, guint64 * length) +static GstFlowReturn +gst_ebml_read_element_length (GstEbmlRead * ebml, guint64 * length, + gint * rread) { + GstFlowReturn ret; guint8 *buf; gint len_mask = 0x80, read = 1, n = 1, num_ffs = 0; guint64 total; guint8 b; - if (!gst_ebml_read_peek_bytes (ebml, 1, NULL, &buf)) - return -1; + ret = gst_ebml_read_peek_bytes (ebml, 1, NULL, &buf); + if (ret != GST_FLOW_OK) + return ret; b = GST_READ_UINT8 (buf); @@ -320,14 +337,15 @@ gst_ebml_read_element_length (GstEbmlRead * ebml, guint64 * length) GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL), ("Invalid EBML length size tag (0x%x) at position %" G_GUINT64_FORMAT " (0x%" G_GINT64_MODIFIER "x)", (guint) b, pos, pos)); - return -1; + return GST_FLOW_ERROR; } if ((total &= (len_mask - 1)) == len_mask - 1) num_ffs++; - if (!gst_ebml_read_peek_bytes (ebml, read, NULL, &buf)) - return -1; + ret = gst_ebml_read_peek_bytes (ebml, read, NULL, &buf); + if (ret != GST_FLOW_OK) + return ret; while (n < read) { guint8 b = GST_READ_UINT8 (buf + n); @@ -343,9 +361,12 @@ gst_ebml_read_element_length (GstEbmlRead * ebml, guint64 * length) else *length = total; + if (rread) + *rread = read; + ebml->offset += read; - return read; + return GST_FLOW_OK; } /* @@ -354,20 +375,21 @@ gst_ebml_read_element_length (GstEbmlRead * ebml, guint64 * length) * next element lies higher than the previous one. */ -gboolean +GstFlowReturn gst_ebml_peek_id (GstEbmlRead * ebml, guint * level_up, guint32 * id) { guint64 off; + GstFlowReturn ret; g_assert (level_up); off = ebml->offset; /* save offset */ - if (!gst_ebml_read_element_id (ebml, id, level_up)) - return FALSE; + if ((ret = gst_ebml_read_element_id (ebml, id, level_up)) != GST_FLOW_OK) + return ret; ebml->offset = off; /* restore offset */ - return TRUE; + return ret; } /* @@ -408,100 +430,111 @@ gst_ebml_read_seek (GstEbmlRead * ebml, guint64 offset) * Skip the next element. */ -gboolean +GstFlowReturn gst_ebml_read_skip (GstEbmlRead * ebml) { guint64 length; guint32 id; + GstFlowReturn ret; - if (!gst_ebml_read_element_id (ebml, &id, NULL)) - return FALSE; + ret = gst_ebml_read_element_id (ebml, &id, NULL); + if (ret != GST_FLOW_OK) + return ret; - if (gst_ebml_read_element_length (ebml, &length) < 0) - return FALSE; + ret = gst_ebml_read_element_length (ebml, &length, NULL); + if (ret != GST_FLOW_OK) + return ret; ebml->offset += length; - return TRUE; + return ret; } /* * Read the next element as a GstBuffer (binary). */ -gboolean +GstFlowReturn gst_ebml_read_buffer (GstEbmlRead * ebml, guint32 * id, GstBuffer ** buf) { guint64 length; + GstFlowReturn ret; - if (!gst_ebml_read_element_id (ebml, id, NULL)) - return FALSE; + ret = gst_ebml_read_element_id (ebml, id, NULL); + if (ret != GST_FLOW_OK) + return ret; - if (gst_ebml_read_element_length (ebml, &length) < 0) - return FALSE; + ret = gst_ebml_read_element_length (ebml, &length, NULL); + if (ret != GST_FLOW_OK) + return ret; if (length == 0) { *buf = gst_buffer_new (); - return TRUE; + return GST_FLOW_OK; } *buf = NULL; - if (!gst_ebml_read_pull_bytes (ebml, (guint) length, buf, NULL)) - return FALSE; + ret = gst_ebml_read_pull_bytes (ebml, (guint) length, buf, NULL); - return TRUE; + return ret; } /* * Read the next element, return a pointer to it and its size. */ -static gboolean +static GstFlowReturn gst_ebml_read_bytes (GstEbmlRead * ebml, guint32 * id, guint8 ** data, guint * size) { guint64 length; + GstFlowReturn ret; *size = 0; - if (!gst_ebml_read_element_id (ebml, id, NULL)) - return FALSE; + ret = gst_ebml_read_element_id (ebml, id, NULL); + if (ret != GST_FLOW_OK) + return ret; - if (gst_ebml_read_element_length (ebml, &length) < 0) - return FALSE; + ret = gst_ebml_read_element_length (ebml, &length, NULL); + if (ret != GST_FLOW_OK) + return ret; if (length == 0) { *data = NULL; - return TRUE; + return ret; } *data = NULL; - if (!gst_ebml_read_pull_bytes (ebml, (guint) length, NULL, data)) - return FALSE; + ret = gst_ebml_read_pull_bytes (ebml, (guint) length, NULL, data); + if (ret != GST_FLOW_OK) + return ret; *size = (guint) length; - return TRUE; + return ret; } /* * Read the next element as an unsigned int. */ -gboolean +GstFlowReturn gst_ebml_read_uint (GstEbmlRead * ebml, guint32 * id, guint64 * num) { guint8 *data; guint size; + GstFlowReturn ret; - if (!gst_ebml_read_bytes (ebml, id, &data, &size)) - return FALSE; + ret = gst_ebml_read_bytes (ebml, id, &data, &size); + if (ret != GST_FLOW_OK) + return ret; if (size < 1 || size > 8) { GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL), ("Invalid integer element size %d at position %" G_GUINT64_FORMAT " (0x%" G_GINT64_MODIFIER "x)", size, ebml->offset - size, ebml->offset - size)); - return FALSE; + return GST_FLOW_ERROR; } *num = 0; while (size > 0) { @@ -510,29 +543,31 @@ gst_ebml_read_uint (GstEbmlRead * ebml, guint32 * id, guint64 * num) data++; } - return TRUE; + return ret; } /* * Read the next element as a signed int. */ -gboolean +GstFlowReturn gst_ebml_read_sint (GstEbmlRead * ebml, guint32 * id, gint64 * num) { guint8 *data; guint size; gboolean negative = 0; + GstFlowReturn ret; - if (!gst_ebml_read_bytes (ebml, id, &data, &size)) - return FALSE; + ret = gst_ebml_read_bytes (ebml, id, &data, &size); + if (ret != GST_FLOW_OK) + return ret; if (size < 1 || size > 8) { GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL), ("Invalid integer element size %d at position %" G_GUINT64_FORMAT " (0x%" G_GINT64_MODIFIER "x)", size, ebml->offset - size, ebml->offset - size)); - return FALSE; + return GST_FLOW_ERROR; } *num = 0; @@ -554,34 +589,36 @@ gst_ebml_read_sint (GstEbmlRead * ebml, guint32 * id, gint64 * num) *num = 0 - *num; } - return TRUE; + return ret; } /* * Read the next element as a float. */ -gboolean +GstFlowReturn gst_ebml_read_float (GstEbmlRead * ebml, guint32 * id, gdouble * num) { guint8 *data; guint size; + GstFlowReturn ret; - if (!gst_ebml_read_bytes (ebml, id, &data, &size)) - return FALSE; + ret = gst_ebml_read_bytes (ebml, id, &data, &size); + if (ret != GST_FLOW_OK) + return ret; if (size != 4 && size != 8 && size != 10) { GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL), ("Invalid float element size %d at position %" G_GUINT64_FORMAT " (0x%" G_GINT64_MODIFIER "x)", size, ebml->offset - size, ebml->offset - size)); - return FALSE; + return GST_FLOW_ERROR; } if (size == 10) { GST_ELEMENT_ERROR (ebml, CORE, NOT_IMPLEMENTED, (NULL), ("FIXME! 10-byte floats unimplemented")); - return FALSE; + return GST_FLOW_NOT_SUPPORTED; } if (size == 4) { @@ -612,43 +649,47 @@ gst_ebml_read_float (GstEbmlRead * ebml, guint32 * id, gdouble * num) *num = d; } - return TRUE; + return ret; } /* * Read the next element as an ASCII string. */ -gboolean +GstFlowReturn gst_ebml_read_ascii (GstEbmlRead * ebml, guint32 * id, gchar ** str) { guint8 *data; guint size; + GstFlowReturn ret; - if (!gst_ebml_read_bytes (ebml, id, &data, &size)) - return FALSE; + ret = gst_ebml_read_bytes (ebml, id, &data, &size); + if (ret != GST_FLOW_OK) + return ret; *str = g_malloc (size + 1); memcpy (*str, data, size); (*str)[size] = '\0'; - return TRUE; + return ret; } /* * Read the next element as a UTF-8 string. */ -gboolean +GstFlowReturn gst_ebml_read_utf8 (GstEbmlRead * ebml, guint32 * id, gchar ** str) { - gboolean ret; + GstFlowReturn ret; #ifndef GST_DISABLE_GST_DEBUG guint64 oldoff = ebml->offset; #endif ret = gst_ebml_read_ascii (ebml, id, str); + if (ret != GST_FLOW_OK) + return ret; if (str != NULL && *str != NULL && **str != '\0' && !g_utf8_validate (*str, -1, NULL)) { @@ -663,14 +704,19 @@ gst_ebml_read_utf8 (GstEbmlRead * ebml, guint32 * id, gchar ** str) * Returns the seconds since the unix epoch. */ -gboolean +GstFlowReturn gst_ebml_read_date (GstEbmlRead * ebml, guint32 * id, gint64 * date) { gint64 ebml_date; - gboolean res = gst_ebml_read_sint (ebml, id, &ebml_date); + GstFlowReturn ret; + + ret = gst_ebml_read_sint (ebml, id, &ebml_date); + if (ret != GST_FLOW_OK) + return ret; *date = (ebml_date / GST_SECOND) + GST_EBML_DATE_OFFSET; - return res; + + return ret; } /* @@ -678,17 +724,20 @@ gst_ebml_read_date (GstEbmlRead * ebml, guint32 * id, gint64 * date) * are supposed to be sub-elements which can be read separately. */ -gboolean +GstFlowReturn gst_ebml_read_master (GstEbmlRead * ebml, guint32 * id) { GstEbmlLevel *level; guint64 length; + GstFlowReturn ret; - if (!gst_ebml_read_element_id (ebml, id, NULL)) - return FALSE; + ret = gst_ebml_read_element_id (ebml, id, NULL); + if (ret != GST_FLOW_OK) + return ret; - if (gst_ebml_read_element_length (ebml, &length) < 0) - return FALSE; + ret = gst_ebml_read_element_length (ebml, &length, NULL); + if (ret != GST_FLOW_OK) + return ret; /* remember level */ level = g_new (GstEbmlLevel, 1); @@ -696,39 +745,42 @@ gst_ebml_read_master (GstEbmlRead * ebml, guint32 * id) level->length = length; ebml->level = g_list_append (ebml->level, level); - return TRUE; + return GST_FLOW_OK; } /* * Read the next element as binary data. */ -gboolean +GstFlowReturn gst_ebml_read_binary (GstEbmlRead * ebml, guint32 * id, guint8 ** binary, guint64 * length) { guint8 *data; guint size; + GstFlowReturn ret; - if (!gst_ebml_read_bytes (ebml, id, &data, &size)) - return FALSE; + ret = gst_ebml_read_bytes (ebml, id, &data, &size); + if (ret != GST_FLOW_OK) + return ret; *length = size; *binary = g_memdup (data, size); - return TRUE; + return GST_FLOW_OK; } /* * Read an EBML header. */ -gboolean +GstFlowReturn gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version) { /* this function is the first to be called */ guint32 id; guint level_up; + GstFlowReturn ret; /* default init */ if (doctype) @@ -736,21 +788,24 @@ gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version) if (version) *version = 1; - if (!gst_ebml_peek_id (ebml, &level_up, &id)) - return FALSE; + ret = gst_ebml_peek_id (ebml, &level_up, &id); + if (ret != GST_FLOW_OK) + return ret; GST_DEBUG_OBJECT (ebml, "id: %08x", GST_READ_UINT32_BE (&id)); if (level_up != 0 || id != GST_EBML_ID_HEADER) { GST_ELEMENT_ERROR (ebml, STREAM, WRONG_TYPE, (NULL), (NULL)); - return FALSE; + return GST_FLOW_ERROR; } - if (!gst_ebml_read_master (ebml, &id)) - return FALSE; + ret = gst_ebml_read_master (ebml, &id); + if (ret != GST_FLOW_OK) + return ret; while (TRUE) { - if (!gst_ebml_peek_id (ebml, &level_up, &id)) - return FALSE; + ret = gst_ebml_peek_id (ebml, &level_up, &id); + if (ret != GST_FLOW_OK) + return ret; /* end-of-header */ if (level_up) @@ -761,11 +816,14 @@ gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version) case GST_EBML_ID_EBMLREADVERSION:{ guint64 num; - if (!gst_ebml_read_uint (ebml, &id, &num)) - return FALSE; + ret = gst_ebml_read_uint (ebml, &id, &num); + if (ret != GST_FLOW_OK) + return ret; g_assert (id == GST_EBML_ID_EBMLREADVERSION); - if (num != GST_EBML_VERSION) - return FALSE; + if (num != GST_EBML_VERSION) { + GST_ELEMENT_ERROR (ebml, STREAM, WRONG_TYPE, (NULL), (NULL)); + return GST_FLOW_ERROR; + } break; } @@ -773,11 +831,14 @@ gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version) case GST_EBML_ID_EBMLMAXSIZELENGTH:{ guint64 num; - if (!gst_ebml_read_uint (ebml, &id, &num)) - return FALSE; + ret = gst_ebml_read_uint (ebml, &id, &num); + if (ret != GST_FLOW_OK) + return ret; g_assert (id == GST_EBML_ID_EBMLMAXSIZELENGTH); - if (num != sizeof (guint64)) - return FALSE; + if (num != sizeof (guint64)) { + GST_ELEMENT_ERROR (ebml, STREAM, WRONG_TYPE, (NULL), (NULL)); + return GST_FLOW_ERROR; + } break; } @@ -785,19 +846,23 @@ gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version) case GST_EBML_ID_EBMLMAXIDLENGTH:{ guint64 num; - if (!gst_ebml_read_uint (ebml, &id, &num)) - return FALSE; + ret = gst_ebml_read_uint (ebml, &id, &num); + if (ret != GST_FLOW_OK) + return ret; g_assert (id == GST_EBML_ID_EBMLMAXIDLENGTH); - if (num != sizeof (guint32)) - return FALSE; + if (num != sizeof (guint32)) { + GST_ELEMENT_ERROR (ebml, STREAM, WRONG_TYPE, (NULL), (NULL)); + return GST_FLOW_ERROR; + } break; } case GST_EBML_ID_DOCTYPE:{ gchar *text; - if (!gst_ebml_read_ascii (ebml, &id, &text)) - return FALSE; + ret = gst_ebml_read_ascii (ebml, &id, &text); + if (ret != GST_FLOW_OK) + return ret; g_assert (id == GST_EBML_ID_DOCTYPE); if (doctype) { if (doctype) @@ -811,8 +876,9 @@ gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version) case GST_EBML_ID_DOCTYPEREADVERSION:{ guint64 num; - if (!gst_ebml_read_uint (ebml, &id, &num)) - return FALSE; + ret = gst_ebml_read_uint (ebml, &id, &num); + if (ret != GST_FLOW_OK) + return ret; g_assert (id == GST_EBML_ID_DOCTYPEREADVERSION); if (version) *version = num; @@ -827,11 +893,12 @@ gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version) case GST_EBML_ID_VOID: case GST_EBML_ID_EBMLVERSION: case GST_EBML_ID_DOCTYPEVERSION: - if (!gst_ebml_read_skip (ebml)) - return FALSE; + ret = gst_ebml_read_skip (ebml); + if (ret != GST_FLOW_OK) + return ret; break; } } - return TRUE; + return GST_FLOW_OK; } |