gst/matroska/: Handle return values from pull_range in a more granular way to properly shut down on seeks.

Original commit message from CVS:
* gst/matroska/ebml-read.c: (gst_ebml_read_peek_bytes),
(gst_ebml_read_pull_bytes), (gst_ebml_read_element_id),
(gst_ebml_read_element_length), (gst_ebml_peek_id),
(gst_ebml_read_skip), (gst_ebml_read_buffer),
(gst_ebml_read_bytes), (gst_ebml_read_uint), (gst_ebml_read_sint),
(gst_ebml_read_float), (gst_ebml_read_ascii), (gst_ebml_read_utf8),
(gst_ebml_read_date), (gst_ebml_read_master),
(gst_ebml_read_binary), (gst_ebml_read_header):
* gst/matroska/ebml-read.h:
* gst/matroska/matroska-demux.c:
(gst_matroska_demux_combine_flows), (gst_matroska_demux_reset),
(gst_matroska_demux_read_track_encodings),
(gst_matroska_demux_add_stream),
(gst_matroska_demux_handle_src_query),
(gst_matroska_demux_handle_seek_event),
(gst_matroska_demux_init_stream),
(gst_matroska_demux_parse_tracks),
(gst_matroska_demux_parse_index_cuetrack),
(gst_matroska_demux_parse_index_pointentry),
(gst_matroska_demux_parse_index), (gst_matroska_demux_parse_info),
(gst_matroska_demux_parse_metadata_id_simple_tag),
(gst_matroska_demux_parse_metadata_id_tag),
(gst_matroska_demux_parse_metadata),
(gst_matroska_demux_sync_streams),
(gst_matroska_demux_push_hdr_buf),
(gst_matroska_demux_push_flac_codec_priv_data),
(gst_matroska_demux_push_xiph_codec_priv_data),
(gst_matroska_demux_add_wvpk_header),
(gst_matroska_demux_check_subtitle_buffer),
(gst_matroska_demux_parse_blockgroup_or_simpleblock),
(gst_matroska_demux_parse_cluster),
(gst_matroska_demux_parse_contents_seekentry),
(gst_matroska_demux_parse_contents),
(gst_matroska_demux_loop_stream_parse_id),
(gst_matroska_demux_loop_stream), (gst_matroska_demux_loop):
* gst/matroska/matroska-demux.h:
* gst/matroska/matroska-ids.h:
Handle return values from pull_range in a more granular way to properly
shut down on seeks.
Combine return values from push.
Implement proper error handling.
Prepare for handling seeking correctly.
This commit is contained in:
Wim Taymans 2008-03-06 19:47:48 +00:00
parent edda3b6c0f
commit 1e61eb7e5f
7 changed files with 785 additions and 671 deletions

View file

@ -1,3 +1,48 @@
2008-03-06 Wim Taymans <wim.taymans@collabora.co.uk>
* gst/matroska/ebml-read.c: (gst_ebml_read_peek_bytes),
(gst_ebml_read_pull_bytes), (gst_ebml_read_element_id),
(gst_ebml_read_element_length), (gst_ebml_peek_id),
(gst_ebml_read_skip), (gst_ebml_read_buffer),
(gst_ebml_read_bytes), (gst_ebml_read_uint), (gst_ebml_read_sint),
(gst_ebml_read_float), (gst_ebml_read_ascii), (gst_ebml_read_utf8),
(gst_ebml_read_date), (gst_ebml_read_master),
(gst_ebml_read_binary), (gst_ebml_read_header):
* gst/matroska/ebml-read.h:
* gst/matroska/matroska-demux.c:
(gst_matroska_demux_combine_flows), (gst_matroska_demux_reset),
(gst_matroska_demux_read_track_encodings),
(gst_matroska_demux_add_stream),
(gst_matroska_demux_handle_src_query),
(gst_matroska_demux_handle_seek_event),
(gst_matroska_demux_init_stream),
(gst_matroska_demux_parse_tracks),
(gst_matroska_demux_parse_index_cuetrack),
(gst_matroska_demux_parse_index_pointentry),
(gst_matroska_demux_parse_index), (gst_matroska_demux_parse_info),
(gst_matroska_demux_parse_metadata_id_simple_tag),
(gst_matroska_demux_parse_metadata_id_tag),
(gst_matroska_demux_parse_metadata),
(gst_matroska_demux_sync_streams),
(gst_matroska_demux_push_hdr_buf),
(gst_matroska_demux_push_flac_codec_priv_data),
(gst_matroska_demux_push_xiph_codec_priv_data),
(gst_matroska_demux_add_wvpk_header),
(gst_matroska_demux_check_subtitle_buffer),
(gst_matroska_demux_parse_blockgroup_or_simpleblock),
(gst_matroska_demux_parse_cluster),
(gst_matroska_demux_parse_contents_seekentry),
(gst_matroska_demux_parse_contents),
(gst_matroska_demux_loop_stream_parse_id),
(gst_matroska_demux_loop_stream), (gst_matroska_demux_loop):
* gst/matroska/matroska-demux.h:
* gst/matroska/matroska-ids.h:
Handle return values from pull_range in a more granular way to properly
shut down on seeks.
Combine return values from push.
Implement proper error handling.
Prepare for handling seeking correctly.
2008-03-03 Jan Schmidt <jan.schmidt@sun.com> 2008-03-03 Jan Schmidt <jan.schmidt@sun.com>
* gst/matroska/ebml-read.c: * gst/matroska/ebml-read.c:

2
common

@ -1 +1 @@
Subproject commit 081a00a5e25d069b15bb7f6092c8f951462cd8eb Subproject commit e02bd43fe6b9e45536eccbf5b7a5f9eae62030fd

View file

@ -162,7 +162,7 @@ gst_ebml_read_element_level_up (GstEbmlRead * ebml)
/* /*
* Calls pull_range for (offset,size) without advancing our offset * 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, gst_ebml_read_peek_bytes (GstEbmlRead * ebml, guint size, GstBuffer ** p_buf,
guint8 ** bytes) guint8 ** bytes)
{ {
@ -182,29 +182,37 @@ gst_ebml_read_peek_bytes (GstEbmlRead * ebml, guint size, GstBuffer ** p_buf,
if (bytes) if (bytes)
*bytes = *bytes =
GST_BUFFER_DATA (ebml->cached_buffer) + ebml->offset - cache_offset; 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); gst_buffer_unref (ebml->cached_buffer);
ebml->cached_buffer = NULL; ebml->cached_buffer = NULL;
} }
if (gst_pad_pull_range (ebml->sinkpad, ebml->offset, MAX (size, 64 * 1024), /* refill the cache */
&ebml->cached_buffer) == GST_FLOW_OK && ret = gst_pad_pull_range (ebml->sinkpad, ebml->offset, MAX (size, 64 * 1024),
GST_BUFFER_SIZE (ebml->cached_buffer) >= size) { &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) if (p_buf)
*p_buf = gst_buffer_create_sub (ebml->cached_buffer, 0, size); *p_buf = gst_buffer_create_sub (ebml->cached_buffer, 0, size);
if (bytes) if (bytes)
*bytes = GST_BUFFER_DATA (ebml->cached_buffer); *bytes = GST_BUFFER_DATA (ebml->cached_buffer);
return TRUE; return GST_FLOW_OK;
} }
/* FIXME, seems silly to require this */
if (!p_buf) if (!p_buf)
return FALSE; return GST_FLOW_ERROR;
ret = gst_pad_pull_range (ebml->sinkpad, ebml->offset, size, p_buf); ret = gst_pad_pull_range (ebml->sinkpad, ebml->offset, size, p_buf);
if (ret != GST_FLOW_OK) { if (ret != GST_FLOW_OK) {
GST_DEBUG ("pull_range returned %d", ret); GST_DEBUG ("pull_range returned %d", ret);
return FALSE; return ret;
} }
if (GST_BUFFER_SIZE (*p_buf) < size) { 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; *p_buf = NULL;
if (bytes) if (bytes)
*bytes = NULL; *bytes = NULL;
return FALSE; return GST_FLOW_ERROR;
} }
if (bytes) if (bytes)
*bytes = GST_BUFFER_DATA (*p_buf); *bytes = GST_BUFFER_DATA (*p_buf);
return TRUE; return GST_FLOW_OK;
} }
/* /*
* Calls pull_range for (offset,size) and advances our offset by size * 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, gst_ebml_read_pull_bytes (GstEbmlRead * ebml, guint size, GstBuffer ** p_buf,
guint8 ** bytes) guint8 ** bytes)
{ {
if (!gst_ebml_read_peek_bytes (ebml, size, p_buf, bytes)) GstFlowReturn ret;
return FALSE;
ret = gst_ebml_read_peek_bytes (ebml, size, p_buf, bytes);
if (ret != GST_FLOW_OK)
return ret;
ebml->offset += size; 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. * Return: FALSE on error.
*/ */
static gboolean static GstFlowReturn
gst_ebml_read_element_id (GstEbmlRead * ebml, guint32 * id, guint * level_up) gst_ebml_read_element_id (GstEbmlRead * ebml, guint32 * id, guint * level_up)
{ {
guint8 *buf; guint8 *buf;
gint len_mask = 0x80, read = 1, n = 1; gint len_mask = 0x80, read = 1, n = 1;
guint32 total; guint32 total;
guint8 b; guint8 b;
GstFlowReturn ret;
if (!gst_ebml_read_peek_bytes (ebml, 1, NULL, &buf)) ret = gst_ebml_read_peek_bytes (ebml, 1, NULL, &buf);
return FALSE; if (ret != GST_FLOW_OK)
return ret;
b = GST_READ_UINT8 (buf); 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), GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
("Invalid EBML ID size tag (0x%x) at position %" G_GUINT64_FORMAT ("Invalid EBML ID size tag (0x%x) at position %" G_GUINT64_FORMAT
" (0x%" G_GINT64_MODIFIER "x)", (guint) b, pos, pos)); " (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)) ret = gst_ebml_read_peek_bytes (ebml, read, NULL, &buf);
return FALSE; if (ret != GST_FLOW_OK)
return ret;
while (n < read) { while (n < read) {
b = GST_READ_UINT8 (buf + n); 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); *level_up = gst_ebml_read_element_level_up (ebml);
ebml->offset += read; 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. * Return: the number of bytes read or -1 on error.
*/ */
static gint static GstFlowReturn
gst_ebml_read_element_length (GstEbmlRead * ebml, guint64 * length) gst_ebml_read_element_length (GstEbmlRead * ebml, guint64 * length,
gint * rread)
{ {
GstFlowReturn ret;
guint8 *buf; guint8 *buf;
gint len_mask = 0x80, read = 1, n = 1, num_ffs = 0; gint len_mask = 0x80, read = 1, n = 1, num_ffs = 0;
guint64 total; guint64 total;
guint8 b; guint8 b;
if (!gst_ebml_read_peek_bytes (ebml, 1, NULL, &buf)) ret = gst_ebml_read_peek_bytes (ebml, 1, NULL, &buf);
return -1; if (ret != GST_FLOW_OK)
return ret;
b = GST_READ_UINT8 (buf); 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), GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
("Invalid EBML length size tag (0x%x) at position %" G_GUINT64_FORMAT ("Invalid EBML length size tag (0x%x) at position %" G_GUINT64_FORMAT
" (0x%" G_GINT64_MODIFIER "x)", (guint) b, pos, pos)); " (0x%" G_GINT64_MODIFIER "x)", (guint) b, pos, pos));
return -1; return GST_FLOW_ERROR;
} }
if ((total &= (len_mask - 1)) == len_mask - 1) if ((total &= (len_mask - 1)) == len_mask - 1)
num_ffs++; num_ffs++;
if (!gst_ebml_read_peek_bytes (ebml, read, NULL, &buf)) ret = gst_ebml_read_peek_bytes (ebml, read, NULL, &buf);
return -1; if (ret != GST_FLOW_OK)
return ret;
while (n < read) { while (n < read) {
guint8 b = GST_READ_UINT8 (buf + n); guint8 b = GST_READ_UINT8 (buf + n);
@ -343,9 +361,12 @@ gst_ebml_read_element_length (GstEbmlRead * ebml, guint64 * length)
else else
*length = total; *length = total;
if (rread)
*rread = read;
ebml->offset += 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. * next element lies higher than the previous one.
*/ */
gboolean GstFlowReturn
gst_ebml_peek_id (GstEbmlRead * ebml, guint * level_up, guint32 * id) gst_ebml_peek_id (GstEbmlRead * ebml, guint * level_up, guint32 * id)
{ {
guint64 off; guint64 off;
GstFlowReturn ret;
g_assert (level_up); g_assert (level_up);
off = ebml->offset; /* save offset */ off = ebml->offset; /* save offset */
if (!gst_ebml_read_element_id (ebml, id, level_up)) if ((ret = gst_ebml_read_element_id (ebml, id, level_up)) != GST_FLOW_OK)
return FALSE; return ret;
ebml->offset = off; /* restore offset */ 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. * Skip the next element.
*/ */
gboolean GstFlowReturn
gst_ebml_read_skip (GstEbmlRead * ebml) gst_ebml_read_skip (GstEbmlRead * ebml)
{ {
guint64 length; guint64 length;
guint32 id; guint32 id;
GstFlowReturn ret;
if (!gst_ebml_read_element_id (ebml, &id, NULL)) ret = gst_ebml_read_element_id (ebml, &id, NULL);
return FALSE; if (ret != GST_FLOW_OK)
return ret;
if (gst_ebml_read_element_length (ebml, &length) < 0) ret = gst_ebml_read_element_length (ebml, &length, NULL);
return FALSE; if (ret != GST_FLOW_OK)
return ret;
ebml->offset += length; ebml->offset += length;
return TRUE; return ret;
} }
/* /*
* Read the next element as a GstBuffer (binary). * Read the next element as a GstBuffer (binary).
*/ */
gboolean GstFlowReturn
gst_ebml_read_buffer (GstEbmlRead * ebml, guint32 * id, GstBuffer ** buf) gst_ebml_read_buffer (GstEbmlRead * ebml, guint32 * id, GstBuffer ** buf)
{ {
guint64 length; guint64 length;
GstFlowReturn ret;
if (!gst_ebml_read_element_id (ebml, id, NULL)) ret = gst_ebml_read_element_id (ebml, id, NULL);
return FALSE; if (ret != GST_FLOW_OK)
return ret;
if (gst_ebml_read_element_length (ebml, &length) < 0) ret = gst_ebml_read_element_length (ebml, &length, NULL);
return FALSE; if (ret != GST_FLOW_OK)
return ret;
if (length == 0) { if (length == 0) {
*buf = gst_buffer_new (); *buf = gst_buffer_new ();
return TRUE; return GST_FLOW_OK;
} }
*buf = NULL; *buf = NULL;
if (!gst_ebml_read_pull_bytes (ebml, (guint) length, buf, NULL)) ret = gst_ebml_read_pull_bytes (ebml, (guint) length, buf, NULL);
return FALSE;
return TRUE; return ret;
} }
/* /*
* Read the next element, return a pointer to it and its size. * 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, gst_ebml_read_bytes (GstEbmlRead * ebml, guint32 * id, guint8 ** data,
guint * size) guint * size)
{ {
guint64 length; guint64 length;
GstFlowReturn ret;
*size = 0; *size = 0;
if (!gst_ebml_read_element_id (ebml, id, NULL)) ret = gst_ebml_read_element_id (ebml, id, NULL);
return FALSE; if (ret != GST_FLOW_OK)
return ret;
if (gst_ebml_read_element_length (ebml, &length) < 0) ret = gst_ebml_read_element_length (ebml, &length, NULL);
return FALSE; if (ret != GST_FLOW_OK)
return ret;
if (length == 0) { if (length == 0) {
*data = NULL; *data = NULL;
return TRUE; return ret;
} }
*data = NULL; *data = NULL;
if (!gst_ebml_read_pull_bytes (ebml, (guint) length, NULL, data)) ret = gst_ebml_read_pull_bytes (ebml, (guint) length, NULL, data);
return FALSE; if (ret != GST_FLOW_OK)
return ret;
*size = (guint) length; *size = (guint) length;
return TRUE; return ret;
} }
/* /*
* Read the next element as an unsigned int. * Read the next element as an unsigned int.
*/ */
gboolean GstFlowReturn
gst_ebml_read_uint (GstEbmlRead * ebml, guint32 * id, guint64 * num) gst_ebml_read_uint (GstEbmlRead * ebml, guint32 * id, guint64 * num)
{ {
guint8 *data; guint8 *data;
guint size; guint size;
GstFlowReturn ret;
if (!gst_ebml_read_bytes (ebml, id, &data, &size)) ret = gst_ebml_read_bytes (ebml, id, &data, &size);
return FALSE; if (ret != GST_FLOW_OK)
return ret;
if (size < 1 || size > 8) { if (size < 1 || size > 8) {
GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL), GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
("Invalid integer element size %d at position %" G_GUINT64_FORMAT ("Invalid integer element size %d at position %" G_GUINT64_FORMAT
" (0x%" G_GINT64_MODIFIER "x)", " (0x%" G_GINT64_MODIFIER "x)",
size, ebml->offset - size, ebml->offset - size)); size, ebml->offset - size, ebml->offset - size));
return FALSE; return GST_FLOW_ERROR;
} }
*num = 0; *num = 0;
while (size > 0) { while (size > 0) {
@ -510,29 +543,31 @@ gst_ebml_read_uint (GstEbmlRead * ebml, guint32 * id, guint64 * num)
data++; data++;
} }
return TRUE; return ret;
} }
/* /*
* Read the next element as a signed int. * Read the next element as a signed int.
*/ */
gboolean GstFlowReturn
gst_ebml_read_sint (GstEbmlRead * ebml, guint32 * id, gint64 * num) gst_ebml_read_sint (GstEbmlRead * ebml, guint32 * id, gint64 * num)
{ {
guint8 *data; guint8 *data;
guint size; guint size;
gboolean negative = 0; gboolean negative = 0;
GstFlowReturn ret;
if (!gst_ebml_read_bytes (ebml, id, &data, &size)) ret = gst_ebml_read_bytes (ebml, id, &data, &size);
return FALSE; if (ret != GST_FLOW_OK)
return ret;
if (size < 1 || size > 8) { if (size < 1 || size > 8) {
GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL), GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
("Invalid integer element size %d at position %" G_GUINT64_FORMAT ("Invalid integer element size %d at position %" G_GUINT64_FORMAT
" (0x%" G_GINT64_MODIFIER "x)", size, ebml->offset - size, " (0x%" G_GINT64_MODIFIER "x)", size, ebml->offset - size,
ebml->offset - size)); ebml->offset - size));
return FALSE; return GST_FLOW_ERROR;
} }
*num = 0; *num = 0;
@ -554,34 +589,36 @@ gst_ebml_read_sint (GstEbmlRead * ebml, guint32 * id, gint64 * num)
*num = 0 - *num; *num = 0 - *num;
} }
return TRUE; return ret;
} }
/* /*
* Read the next element as a float. * Read the next element as a float.
*/ */
gboolean GstFlowReturn
gst_ebml_read_float (GstEbmlRead * ebml, guint32 * id, gdouble * num) gst_ebml_read_float (GstEbmlRead * ebml, guint32 * id, gdouble * num)
{ {
guint8 *data; guint8 *data;
guint size; guint size;
GstFlowReturn ret;
if (!gst_ebml_read_bytes (ebml, id, &data, &size)) ret = gst_ebml_read_bytes (ebml, id, &data, &size);
return FALSE; if (ret != GST_FLOW_OK)
return ret;
if (size != 4 && size != 8 && size != 10) { if (size != 4 && size != 8 && size != 10) {
GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL), GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
("Invalid float element size %d at position %" G_GUINT64_FORMAT ("Invalid float element size %d at position %" G_GUINT64_FORMAT
" (0x%" G_GINT64_MODIFIER "x)", size, ebml->offset - size, " (0x%" G_GINT64_MODIFIER "x)", size, ebml->offset - size,
ebml->offset - size)); ebml->offset - size));
return FALSE; return GST_FLOW_ERROR;
} }
if (size == 10) { if (size == 10) {
GST_ELEMENT_ERROR (ebml, CORE, NOT_IMPLEMENTED, (NULL), GST_ELEMENT_ERROR (ebml, CORE, NOT_IMPLEMENTED, (NULL),
("FIXME! 10-byte floats unimplemented")); ("FIXME! 10-byte floats unimplemented"));
return FALSE; return GST_FLOW_NOT_SUPPORTED;
} }
if (size == 4) { if (size == 4) {
@ -612,43 +649,47 @@ gst_ebml_read_float (GstEbmlRead * ebml, guint32 * id, gdouble * num)
*num = d; *num = d;
} }
return TRUE; return ret;
} }
/* /*
* Read the next element as an ASCII string. * Read the next element as an ASCII string.
*/ */
gboolean GstFlowReturn
gst_ebml_read_ascii (GstEbmlRead * ebml, guint32 * id, gchar ** str) gst_ebml_read_ascii (GstEbmlRead * ebml, guint32 * id, gchar ** str)
{ {
guint8 *data; guint8 *data;
guint size; guint size;
GstFlowReturn ret;
if (!gst_ebml_read_bytes (ebml, id, &data, &size)) ret = gst_ebml_read_bytes (ebml, id, &data, &size);
return FALSE; if (ret != GST_FLOW_OK)
return ret;
*str = g_malloc (size + 1); *str = g_malloc (size + 1);
memcpy (*str, data, size); memcpy (*str, data, size);
(*str)[size] = '\0'; (*str)[size] = '\0';
return TRUE; return ret;
} }
/* /*
* Read the next element as a UTF-8 string. * Read the next element as a UTF-8 string.
*/ */
gboolean GstFlowReturn
gst_ebml_read_utf8 (GstEbmlRead * ebml, guint32 * id, gchar ** str) gst_ebml_read_utf8 (GstEbmlRead * ebml, guint32 * id, gchar ** str)
{ {
gboolean ret; GstFlowReturn ret;
#ifndef GST_DISABLE_GST_DEBUG #ifndef GST_DISABLE_GST_DEBUG
guint64 oldoff = ebml->offset; guint64 oldoff = ebml->offset;
#endif #endif
ret = gst_ebml_read_ascii (ebml, id, str); ret = gst_ebml_read_ascii (ebml, id, str);
if (ret != GST_FLOW_OK)
return ret;
if (str != NULL && *str != NULL && **str != '\0' && if (str != NULL && *str != NULL && **str != '\0' &&
!g_utf8_validate (*str, -1, NULL)) { !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. * Returns the seconds since the unix epoch.
*/ */
gboolean GstFlowReturn
gst_ebml_read_date (GstEbmlRead * ebml, guint32 * id, gint64 * date) gst_ebml_read_date (GstEbmlRead * ebml, guint32 * id, gint64 * date)
{ {
gint64 ebml_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; *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. * are supposed to be sub-elements which can be read separately.
*/ */
gboolean GstFlowReturn
gst_ebml_read_master (GstEbmlRead * ebml, guint32 * id) gst_ebml_read_master (GstEbmlRead * ebml, guint32 * id)
{ {
GstEbmlLevel *level; GstEbmlLevel *level;
guint64 length; guint64 length;
GstFlowReturn ret;
if (!gst_ebml_read_element_id (ebml, id, NULL)) ret = gst_ebml_read_element_id (ebml, id, NULL);
return FALSE; if (ret != GST_FLOW_OK)
return ret;
if (gst_ebml_read_element_length (ebml, &length) < 0) ret = gst_ebml_read_element_length (ebml, &length, NULL);
return FALSE; if (ret != GST_FLOW_OK)
return ret;
/* remember level */ /* remember level */
level = g_new (GstEbmlLevel, 1); level = g_new (GstEbmlLevel, 1);
@ -696,39 +745,42 @@ gst_ebml_read_master (GstEbmlRead * ebml, guint32 * id)
level->length = length; level->length = length;
ebml->level = g_list_append (ebml->level, level); ebml->level = g_list_append (ebml->level, level);
return TRUE; return GST_FLOW_OK;
} }
/* /*
* Read the next element as binary data. * Read the next element as binary data.
*/ */
gboolean GstFlowReturn
gst_ebml_read_binary (GstEbmlRead * ebml, gst_ebml_read_binary (GstEbmlRead * ebml,
guint32 * id, guint8 ** binary, guint64 * length) guint32 * id, guint8 ** binary, guint64 * length)
{ {
guint8 *data; guint8 *data;
guint size; guint size;
GstFlowReturn ret;
if (!gst_ebml_read_bytes (ebml, id, &data, &size)) ret = gst_ebml_read_bytes (ebml, id, &data, &size);
return FALSE; if (ret != GST_FLOW_OK)
return ret;
*length = size; *length = size;
*binary = g_memdup (data, size); *binary = g_memdup (data, size);
return TRUE; return GST_FLOW_OK;
} }
/* /*
* Read an EBML header. * Read an EBML header.
*/ */
gboolean GstFlowReturn
gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version) gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version)
{ {
/* this function is the first to be called */ /* this function is the first to be called */
guint32 id; guint32 id;
guint level_up; guint level_up;
GstFlowReturn ret;
/* default init */ /* default init */
if (doctype) if (doctype)
@ -736,21 +788,24 @@ gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version)
if (version) if (version)
*version = 1; *version = 1;
if (!gst_ebml_peek_id (ebml, &level_up, &id)) ret = gst_ebml_peek_id (ebml, &level_up, &id);
return FALSE; if (ret != GST_FLOW_OK)
return ret;
GST_DEBUG_OBJECT (ebml, "id: %08x", GST_READ_UINT32_BE (&id)); GST_DEBUG_OBJECT (ebml, "id: %08x", GST_READ_UINT32_BE (&id));
if (level_up != 0 || id != GST_EBML_ID_HEADER) { if (level_up != 0 || id != GST_EBML_ID_HEADER) {
GST_ELEMENT_ERROR (ebml, STREAM, WRONG_TYPE, (NULL), (NULL)); GST_ELEMENT_ERROR (ebml, STREAM, WRONG_TYPE, (NULL), (NULL));
return FALSE; return GST_FLOW_ERROR;
} }
if (!gst_ebml_read_master (ebml, &id)) ret = gst_ebml_read_master (ebml, &id);
return FALSE; if (ret != GST_FLOW_OK)
return ret;
while (TRUE) { while (TRUE) {
if (!gst_ebml_peek_id (ebml, &level_up, &id)) ret = gst_ebml_peek_id (ebml, &level_up, &id);
return FALSE; if (ret != GST_FLOW_OK)
return ret;
/* end-of-header */ /* end-of-header */
if (level_up) if (level_up)
@ -761,11 +816,14 @@ gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version)
case GST_EBML_ID_EBMLREADVERSION:{ case GST_EBML_ID_EBMLREADVERSION:{
guint64 num; guint64 num;
if (!gst_ebml_read_uint (ebml, &id, &num)) ret = gst_ebml_read_uint (ebml, &id, &num);
return FALSE; if (ret != GST_FLOW_OK)
return ret;
g_assert (id == GST_EBML_ID_EBMLREADVERSION); g_assert (id == GST_EBML_ID_EBMLREADVERSION);
if (num != GST_EBML_VERSION) if (num != GST_EBML_VERSION) {
return FALSE; GST_ELEMENT_ERROR (ebml, STREAM, WRONG_TYPE, (NULL), (NULL));
return GST_FLOW_ERROR;
}
break; break;
} }
@ -773,11 +831,14 @@ gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version)
case GST_EBML_ID_EBMLMAXSIZELENGTH:{ case GST_EBML_ID_EBMLMAXSIZELENGTH:{
guint64 num; guint64 num;
if (!gst_ebml_read_uint (ebml, &id, &num)) ret = gst_ebml_read_uint (ebml, &id, &num);
return FALSE; if (ret != GST_FLOW_OK)
return ret;
g_assert (id == GST_EBML_ID_EBMLMAXSIZELENGTH); g_assert (id == GST_EBML_ID_EBMLMAXSIZELENGTH);
if (num != sizeof (guint64)) if (num != sizeof (guint64)) {
return FALSE; GST_ELEMENT_ERROR (ebml, STREAM, WRONG_TYPE, (NULL), (NULL));
return GST_FLOW_ERROR;
}
break; break;
} }
@ -785,19 +846,23 @@ gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version)
case GST_EBML_ID_EBMLMAXIDLENGTH:{ case GST_EBML_ID_EBMLMAXIDLENGTH:{
guint64 num; guint64 num;
if (!gst_ebml_read_uint (ebml, &id, &num)) ret = gst_ebml_read_uint (ebml, &id, &num);
return FALSE; if (ret != GST_FLOW_OK)
return ret;
g_assert (id == GST_EBML_ID_EBMLMAXIDLENGTH); g_assert (id == GST_EBML_ID_EBMLMAXIDLENGTH);
if (num != sizeof (guint32)) if (num != sizeof (guint32)) {
return FALSE; GST_ELEMENT_ERROR (ebml, STREAM, WRONG_TYPE, (NULL), (NULL));
return GST_FLOW_ERROR;
}
break; break;
} }
case GST_EBML_ID_DOCTYPE:{ case GST_EBML_ID_DOCTYPE:{
gchar *text; gchar *text;
if (!gst_ebml_read_ascii (ebml, &id, &text)) ret = gst_ebml_read_ascii (ebml, &id, &text);
return FALSE; if (ret != GST_FLOW_OK)
return ret;
g_assert (id == GST_EBML_ID_DOCTYPE); g_assert (id == GST_EBML_ID_DOCTYPE);
if (doctype) { if (doctype) {
if (doctype) if (doctype)
@ -811,8 +876,9 @@ gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version)
case GST_EBML_ID_DOCTYPEREADVERSION:{ case GST_EBML_ID_DOCTYPEREADVERSION:{
guint64 num; guint64 num;
if (!gst_ebml_read_uint (ebml, &id, &num)) ret = gst_ebml_read_uint (ebml, &id, &num);
return FALSE; if (ret != GST_FLOW_OK)
return ret;
g_assert (id == GST_EBML_ID_DOCTYPEREADVERSION); g_assert (id == GST_EBML_ID_DOCTYPEREADVERSION);
if (version) if (version)
*version = num; *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_VOID:
case GST_EBML_ID_EBMLVERSION: case GST_EBML_ID_EBMLVERSION:
case GST_EBML_ID_DOCTYPEVERSION: case GST_EBML_ID_DOCTYPEVERSION:
if (!gst_ebml_read_skip (ebml)) ret = gst_ebml_read_skip (ebml);
return FALSE; if (ret != GST_FLOW_OK)
return ret;
break; break;
} }
} }
return TRUE; return GST_FLOW_OK;
} }

View file

@ -59,58 +59,58 @@ typedef struct _GstEbmlReadClass {
GstElementClass parent; GstElementClass parent;
} GstEbmlReadClass; } GstEbmlReadClass;
GType gst_ebml_read_get_type (void); GType gst_ebml_read_get_type (void);
gboolean gst_ebml_peek_id (GstEbmlRead *ebml, GstFlowReturn gst_ebml_peek_id (GstEbmlRead *ebml,
guint *level_up, guint *level_up,
guint32 *id); guint32 *id);
gboolean gst_ebml_read_seek (GstEbmlRead *ebml, GstFlowReturn gst_ebml_read_seek (GstEbmlRead *ebml,
guint64 offset); guint64 offset);
gint64 gst_ebml_read_get_length (GstEbmlRead *ebml); gint64 gst_ebml_read_get_length (GstEbmlRead *ebml);
gboolean gst_ebml_read_skip (GstEbmlRead *ebml); GstFlowReturn gst_ebml_read_skip (GstEbmlRead *ebml);
gboolean gst_ebml_read_buffer (GstEbmlRead *ebml, GstFlowReturn gst_ebml_read_buffer (GstEbmlRead *ebml,
guint32 *id, guint32 *id,
GstBuffer **buf); GstBuffer **buf);
gboolean gst_ebml_read_uint (GstEbmlRead *ebml, GstFlowReturn gst_ebml_read_uint (GstEbmlRead *ebml,
guint32 *id, guint32 *id,
guint64 *num); guint64 *num);
gboolean gst_ebml_read_sint (GstEbmlRead *ebml, GstFlowReturn gst_ebml_read_sint (GstEbmlRead *ebml,
guint32 *id, guint32 *id,
gint64 *num); gint64 *num);
gboolean gst_ebml_read_float (GstEbmlRead *ebml, GstFlowReturn gst_ebml_read_float (GstEbmlRead *ebml,
guint32 *id, guint32 *id,
gdouble *num); gdouble *num);
gboolean gst_ebml_read_ascii (GstEbmlRead *ebml, GstFlowReturn gst_ebml_read_ascii (GstEbmlRead *ebml,
guint32 *id, guint32 *id,
gchar **str); gchar **str);
gboolean gst_ebml_read_utf8 (GstEbmlRead *ebml, GstFlowReturn gst_ebml_read_utf8 (GstEbmlRead *ebml,
guint32 *id, guint32 *id,
gchar **str); gchar **str);
gboolean gst_ebml_read_date (GstEbmlRead *ebml, GstFlowReturn gst_ebml_read_date (GstEbmlRead *ebml,
guint32 *id, guint32 *id,
gint64 *date); gint64 *date);
gboolean gst_ebml_read_master (GstEbmlRead *ebml, GstFlowReturn gst_ebml_read_master (GstEbmlRead *ebml,
guint32 *id); guint32 *id);
gboolean gst_ebml_read_binary (GstEbmlRead *ebml, GstFlowReturn gst_ebml_read_binary (GstEbmlRead *ebml,
guint32 *id, guint32 *id,
guint8 **binary, guint8 **binary,
guint64 *length); guint64 *length);
gboolean gst_ebml_read_header (GstEbmlRead *read, GstFlowReturn gst_ebml_read_header (GstEbmlRead *read,
gchar **doctype, gchar **doctype,
guint *version); guint *version);
G_END_DECLS G_END_DECLS

File diff suppressed because it is too large Load diff

View file

@ -89,17 +89,9 @@ typedef struct _GstMatroskaDemux {
/* timescale in the file */ /* timescale in the file */
guint64 time_scale; guint64 time_scale;
/* length, position (time, ns) */ /* keeping track of playback position */
guint64 pos; GstSegment segment;
guint64 duration; gboolean segment_running;
/* a possible pending seek */
gboolean seek_pending;
gdouble segment_rate;
gint64 segment_start;
gint64 segment_stop;
gboolean segment_play;
} GstMatroskaDemux; } GstMatroskaDemux;
typedef struct _GstMatroskaDemuxClass { typedef struct _GstMatroskaDemuxClass {

View file

@ -255,6 +255,7 @@ typedef struct _GstMatroskaTrackContext {
GstPad *pad; GstPad *pad;
GstCaps *caps; GstCaps *caps;
guint index; guint index;
GstFlowReturn last_flow;
/* some often-used info */ /* some often-used info */
gchar *codec_id, *codec_name, *name, *language; gchar *codec_id, *codec_name, *name, *language;