/*
* 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)
{
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) {
*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;
}
/*
* 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);
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);
*level_up = gst_ebml_read_element_level_up (ebml);
ebml->offset += read;
- return TRUE;
+ return GST_FLOW_OK;
}
/*
* 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);
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);
else
*length = total;
+ if (rread)
+ *rread = read;
+
ebml->offset += read;
- return read;
+ return GST_FLOW_OK;
}
/*
* 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;
}
/*
* 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) {
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;
*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) {
*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)) {
* 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;
}
/*
* 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);
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)
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)
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;
}
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;
}
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)
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;
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;
}
g_free (track);
}
+/*
+ * Returns the aggregated GstFlowReturn.
+ */
+static GstFlowReturn
+gst_matroska_demux_combine_flows (GstMatroskaDemux * demux,
+ GstMatroskaTrackContext * track, GstFlowReturn ret)
+{
+ guint i;
+
+ /* store the value */
+ track->last_flow = ret;
+
+ /* any other error that is not-linked can be returned right away */
+ if (ret != GST_FLOW_NOT_LINKED)
+ goto done;
+
+ /* only return NOT_LINKED if all other pads returned NOT_LINKED */
+ for (i = 0; i < GST_MATROSKA_DEMUX_MAX_STREAMS; i++) {
+ GstMatroskaTrackContext *ostream = demux->src[i];
+
+ if (ostream == NULL)
+ continue;
+
+ ret = ostream->last_flow;
+ /* some other return value (must be SUCCESS but we can return
+ * other values as well) */
+ if (ret != GST_FLOW_NOT_LINKED)
+ goto done;
+ }
+ /* if we get here, all other pads were unlinked and we return
+ * NOT_LINKED then */
+done:
+ GST_LOG_OBJECT (demux, "combined return %s", gst_flow_get_name (ret));
+ return ret;
+}
+
static void
gst_matroska_demux_reset (GstElement * element)
{
/* reset timers */
demux->clock = NULL;
demux->time_scale = 1000000;
- demux->duration = 0;
- demux->pos = 0;
demux->created = G_MININT64;
demux->metadata_parsed = FALSE;
demux->index_parsed = FALSE;
- demux->segment_rate = 1.0;
- demux->segment_start = GST_CLOCK_TIME_NONE;
- demux->segment_stop = GST_CLOCK_TIME_NONE;
- demux->segment_play = FALSE;
- demux->seek_pending = FALSE;
+ gst_segment_init (&demux->segment, GST_FORMAT_TIME);
}
static gint
return (gint) enc_b->order - (gint) enc_a->order;
}
-static gboolean
+static GstFlowReturn
gst_matroska_demux_read_track_encodings (GstEbmlRead * ebml,
GstMatroskaDemux * demux, GstMatroskaTrackContext * context)
{
- gboolean res = TRUE;
+ GstFlowReturn ret;
guint32 id;
- if (!gst_ebml_read_master (ebml, &id))
- return FALSE;
+ if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+ return ret;
context->encodings =
g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaTrackEncoding), 1);
- while (res) {
- if (!gst_ebml_peek_id (ebml, &demux->level_up, &id)) {
- res = FALSE;
+ while (ret == GST_FLOW_OK) {
+ if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) {
break;
} else if (demux->level_up > 0) {
demux->level_up--;
case GST_MATROSKA_ID_CONTENTENCODING:{
GstMatroskaTrackEncoding enc = { 0, };
- if (!gst_ebml_read_master (ebml, &id)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
break;
}
- while (res) {
- if (!gst_ebml_peek_id (ebml, &demux->level_up, &id)) {
- res = FALSE;
+ while (ret == GST_FLOW_OK) {
+ if ((ret =
+ gst_ebml_peek_id (ebml, &demux->level_up,
+ &id)) != GST_FLOW_OK) {
break;
} else if (demux->level_up > 0) {
demux->level_up--;
case GST_MATROSKA_ID_CONTENTENCODINGORDER:{
guint64 num;
- if (!gst_ebml_read_uint (ebml, &id, &num)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
break;
}
enc.order = num;
case GST_MATROSKA_ID_CONTENTENCODINGSCOPE:{
guint64 num;
- if (!gst_ebml_read_uint (ebml, &id, &num)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
break;
}
if (num > 7)
case GST_MATROSKA_ID_CONTENTENCODINGTYPE:{
guint64 num;
- if (!gst_ebml_read_uint (ebml, &id, &num)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
break;
}
if (num > 1)
}
case GST_MATROSKA_ID_CONTENTCOMPRESSION:{
- if (!gst_ebml_read_master (ebml, &id)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
break;
}
- while (res) {
+ while (ret == GST_FLOW_OK) {
- if (!gst_ebml_peek_id (ebml, &demux->level_up, &id)) {
- res = FALSE;
+ if ((ret =
+ gst_ebml_peek_id (ebml, &demux->level_up,
+ &id)) != GST_FLOW_OK) {
break;
} else if (demux->level_up > 0) {
demux->level_up--;
case GST_MATROSKA_ID_CONTENTCOMPALGO:{
guint64 num;
- if (!gst_ebml_read_uint (ebml, &id, &num)) {
- res = FALSE;
+ if ((ret =
+ gst_ebml_read_uint (ebml, &id,
+ &num)) != GST_FLOW_OK) {
break;
}
if (num > 3)
guint64 size;
- if (!gst_ebml_read_binary (ebml, &id, &data, &size)) {
- res = FALSE;
+ if ((ret =
+ gst_ebml_read_binary (ebml, &id, &data,
+ &size)) != GST_FLOW_OK) {
break;
}
enc.comp_settings = data;
default:
GST_WARNING ("Unknown track compression header entry 0x%x"
" - ignoring", id);
- if (!gst_ebml_read_skip (ebml))
- res = FALSE;
+ ret = gst_ebml_read_skip (ebml);
break;
}
default:
GST_WARNING
("Unknown track encoding header entry 0x%x - ignoring", id);
- if (!gst_ebml_read_skip (ebml))
- res = FALSE;
+ ret = gst_ebml_read_skip (ebml);
break;
}
default:
GST_WARNING ("Unknown track encodings header entry 0x%x - ignoring",
id);
- if (!gst_ebml_read_skip (ebml))
- res = FALSE;
+ ret = gst_ebml_read_skip (ebml);
break;
}
/* Sort encodings according to their order */
g_array_sort (context->encodings, gst_matroska_demux_encoding_cmp);
- return res;
+ return ret;
}
-static gboolean
+static GstFlowReturn
gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
{
GstElementClass *klass = GST_ELEMENT_GET_CLASS (demux);
GstPadTemplate *templ = NULL;
GstCaps *caps = NULL;
gchar *padname = NULL;
- gboolean res = TRUE;
+ GstFlowReturn ret;
guint32 id;
GstTagList *list = NULL;
gchar *codec = NULL;
context->default_duration = 0;
context->pos = 0;
context->set_discont = TRUE;
+ context->last_flow = GST_FLOW_OK;
demux->num_streams++;
/* start with the master */
- if (!gst_ebml_read_master (ebml, &id))
- return FALSE;
+ if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+ return ret;
/* try reading the trackentry headers */
- while (res) {
- if (!gst_ebml_peek_id (ebml, &demux->level_up, &id)) {
- res = FALSE;
+ while (ret == GST_FLOW_OK) {
+ if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) {
break;
} else if (demux->level_up > 0) {
demux->level_up--;
case GST_MATROSKA_ID_TRACKNUMBER:{
guint64 num;
- if (!gst_ebml_read_uint (ebml, &id, &num)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
break;
}
context->num = num;
break;
}
-
/* track UID (unique identifier) */
case GST_MATROSKA_ID_TRACKUID:{
guint64 num;
- if (!gst_ebml_read_uint (ebml, &id, &num)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
break;
}
context->uid = num;
case GST_MATROSKA_ID_TRACKTYPE:{
guint64 track_type;
- if (!gst_ebml_read_uint (ebml, &id, &track_type)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_uint (ebml, &id, &track_type)) != GST_FLOW_OK) {
break;
}
if (!gst_matroska_track_init_video_context (&context)) {
GST_WARNING
("trackvideo EBML entry in non-video track - ignoring track");
- res = FALSE;
+ ret = GST_FLOW_ERROR;
break;
- } else if (!gst_ebml_read_master (ebml, &id)) {
- res = FALSE;
+ } else if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
break;
}
videocontext = (GstMatroskaTrackVideoContext *) context;
demux->src[demux->num_streams - 1] = context;
- while (res) {
- if (!gst_ebml_peek_id (ebml, &demux->level_up, &id)) {
- res = FALSE;
+ while (ret == GST_FLOW_OK) {
+ if ((ret =
+ gst_ebml_peek_id (ebml, &demux->level_up,
+ &id)) != GST_FLOW_OK) {
break;
} else if (demux->level_up > 0) {
demux->level_up--;
case GST_MATROSKA_ID_TRACKDEFAULTDURATION:{
guint64 num;
- if (!gst_ebml_read_uint (ebml, &id, &num)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
break;
}
context->default_duration = num;
case GST_MATROSKA_ID_VIDEOFRAMERATE:{
gdouble num;
- if (!gst_ebml_read_float (ebml, &id, &num)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK) {
break;
}
if (num != 0.0) {
case GST_MATROSKA_ID_VIDEODISPLAYWIDTH:{
guint64 num;
- if (!gst_ebml_read_uint (ebml, &id, &num)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
break;
}
videocontext->display_width = num;
case GST_MATROSKA_ID_VIDEODISPLAYHEIGHT:{
guint64 num;
- if (!gst_ebml_read_uint (ebml, &id, &num)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
break;
}
videocontext->display_height = num;
case GST_MATROSKA_ID_VIDEOPIXELWIDTH:{
guint64 num;
- if (!gst_ebml_read_uint (ebml, &id, &num)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
break;
}
videocontext->pixel_width = num;
case GST_MATROSKA_ID_VIDEOPIXELHEIGHT:{
guint64 num;
- if (!gst_ebml_read_uint (ebml, &id, &num)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
break;
}
videocontext->pixel_height = num;
case GST_MATROSKA_ID_VIDEOFLAGINTERLACED:{
guint64 num;
- if (!gst_ebml_read_uint (ebml, &id, &num)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
break;
}
if (num)
case GST_MATROSKA_ID_VIDEOSTEREOMODE:{
guint64 num;
- if (!gst_ebml_read_uint (ebml, &id, &num)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
break;
}
if (num != GST_MATROSKA_EYE_MODE_MONO &&
case GST_MATROSKA_ID_VIDEOASPECTRATIO:{
guint64 num;
- if (!gst_ebml_read_uint (ebml, &id, &num)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
break;
}
if (num != GST_MATROSKA_ASPECT_RATIO_MODE_FREE &&
case GST_MATROSKA_ID_VIDEOCOLOURSPACE:{
guint64 num;
- if (!gst_ebml_read_uint (ebml, &id, &num)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
break;
}
videocontext->fourcc = num;
/* pass-through */
case GST_EBML_ID_VOID:
- if (!gst_ebml_read_skip (ebml))
- res = FALSE;
+ ret = gst_ebml_read_skip (ebml);
break;
}
if (!gst_matroska_track_init_audio_context (&context)) {
GST_WARNING
("trackaudio EBML entry in non-audio track - ignoring track");
- res = FALSE;
+ ret = GST_FLOW_ERROR;
break;
- } else if (!gst_ebml_read_master (ebml, &id)) {
- res = FALSE;
+ } else if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
break;
}
audiocontext = (GstMatroskaTrackAudioContext *) context;
demux->src[demux->num_streams - 1] = context;
- while (res) {
- if (!gst_ebml_peek_id (ebml, &demux->level_up, &id)) {
- res = FALSE;
+ while (ret == GST_FLOW_OK) {
+ if ((ret =
+ gst_ebml_peek_id (ebml, &demux->level_up,
+ &id)) != GST_FLOW_OK) {
break;
} else if (demux->level_up > 0) {
demux->level_up--;
case GST_MATROSKA_ID_AUDIOSAMPLINGFREQ:{
gdouble num;
- if (!gst_ebml_read_float (ebml, &id, &num)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK) {
break;
}
audiocontext->samplerate = num;
case GST_MATROSKA_ID_AUDIOBITDEPTH:{
guint64 num;
- if (!gst_ebml_read_uint (ebml, &id, &num)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
break;
}
audiocontext->bitdepth = num;
case GST_MATROSKA_ID_AUDIOCHANNELS:{
guint64 num;
- if (!gst_ebml_read_uint (ebml, &id, &num)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
break;
}
audiocontext->channels = num;
/* pass-through */
case GST_EBML_ID_VOID:
- if (!gst_ebml_read_skip (ebml))
- res = FALSE;
+ ret = gst_ebml_read_skip (ebml);
break;
}
case GST_MATROSKA_ID_CODECID:{
gchar *text;
- if (!gst_ebml_read_ascii (ebml, &id, &text)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_ascii (ebml, &id, &text)) != GST_FLOW_OK) {
break;
}
context->codec_id = text;
guint8 *data;
guint64 size;
- if (!gst_ebml_read_binary (ebml, &id, &data, &size)) {
- res = FALSE;
+ if ((ret =
+ gst_ebml_read_binary (ebml, &id, &data,
+ &size)) != GST_FLOW_OK) {
break;
}
context->codec_priv = data;
case GST_MATROSKA_ID_CODECNAME:{
gchar *text;
- if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK) {
break;
}
context->codec_name = text;
case GST_MATROSKA_ID_TRACKNAME:{
gchar *text;
- if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK) {
break;
}
context->name = text;
case GST_MATROSKA_ID_TRACKLANGUAGE:{
gchar *text;
- if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK) {
break;
}
case GST_MATROSKA_ID_TRACKFLAGENABLED:{
guint64 num;
- if (!gst_ebml_read_uint (ebml, &id, &num)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
break;
}
if (num)
case GST_MATROSKA_ID_TRACKFLAGDEFAULT:{
guint64 num;
- if (!gst_ebml_read_uint (ebml, &id, &num)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
break;
}
if (num)
case GST_MATROSKA_ID_TRACKFLAGLACING:{
guint64 num;
- if (!gst_ebml_read_uint (ebml, &id, &num)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
break;
}
if (num)
case GST_MATROSKA_ID_TRACKDEFAULTDURATION:{
guint64 num;
- if (!gst_ebml_read_uint (ebml, &id, &num)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
break;
}
context->default_duration = num;
}
case GST_MATROSKA_ID_CONTENTENCODINGS:{
- if (!gst_matroska_demux_read_track_encodings (ebml, demux, context)) {
- res = FALSE;
- }
+ ret = gst_matroska_demux_read_track_encodings (ebml, demux, context);
break;
}
case GST_MATROSKA_ID_TRACKMINCACHE:
case GST_MATROSKA_ID_TRACKMAXCACHE:
case GST_EBML_ID_VOID:
- if (!gst_ebml_read_skip (ebml))
- res = FALSE;
+ ret = gst_ebml_read_skip (ebml);
break;
}
}
}
- if (context->type == 0 || context->codec_id == NULL || !res) {
- if (res)
+ if (context->type == 0 || context->codec_id == NULL || ret != GST_FLOW_OK) {
+ if (ret == GST_FLOW_OK)
GST_WARNING ("Unknown stream/codec in track entry header");
demux->num_streams--;
gst_matroska_track_free (context);
}
- return res;
+ return ret;
}
/* now create the GStreamer connectivity */
g_free (padname);
/* tadaah! */
- return TRUE;
+ return ret;
}
static const GstQueryType *
}
GST_OBJECT_LOCK (demux);
- gst_query_set_position (query, GST_FORMAT_TIME, demux->pos);
+ gst_query_set_position (query, GST_FORMAT_TIME, demux->segment.last_stop);
GST_OBJECT_UNLOCK (demux);
res = TRUE;
}
GST_OBJECT_LOCK (demux);
- gst_query_set_duration (query, GST_FORMAT_TIME, demux->duration);
+ gst_query_set_duration (query, GST_FORMAT_TIME, demux->segment.duration);
GST_OBJECT_UNLOCK (demux);
res = TRUE;
if (cur == GST_CLOCK_TIME_NONE)
cur = 0;
if (stop == GST_CLOCK_TIME_NONE)
- stop = demux->duration;
+ stop = demux->segment.duration;
if (cur_type == GST_SEEK_TYPE_SET)
segment_start = cur;
else if (cur_type == GST_SEEK_TYPE_CUR)
- segment_start = demux->segment_start + cur;
+ segment_start = demux->segment.start + cur;
else
- segment_start = demux->segment_start;
+ segment_start = demux->segment.start;
if (stop_type == GST_SEEK_TYPE_SET)
segment_stop = stop;
else if (stop_type == GST_SEEK_TYPE_CUR)
- segment_stop = demux->segment_stop + stop;
+ segment_stop = demux->segment.stop + stop;
else
- segment_stop = demux->segment_stop;
+ segment_stop = demux->segment.stop;
- segment_start = CLAMP (segment_start, 0, demux->duration);
- segment_stop = CLAMP (segment_stop, 0, demux->duration);
+ segment_start = CLAMP (segment_start, 0, demux->segment.duration);
+ segment_stop = CLAMP (segment_stop, 0, demux->segment.duration);
GST_DEBUG ("New segment positions: %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
GST_TIME_ARGS (segment_start), GST_TIME_ARGS (segment_stop));
GST_DEBUG ("Committing new seek segment");
- demux->segment_rate = rate;
- demux->segment_play = !!(flags & GST_SEEK_FLAG_SEGMENT);
+ demux->segment.rate = rate;
+ demux->segment.flags = flags;
- demux->segment_start = segment_start;
- demux->segment_stop = segment_stop;
+ demux->segment.start = segment_start;
+ demux->segment.stop = segment_stop;
GST_OBJECT_UNLOCK (demux);
/* notify start of new segment */
- if (demux->segment_play) {
+ if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
GstMessage *msg;
msg = gst_message_new_segment_start (GST_OBJECT (demux),
- GST_FORMAT_TIME, demux->segment_start);
+ GST_FORMAT_TIME, demux->segment.start);
gst_element_post_message (GST_ELEMENT (demux), msg);
}
newsegment_event = gst_event_new_new_segment (FALSE, rate,
GST_FORMAT_TIME, segment_start, segment_stop, segment_start);
- GST_DEBUG ("Stopping flush");
if (flush) {
+ GST_DEBUG ("Stopping flush");
+ gst_pad_push_event (demux->sinkpad, gst_event_new_flush_stop ());
gst_matroska_demux_send_event (demux, gst_event_new_flush_stop ());
+ } else if (demux->segment_running) {
+ /* FIXME, the current segment was still running when we performed the
+ * seek, we need to close the current segment */
+ GST_DEBUG ("Closing currently running segment");
}
- gst_pad_push_event (demux->sinkpad, gst_event_new_flush_stop ());
/* send newsegment event to all source pads and update the time */
gst_matroska_demux_send_event (demux, newsegment_event);
for (i = 0; i < demux->num_streams; i++) {
demux->src[i]->pos = entry->time;
demux->src[i]->set_discont = TRUE;
+ demux->src[i]->last_flow = GST_FLOW_OK;
}
- demux->pos = entry->time;
+ demux->segment.last_stop = entry->time;
/* restart our task since it might have been stopped when we did the
* flush. */
+ demux->segment_running = TRUE;
gst_pad_start_task (demux->sinkpad, (GstTaskFunction) gst_matroska_demux_loop,
demux->sinkpad);
return TRUE;
seek_error:
-
- /* FIXME: shouldn't we either make it a real error or start the task
- * function again so that things can continue from where they left off? */
- GST_DEBUG ("Got a seek error");
- GST_OBJECT_UNLOCK (demux);
- GST_PAD_STREAM_UNLOCK (demux->sinkpad);
-
- return FALSE;
+ {
+ /* FIXME: shouldn't we either make it a real error or start the task
+ * function again so that things can continue from where they left off? */
+ GST_DEBUG ("Got a seek error");
+ GST_OBJECT_UNLOCK (demux);
+ GST_PAD_STREAM_UNLOCK (demux->sinkpad);
+ return FALSE;
+ }
}
static gboolean
return res;
}
-static gboolean
+static GstFlowReturn
gst_matroska_demux_init_stream (GstMatroskaDemux * demux)
{
GstEbmlRead *ebml = GST_EBML_READ (demux);
guint32 id;
gchar *doctype;
guint version;
+ GstFlowReturn ret;
- if (!gst_ebml_read_header (ebml, &doctype, &version))
- return FALSE;
+ if ((ret = gst_ebml_read_header (ebml, &doctype, &version)) != GST_FLOW_OK)
+ return ret;
if (!doctype || strcmp (doctype, "matroska") != 0) {
GST_ELEMENT_ERROR (demux, STREAM, WRONG_TYPE, (NULL),
("Input is not a matroska stream (doctype=%s)",
doctype ? doctype : "none"));
g_free (doctype);
- return FALSE;
+ return GST_FLOW_ERROR;
}
g_free (doctype);
if (version > 2) {
GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
("Demuxer version (2) is too old to read stream version %d", version));
- return FALSE;
+ return GST_FLOW_ERROR;
}
/* find segment, must be the next element */
while (1) {
guint last_level;
- if (!gst_ebml_peek_id (ebml, &last_level, &id)) {
+ if ((ret = gst_ebml_peek_id (ebml, &last_level, &id)) != GST_FLOW_OK) {
GST_DEBUG_OBJECT (demux, "gst_ebml_peek_id() failed!");
- return FALSE;
+ return ret;
}
if (id == GST_MATROSKA_ID_SEGMENT)
GST_WARNING ("Expected a Segment ID (0x%x), but received 0x%x!",
GST_MATROSKA_ID_SEGMENT, id);
- if (!gst_ebml_read_skip (ebml))
- return FALSE;
+ if ((ret = gst_ebml_read_skip (ebml)) != GST_FLOW_OK)
+ return ret;
}
/* we now have a EBML segment */
- if (!gst_ebml_read_master (ebml, &id)) {
+ if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
GST_DEBUG_OBJECT (demux, "gst_ebml_read_master() failed!");
- return FALSE;
+ return ret;
}
/* seeks are from the beginning of the segment,
* after the segment ID/length */
demux->ebml_segment_start = ebml->offset;
- return TRUE;
+ return ret;
}
-static gboolean
+static GstFlowReturn
gst_matroska_demux_parse_tracks (GstMatroskaDemux * demux)
{
GstEbmlRead *ebml = GST_EBML_READ (demux);
- gboolean res = TRUE;
+ GstFlowReturn ret = GST_FLOW_OK;
guint32 id;
- while (res) {
- if (!gst_ebml_peek_id (ebml, &demux->level_up, &id)) {
- res = FALSE;
+ while (ret == GST_FLOW_OK) {
+ if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) {
break;
} else if (demux->level_up) {
demux->level_up--;
switch (id) {
/* one track within the "all-tracks" header */
case GST_MATROSKA_ID_TRACKENTRY:
- if (!gst_matroska_demux_add_stream (demux))
- res = FALSE;
+ ret = gst_matroska_demux_add_stream (demux);
break;
default:
/* fall-through */
case GST_EBML_ID_VOID:
- if (!gst_ebml_read_skip (ebml))
- res = FALSE;
+ ret = gst_ebml_read_skip (ebml);
break;
}
}
}
- return res;
+ return ret;
}
-static gboolean
+static GstFlowReturn
gst_matroska_demux_parse_index_cuetrack (GstMatroskaDemux * demux,
gboolean prevent_eos, GstMatroskaIndex * idx, guint64 length)
{
GstEbmlRead *ebml = GST_EBML_READ (demux);
- gboolean got_error = FALSE;
guint32 id;
+ GstFlowReturn ret;
- if (!gst_ebml_read_master (ebml, &id))
- return FALSE;
+ if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+ return ret;
- while (!got_error) {
+ while (TRUE) {
if (prevent_eos && length == ebml->offset)
break;
- if (!gst_ebml_peek_id (ebml, &demux->level_up, &id))
- return FALSE;
+ if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK)
+ return ret;
if (demux->level_up) {
demux->level_up--;
{
guint64 num;
- if (!gst_ebml_read_uint (ebml, &id, &num))
+ if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
goto error;
idx->track = num;
{
guint64 num;
- if (!gst_ebml_read_uint (ebml, &id, &num))
+ if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
goto error;
idx->pos = num;
/* fall-through */
case GST_EBML_ID_VOID:
- if (!gst_ebml_read_skip (ebml))
+ if ((ret = gst_ebml_read_skip (ebml)) != GST_FLOW_OK)
goto error;
break;
}
}
}
- return TRUE;
+ return ret;
error:
if (demux->level_up)
demux->level_up--;
- return FALSE;
+ return ret;
}
-static gboolean
+static GstFlowReturn
gst_matroska_demux_parse_index_pointentry (GstMatroskaDemux * demux,
gboolean prevent_eos, guint64 length)
{
GstEbmlRead *ebml = GST_EBML_READ (demux);
GstMatroskaIndex idx;
- gboolean got_error = FALSE;
guint32 id;
+ GstFlowReturn ret;
- if (!gst_ebml_read_master (ebml, &id))
- return FALSE;
+ if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+ return ret;
/* in the end, we hope to fill one entry with a
* timestamp, a file position and a tracknum */
idx.time = (guint64) - 1;
idx.track = (guint16) - 1;
- while (!got_error) {
+ while (ret == GST_FLOW_OK) {
if (prevent_eos && length == ebml->offset)
break;
- if (!gst_ebml_peek_id (ebml, &demux->level_up, &id))
- return FALSE;
+ if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK)
+ return ret;
if (demux->level_up) {
demux->level_up--;
{
guint64 time;
- if (!gst_ebml_read_uint (ebml, &id, &time)) {
- got_error = TRUE;
- } else {
+ if ((ret = gst_ebml_read_uint (ebml, &id, &time)) == GST_FLOW_OK) {
idx.time = time * demux->time_scale;
}
break;
/* position in the file + track to which it belongs */
case GST_MATROSKA_ID_CUETRACKPOSITION:
{
- if (!gst_matroska_demux_parse_index_cuetrack (demux, prevent_eos, &idx,
- length)) {
- got_error = TRUE;
- }
+ ret = gst_matroska_demux_parse_index_cuetrack (demux, prevent_eos, &idx,
+ length);
break;
}
/* fall-through */
case GST_EBML_ID_VOID:
- if (!gst_ebml_read_skip (ebml))
- got_error = TRUE;
+ ret = gst_ebml_read_skip (ebml);
break;
}
demux->num_indexes++;
}
- return (!got_error);
+ return ret;
}
-static gboolean
+static GstFlowReturn
gst_matroska_demux_parse_index (GstMatroskaDemux * demux, gboolean prevent_eos)
{
GstEbmlRead *ebml = GST_EBML_READ (demux);
- gboolean got_error = FALSE;
guint32 id;
guint64 length = 0;
+ GstFlowReturn ret = GST_FLOW_OK;
if (prevent_eos) {
length = gst_ebml_read_get_length (ebml);
}
- while (!got_error) {
+ while (ret == GST_FLOW_OK) {
/* We're an element that can be seeked to. If we are, then
* we want to prevent EOS, since that'll kill us. So we cache
* file size and seek until there, and don't call EOS upon os. */
if (prevent_eos && length == ebml->offset)
break;
- if (!gst_ebml_peek_id (ebml, &demux->level_up, &id))
- return FALSE;
+ if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK)
+ return ret;
if (demux->level_up) {
demux->level_up--;
switch (id) {
/* one single index entry ('point') */
case GST_MATROSKA_ID_POINTENTRY:
- if (!gst_matroska_demux_parse_index_pointentry (demux, prevent_eos,
- length))
- got_error = TRUE;
+ ret = gst_matroska_demux_parse_index_pointentry (demux, prevent_eos,
+ length);
break;
default:
/* fall-through */
case GST_EBML_ID_VOID:
- if (!gst_ebml_read_skip (ebml))
- got_error = TRUE;
+ ret = gst_ebml_read_skip (ebml);
break;
}
}
}
- return (!got_error);
+ return ret;
}
-static gboolean
+static GstFlowReturn
gst_matroska_demux_parse_info (GstMatroskaDemux * demux)
{
GstEbmlRead *ebml = GST_EBML_READ (demux);
- gboolean res = TRUE;
+ GstFlowReturn ret = GST_FLOW_OK;
guint32 id;
- while (res) {
- if (!gst_ebml_peek_id (ebml, &demux->level_up, &id)) {
- res = FALSE;
+ while (ret == GST_FLOW_OK) {
+ if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) {
break;
} else if (demux->level_up) {
demux->level_up--;
case GST_MATROSKA_ID_TIMECODESCALE:{
guint64 num;
- if (!gst_ebml_read_uint (ebml, &id, &num)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
break;
}
demux->time_scale = num;
gdouble num;
GstClockTime dur;
- if (!gst_ebml_read_float (ebml, &id, &num)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK) {
break;
}
-
dur = gst_gdouble_to_guint64 (num *
gst_guint64_to_gdouble (demux->time_scale));
if (GST_CLOCK_TIME_IS_VALID (dur) && dur <= G_MAXINT64)
- demux->duration = dur;
+ demux->segment.duration = dur;
break;
}
case GST_MATROSKA_ID_WRITINGAPP:{
gchar *text;
- if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK) {
break;
}
demux->writing_app = text;
case GST_MATROSKA_ID_MUXINGAPP:{
gchar *text;
- if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK) {
break;
}
demux->muxing_app = text;
case GST_MATROSKA_ID_DATEUTC:{
gint64 time;
- if (!gst_ebml_read_date (ebml, &id, &time)) {
- res = FALSE;
+ if ((ret = gst_ebml_read_date (ebml, &id, &time)) != GST_FLOW_OK) {
break;
}
demux->created = time;
case GST_MATROSKA_ID_SEGMENTUID:{
/* TODO not yet implemented. */
- if (!gst_ebml_read_skip (ebml))
- res = FALSE;
+ ret = gst_ebml_read_skip (ebml);
break;
}
/* fall-through */
case GST_EBML_ID_VOID:
- if (!gst_ebml_read_skip (ebml))
- res = FALSE;
+ ret = gst_ebml_read_skip (ebml);
break;
}
}
}
- return res;
+ return ret;
}
-static gboolean
+static GstFlowReturn
gst_matroska_demux_parse_metadata_id_simple_tag (GstMatroskaDemux * demux,
gboolean prevent_eos, guint64 length, GstTagList ** p_taglist)
{
GST_MATROSKA_TAG_ID_COPYRIGHT, GST_TAG_COPYRIGHT}
};
GstEbmlRead *ebml = GST_EBML_READ (demux);
- gboolean got_error = FALSE;
+ GstFlowReturn ret;
guint32 id;
gchar *value = NULL;
gchar *tag = NULL;
- if (!gst_ebml_read_master (ebml, &id))
- return FALSE;
+ if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+ return ret;
- while (!got_error) {
+ while (ret == GST_FLOW_OK) {
/* read all sub-entries */
if (prevent_eos && length == ebml->offset)
break;
- if (!gst_ebml_peek_id (ebml, &demux->level_up, &id))
- return FALSE;
+ if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK)
+ return ret;
if (demux->level_up) {
demux->level_up--;
switch (id) {
case GST_MATROSKA_ID_TAGNAME:
g_free (tag);
- if (!gst_ebml_read_ascii (ebml, &id, &tag))
- got_error = TRUE;
+ tag = NULL;
+ ret = gst_ebml_read_ascii (ebml, &id, &tag);
break;
case GST_MATROSKA_ID_TAGSTRING:
g_free (value);
- if (!gst_ebml_read_utf8 (ebml, &id, &value))
- got_error = TRUE;
+ value = NULL;
+ ret = gst_ebml_read_utf8 (ebml, &id, &value);
break;
default:
/* fall-through */
case GST_EBML_ID_VOID:
- if (!gst_ebml_read_skip (ebml))
- got_error = TRUE;
+ ret = gst_ebml_read_skip (ebml);
break;
}
g_free (tag);
g_free (value);
- return (!got_error);
+ return ret;
}
-static gboolean
+static GstFlowReturn
gst_matroska_demux_parse_metadata_id_tag (GstMatroskaDemux * demux,
gboolean prevent_eos, guint64 length, GstTagList ** p_taglist)
{
GstEbmlRead *ebml = GST_EBML_READ (demux);
- gboolean got_error = FALSE;
guint32 id;
+ GstFlowReturn ret;
- if (!gst_ebml_read_master (ebml, &id))
- return FALSE;
+ if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+ return ret;
- while (!got_error) {
+ while (ret == GST_FLOW_OK) {
/* read all sub-entries */
if (prevent_eos && length == ebml->offset)
break;
- if (!gst_ebml_peek_id (ebml, &demux->level_up, &id))
- return FALSE;
+ if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK)
+ return ret;
if (demux->level_up) {
demux->level_up--;
switch (id) {
case GST_MATROSKA_ID_SIMPLETAG:
- if (!gst_matroska_demux_parse_metadata_id_simple_tag (demux,
- prevent_eos, length, p_taglist)) {
- got_error = TRUE;
- }
+ ret = gst_matroska_demux_parse_metadata_id_simple_tag (demux,
+ prevent_eos, length, p_taglist);
break;
default:
/* fall-through */
case GST_EBML_ID_VOID:
- if (!gst_ebml_read_skip (ebml))
- got_error = TRUE;
+ ret = gst_ebml_read_skip (ebml);
break;
}
}
}
- return (!got_error);
+ return ret;
}
-static gboolean
+static GstFlowReturn
gst_matroska_demux_parse_metadata (GstMatroskaDemux * demux,
gboolean prevent_eos)
{
GstEbmlRead *ebml = GST_EBML_READ (demux);
GstTagList *taglist = gst_tag_list_new ();
- gboolean got_error = FALSE;
+ GstFlowReturn ret = GST_FLOW_OK;
guint64 length = 0;
guint32 id;
length = gst_ebml_read_get_length (ebml);
}
- while (!got_error) {
+ while (ret == GST_FLOW_OK) {
/* We're an element that can be seeked to. If we are, then
* we want to prevent EOS, since that'll kill us. So we cache
* file size and seek until there, and don't call EOS upon os. */
if (prevent_eos && length == ebml->offset)
break;
- if (!gst_ebml_peek_id (ebml, &demux->level_up, &id))
- return FALSE;
+ if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK)
+ return ret;
if (demux->level_up) {
demux->level_up--;
switch (id) {
case GST_MATROSKA_ID_TAG:
- if (!gst_matroska_demux_parse_metadata_id_tag (demux, prevent_eos,
- length, &taglist)) {
- got_error = TRUE;
- }
+ ret = gst_matroska_demux_parse_metadata_id_tag (demux, prevent_eos,
+ length, &taglist);
break;
default:
/* fall-through */
case GST_EBML_ID_VOID:
- if (!gst_ebml_read_skip (ebml))
- got_error = TRUE;
+ ret = gst_ebml_read_skip (ebml);
break;
}
gst_tag_list_free (taglist);
}
- return (!got_error);
+ return ret;
}
/*
{
gint stream_nr;
- GST_LOG ("Sync to %" GST_TIME_FORMAT, GST_TIME_ARGS (demux->pos));
+ GST_LOG ("Sync to %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (demux->segment.last_stop));
for (stream_nr = 0; stream_nr < demux->num_streams; stream_nr++) {
GstMatroskaTrackContext *context;
stream_nr, GST_TIME_ARGS (context->pos));
/* does it lag? 0.5 seconds is a random treshold... */
- if (context->pos + (GST_SECOND / 2) < demux->pos) {
+ if (context->pos + (GST_SECOND / 2) < demux->segment.last_stop) {
GST_DEBUG ("Synchronizing stream %d with others by advancing time "
"from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT, stream_nr,
- GST_TIME_ARGS (context->pos), GST_TIME_ARGS (demux->pos));
+ GST_TIME_ARGS (context->pos),
+ GST_TIME_ARGS (demux->segment.last_stop));
- context->pos = demux->pos;
+ context->pos = demux->segment.last_stop;
/* advance stream time */
gst_pad_push_event (context->pad,
- gst_event_new_new_segment (TRUE, demux->segment_rate,
- GST_FORMAT_TIME, demux->pos, -1, demux->pos));
+ gst_event_new_new_segment (TRUE, demux->segment.rate,
+ GST_FORMAT_TIME, demux->segment.last_stop, -1,
+ demux->segment.last_stop));
}
}
}
-static gboolean
+static GstFlowReturn
gst_matroska_demux_push_hdr_buf (GstMatroskaDemux * demux,
GstMatroskaTrackContext * stream, guint8 * data, guint len)
{
- GstFlowReturn flow;
+ GstFlowReturn ret, cret;
GstBuffer *header_buf = NULL;
- flow = gst_pad_alloc_buffer_and_set_caps (stream->pad,
+ ret = gst_pad_alloc_buffer_and_set_caps (stream->pad,
GST_BUFFER_OFFSET_NONE, len, stream->caps, &header_buf);
- if (flow == GST_FLOW_OK) {
- memcpy (GST_BUFFER_DATA (header_buf), data, len);
+ /* we combine but don't use the combined value to check if we have a buffer
+ * or not. The combined value is what we return. */
+ cret = gst_matroska_demux_combine_flows (demux, stream, ret);
+ if (ret != GST_FLOW_OK)
+ goto no_buffer;
- if (stream->set_discont) {
- GST_BUFFER_FLAG_SET (header_buf, GST_BUFFER_FLAG_DISCONT);
- stream->set_discont = FALSE;
- }
+ memcpy (GST_BUFFER_DATA (header_buf), data, len);
- flow = gst_pad_push (stream->pad, header_buf);
+ if (stream->set_discont) {
+ GST_BUFFER_FLAG_SET (header_buf, GST_BUFFER_FLAG_DISCONT);
+ stream->set_discont = FALSE;
}
- if (flow != GST_FLOW_OK && flow != GST_FLOW_NOT_LINKED)
- return FALSE;
+ ret = gst_pad_push (stream->pad, header_buf);
- return TRUE;
+ /* combine flows */
+ cret = gst_matroska_demux_combine_flows (demux, stream, ret);
+
+ return cret;
+
+ /* ERRORS */
+no_buffer:
+ {
+ GST_DEBUG_OBJECT (demux, "could not alloc buffer: %s, combined %s",
+ gst_flow_get_name (ret), gst_flow_get_name (cret));
+ return cret;
+ }
}
-static gboolean
+static GstFlowReturn
gst_matroska_demux_push_flac_codec_priv_data (GstMatroskaDemux * demux,
GstMatroskaTrackContext * stream)
{
+ GstFlowReturn ret;
guint8 *pdata;
guint off, len;
/* need at least 'fLaC' marker + STREAMINFO metadata block */
if (stream->codec_priv_size < ((4) + (4 + 34))) {
GST_WARNING_OBJECT (demux, "not enough codec priv data for flac headers");
- return FALSE;
+ return GST_FLOW_ERROR;
}
if (memcmp (pdata, "fLaC", 4) != 0) {
GST_WARNING_OBJECT (demux, "no flac marker at start of stream headers");
- return FALSE;
+ return GST_FLOW_ERROR;
}
- if (!gst_matroska_demux_push_hdr_buf (demux, stream, pdata, 4))
- return FALSE;
+ ret = gst_matroska_demux_push_hdr_buf (demux, stream, pdata, 4);
+ if (ret != GST_FLOW_OK)
+ return ret;
off = 4; /* skip fLaC marker */
while (off < stream->codec_priv_size) {
GST_DEBUG_OBJECT (demux, "header packet: len=%u bytes, flags=0x%02x",
len, (guint) pdata[off]);
- if (!gst_matroska_demux_push_hdr_buf (demux, stream, pdata + off, len))
- return FALSE;
+ ret = gst_matroska_demux_push_hdr_buf (demux, stream, pdata + off, len);
+ if (ret != GST_FLOW_OK)
+ return ret;
off += 4 + len;
}
-
- return TRUE;
+ return GST_FLOW_OK;
}
-static gboolean
+static GstFlowReturn
gst_matroska_demux_push_xiph_codec_priv_data (GstMatroskaDemux * demux,
GstMatroskaTrackContext * stream)
{
+ GstFlowReturn ret;
guint8 *p = (guint8 *) stream->codec_priv;
gint i, offset, length, num_packets;
GST_DEBUG_OBJECT (demux, "buffer %d: length=%u bytes", i, (guint) length);
if (offset + length > stream->codec_priv_size)
- return FALSE;
+ return GST_FLOW_ERROR;
- if (!gst_matroska_demux_push_hdr_buf (demux, stream, p + offset, length))
- return FALSE;
+ ret = gst_matroska_demux_push_hdr_buf (demux, stream, p + offset, length);
+ if (ret != GST_FLOW_OK)
+ return ret;
offset += length;
}
length = stream->codec_priv_size - offset;
GST_DEBUG_OBJECT (demux, "buffer %d: length=%u bytes", i, (guint) length);
- if (!gst_matroska_demux_push_hdr_buf (demux, stream, p + offset, length))
- return FALSE;
+ ret = gst_matroska_demux_push_hdr_buf (demux, stream, p + offset, length);
+ if (ret != GST_FLOW_OK)
+ return ret;
- return TRUE;
+ return GST_FLOW_OK;
}
static void
return FALSE;
}
-static gboolean
-gst_matroska_demux_add_wvpk_header (GstMatroskaTrackContext * stream,
- gint block_length, GstBuffer ** buf)
+static GstFlowReturn
+gst_matroska_demux_add_wvpk_header (GstMatroskaDemux * demux,
+ GstMatroskaTrackContext * stream, gint block_length, GstBuffer ** buf)
{
GstBuffer *newbuf;
guint8 *data;
guint newlen;
+ GstFlowReturn ret, cret;
/* we need to reconstruct the header of the wavpack block */
Wavpack4Header wvh;
/* block_samples, flags and crc are already in the buffer */
newlen = block_length + sizeof (Wavpack4Header) - 12;
- if (gst_pad_alloc_buffer_and_set_caps (stream->pad, GST_BUFFER_OFFSET_NONE,
- newlen, stream->caps, &newbuf) != GST_FLOW_OK) {
- return TRUE; /* not an error, pad might not be linked */
+ ret = gst_pad_alloc_buffer_and_set_caps (stream->pad, GST_BUFFER_OFFSET_NONE,
+ newlen, stream->caps, &newbuf);
+ cret = gst_matroska_demux_combine_flows (demux, stream, ret);
+ if (ret != GST_FLOW_OK) {
+ GST_DEBUG_OBJECT (demux, "pad_alloc failed %s, combined %s",
+ gst_flow_get_name (ret), gst_flow_get_name (cret));
+ return cret;
}
data = GST_BUFFER_DATA (newbuf);
gst_buffer_copy_metadata (newbuf, *buf, GST_BUFFER_COPY_TIMESTAMPS);
gst_buffer_unref (*buf);
*buf = newbuf;
- return TRUE;
+
+ return cret;
}
static GstBuffer *
GST_BUFFER_DATA (newbuf) = (guint8 *) utf8;
GST_BUFFER_SIZE (newbuf) = strlen (utf8);
gst_buffer_copy_metadata (newbuf, buf, GST_BUFFER_COPY_TIMESTAMPS);
-
gst_buffer_unref (buf);
+
return newbuf;
}
return buf;
}
-static gboolean
+static GstFlowReturn
gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
guint64 cluster_time, gboolean is_simpleblock)
{
GstMatroskaTrackContext *stream = NULL;
GstEbmlRead *ebml = GST_EBML_READ (demux);
- gboolean got_error = FALSE;
+ GstFlowReturn ret = GST_FLOW_OK;
gboolean readblock = FALSE;
guint32 id;
guint64 block_duration = 0;
gint flags = 0;
gint64 referenceblock = 0;
- while (!got_error) {
+ while (ret == GST_FLOW_OK) {
if (!is_simpleblock) {
- if (!gst_ebml_peek_id (ebml, &demux->level_up, &id))
- goto error;
+ if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK)
+ goto done;
if (demux->level_up) {
demux->level_up--;
guint64 num;
guint8 *data;
- if (!gst_ebml_read_buffer (ebml, &id, &buf)) {
- got_error = TRUE;
+ if ((ret = gst_ebml_read_buffer (ebml, &id, &buf)) != GST_FLOW_OK)
break;
- }
data = GST_BUFFER_DATA (buf);
size = GST_BUFFER_SIZE (buf);
if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0) {
GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), ("Data error"));
gst_buffer_unref (buf);
- got_error = TRUE;
+ buf = NULL;
+ ret = GST_FLOW_ERROR;
break;
}
data += n;
stream_num = gst_matroska_demux_stream_from_num (demux, num);
if (size <= 3 || stream_num < 0 || stream_num >= demux->num_streams) {
gst_buffer_unref (buf);
+ buf = NULL;
GST_WARNING ("Invalid stream %d or size %u", stream_num, size);
break;
}
case 0x2: /* fixed-size lacing */
case 0x3: /* EBML lacing */
if (size == 0) {
- got_error = TRUE;
+ GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
+ ("Invalid lacing size"));
+ ret = GST_FLOW_ERROR;
break;
}
laces = GST_READ_UINT8 (data) + 1;
case 0x1: /* xiph lacing */ {
guint temp, total = 0;
- for (n = 0; !got_error && n < laces - 1; n++) {
+ for (n = 0; ret == GST_FLOW_OK && n < laces - 1; n++) {
while (1) {
if (size == 0) {
- got_error = TRUE;
+ GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
+ ("Invalid lacing size"));
+ ret = GST_FLOW_ERROR;
break;
}
temp = GST_READ_UINT8 (data);
if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0) {
GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
("Data error"));
- got_error = TRUE;
+ ret = GST_FLOW_ERROR;
break;
}
data += n;
size -= n;
total = lace_size[0] = num;
- for (n = 1; !got_error && n < laces - 1; n++) {
+ for (n = 1; ret == GST_FLOW_OK && n < laces - 1; n++) {
gint64 snum;
gint r;
if ((r = gst_matroska_ebmlnum_sint (data, size, &snum)) < 0) {
GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
("Data error"));
- got_error = TRUE;
+ ret = GST_FLOW_ERROR;
break;
}
data += r;
}
if (stream->send_xiph_headers) {
- if (!gst_matroska_demux_push_xiph_codec_priv_data (demux, stream)) {
- got_error = TRUE;
- }
+ ret = gst_matroska_demux_push_xiph_codec_priv_data (demux, stream);
stream->send_xiph_headers = FALSE;
}
if (stream->send_flac_headers) {
- if (!gst_matroska_demux_push_flac_codec_priv_data (demux, stream)) {
- got_error = TRUE;
- }
+ ret = gst_matroska_demux_push_flac_codec_priv_data (demux, stream);
stream->send_flac_headers = FALSE;
}
stream->send_dvd_event = FALSE;
}
- if (got_error)
+ if (ret != GST_FLOW_OK)
break;
readblock = TRUE;
}
case GST_MATROSKA_ID_BLOCKDURATION:{
- if (!gst_ebml_read_uint (ebml, &id, &block_duration))
- got_error = TRUE;
+ ret = gst_ebml_read_uint (ebml, &id, &block_duration);
break;
}
case GST_MATROSKA_ID_REFERENCEBLOCK:{
- if (!gst_ebml_read_sint (ebml, &id, &referenceblock))
- got_error = TRUE;
+ ret = gst_ebml_read_sint (ebml, &id, &referenceblock);
break;
}
/* fall-through */
case GST_EBML_ID_VOID:
- if (!gst_ebml_read_skip (ebml))
- got_error = TRUE;
+ ret = gst_ebml_read_skip (ebml);
break;
}
lace_time = GST_CLOCK_TIME_NONE;
}
- if (referenceblock && readblock && demux->src[stream_num]->set_discont) {
+ stream = demux->src[stream_num];
+
+ if (referenceblock && readblock && stream->set_discont) {
/* When doing seeks or such, we need to restart on key frames or
decoders might choke. */
readblock = FALSE;
gst_buffer_unref (buf);
+ buf = NULL;
}
- if (!got_error && readblock) {
+ if (ret == GST_FLOW_OK && readblock) {
guint64 duration = 0;
- stream = demux->src[stream_num];
-
if (block_duration) {
duration = block_duration * demux->time_scale;
} else if (stream->default_duration) {
}
for (n = 0; n < laces; n++) {
- GstFlowReturn ret;
GstBuffer *sub;
if (lace_size[n] == 0)
GST_BUFFER_TIMESTAMP (sub) = lace_time;
if (lace_time != GST_CLOCK_TIME_NONE)
- demux->pos = lace_time;
+ demux->segment.last_stop = lace_time;
- stream->pos = demux->pos;
+ stream->pos = demux->segment.last_stop;
gst_matroska_demux_sync_streams (demux);
if (gst_matroska_demux_stream_is_wavpack (stream)) {
- if (!gst_matroska_demux_add_wvpk_header (stream, lace_size[n], &sub)) {
- got_error = TRUE;
- }
+ ret =
+ gst_matroska_demux_add_wvpk_header (demux, stream, lace_size[n],
+ &sub);
}
/* FIXME: do all laces have the same lenght? */
stream->set_discont = FALSE;
}
- GST_DEBUG ("Pushing data of size %d for stream %d, time=%"
- GST_TIME_FORMAT " and duration=%" GST_TIME_FORMAT,
+ GST_DEBUG ("Pushing lace %d, data of size %d for stream %d, time=%"
+ GST_TIME_FORMAT " and duration=%" GST_TIME_FORMAT, n,
GST_BUFFER_SIZE (sub), stream_num,
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (sub)),
GST_TIME_ARGS (GST_BUFFER_DURATION (sub)));
}
ret = gst_pad_push (stream->pad, sub);
- if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
- got_error = TRUE;
+ /* combine flows */
+ ret = gst_matroska_demux_combine_flows (demux, stream, ret);
size -= lace_size[n];
if (lace_time != GST_CLOCK_TIME_NONE)
}
}
- if (0) {
- error:
- got_error = TRUE;
- }
-
+done:
if (readblock)
gst_buffer_unref (buf);
g_free (lace_size);
- return (!got_error);
+ return ret;
}
-static gboolean
+static GstFlowReturn
gst_matroska_demux_parse_cluster (GstMatroskaDemux * demux)
{
GstEbmlRead *ebml = GST_EBML_READ (demux);
- gboolean got_error = FALSE;
+ GstFlowReturn ret = GST_FLOW_OK;
guint64 cluster_time = GST_CLOCK_TIME_NONE;
guint32 id;
- while (!got_error) {
- if (!gst_ebml_peek_id (ebml, &demux->level_up, &id))
- return FALSE;
+ while (ret == GST_FLOW_OK) {
+ if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK)
+ return ret;
if (demux->level_up) {
demux->level_up--;
{
guint64 num;
- if (!gst_ebml_read_uint (ebml, &id, &num)) {
- got_error = TRUE;
- } else {
+ if ((ret = gst_ebml_read_uint (ebml, &id, &num)) == GST_FLOW_OK) {
cluster_time = num * demux->time_scale;
}
break;
/* a group of blocks inside a cluster */
case GST_MATROSKA_ID_BLOCKGROUP:
- if (!gst_ebml_read_master (ebml, &id)) {
- got_error = TRUE;
- } else {
- if (!gst_matroska_demux_parse_blockgroup_or_simpleblock (demux,
- cluster_time, FALSE))
- got_error = TRUE;
+ if ((ret = gst_ebml_read_master (ebml, &id)) == GST_FLOW_OK) {
+ ret = gst_matroska_demux_parse_blockgroup_or_simpleblock (demux,
+ cluster_time, FALSE);
}
break;
case GST_MATROSKA_ID_SIMPLEBLOCK:
{
- if (!gst_matroska_demux_parse_blockgroup_or_simpleblock (demux,
- cluster_time, TRUE))
- got_error = TRUE;
+ ret = gst_matroska_demux_parse_blockgroup_or_simpleblock (demux,
+ cluster_time, TRUE);
break;
}
/* fall-through */
case GST_EBML_ID_VOID:
- if (!gst_ebml_read_skip (ebml))
- got_error = TRUE;
+ ret = gst_ebml_read_skip (ebml);
break;
}
}
}
- return (!got_error);
+ return ret;
}
-static gboolean
+static GstFlowReturn
gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux,
gboolean * p_run_loop)
{
GstEbmlRead *ebml = GST_EBML_READ (demux);
- gboolean got_error = FALSE;
+ GstFlowReturn ret;
guint64 seek_pos = (guint64) - 1;
guint32 seek_id = 0;
guint32 id;
- if (!gst_ebml_read_master (ebml, &id))
- return FALSE;
+ if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+ return ret;
- while (!got_error) {
- if (!gst_ebml_peek_id (ebml, &demux->level_up, &id))
- return FALSE;
+ while (ret == GST_FLOW_OK) {
+ if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK)
+ return ret;
if (demux->level_up) {
demux->level_up--;
{
guint64 t;
- if (!gst_ebml_read_uint (ebml, &id, &t)) {
- got_error = TRUE;
- } else {
+ if ((ret = gst_ebml_read_uint (ebml, &id, &t)) == GST_FLOW_OK) {
seek_id = t;
}
break;
{
guint64 t;
- if (!gst_ebml_read_uint (ebml, &id, &t)) {
- got_error = TRUE;
- } else {
+ if ((ret = gst_ebml_read_uint (ebml, &id, &t)) == GST_FLOW_OK) {
seek_pos = t;
}
break;
/* fall-through */
case GST_EBML_ID_VOID:
- if (!gst_ebml_read_skip (ebml))
- got_error = TRUE;
+ ret = gst_ebml_read_skip (ebml);
break;
}
}
}
- if (got_error)
- return FALSE;
+ if (ret != GST_FLOW_OK)
+ return ret;
if (!seek_id || seek_pos == (guint64) - 1) {
GST_WARNING ("Incomplete seekhead entry (0x%x/%"
G_GUINT64_FORMAT ")", seek_id, seek_pos);
- return TRUE;
+ return GST_FLOW_OK;
}
switch (seek_id) {
/* seek */
if (!gst_ebml_read_seek (ebml, seek_pos + demux->ebml_segment_start))
- return FALSE;
+ return GST_FLOW_ERROR;
/* we don't want to lose our seekhead level, so we add
* a dummy. This is a crude hack. */
ebml->level = g_list_append (ebml->level, level);
/* check ID */
- if (!gst_ebml_peek_id (ebml, &demux->level_up, &id))
- return FALSE;
+ if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK)
+ return ret;
if (id != seek_id) {
g_warning ("We looked for ID=0x%x but got ID=0x%x (pos=%"
/* read master + parse */
switch (id) {
case GST_MATROSKA_ID_CUES:
- if (!gst_ebml_read_master (ebml, &id))
- return FALSE;
- if (!gst_matroska_demux_parse_index (demux, TRUE))
- return FALSE;
+ if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+ return ret;
+ if ((ret =
+ gst_matroska_demux_parse_index (demux, TRUE)) != GST_FLOW_OK)
+ return ret;
if (gst_ebml_read_get_length (ebml) == ebml->offset)
*p_run_loop = FALSE;
else
demux->index_parsed = TRUE;
break;
case GST_MATROSKA_ID_TAGS:
- if (!gst_ebml_read_master (ebml, &id))
- return FALSE;
- if (!gst_matroska_demux_parse_metadata (demux, TRUE))
- return FALSE;
+ if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+ return ret;
+ if ((ret =
+ gst_matroska_demux_parse_metadata (demux,
+ TRUE)) != GST_FLOW_OK)
+ return ret;
if (gst_ebml_read_get_length (ebml) == ebml->offset)
*p_run_loop = FALSE;
else
break;
}
- return (!got_error);
+ return ret;
}
-static gboolean
+static GstFlowReturn
gst_matroska_demux_parse_contents (GstMatroskaDemux * demux,
gboolean * p_run_loop)
{
GstEbmlRead *ebml = GST_EBML_READ (demux);
- gboolean got_error = FALSE;
+ GstFlowReturn ret = GST_FLOW_OK;
guint32 id;
- while (!got_error) {
- if (!gst_ebml_peek_id (ebml, &demux->level_up, &id))
- return FALSE;
+ while (ret == GST_FLOW_OK) {
+ if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK)
+ return ret;
if (demux->level_up) {
demux->level_up--;
switch (id) {
case GST_MATROSKA_ID_SEEKENTRY:
{
- if (!gst_matroska_demux_parse_contents_seekentry (demux, p_run_loop))
- got_error = TRUE;
+ ret = gst_matroska_demux_parse_contents_seekentry (demux, p_run_loop);
break;
}
/* fall-through */
case GST_EBML_ID_VOID:
- if (!gst_ebml_read_skip (ebml))
- got_error = TRUE;
+ ret = gst_ebml_read_skip (ebml);
break;
}
}
}
- return (!got_error);
+ return ret;
}
/* returns FALSE on error, otherwise TRUE */
-static gboolean
+static GstFlowReturn
gst_matroska_demux_loop_stream_parse_id (GstMatroskaDemux * demux,
guint32 id, gboolean * p_run_loop)
{
GstEbmlRead *ebml = GST_EBML_READ (demux);
+ GstFlowReturn ret;
switch (id) {
/* stream info */
case GST_MATROSKA_ID_INFO:
- if (!gst_ebml_read_master (ebml, &id))
- return FALSE;
- if (!gst_matroska_demux_parse_info (demux))
- return FALSE;
+ if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+ return ret;
+ if ((ret = gst_matroska_demux_parse_info (demux)) != GST_FLOW_OK)
+ return ret;
break;
/* track info headers */
case GST_MATROSKA_ID_TRACKS:
{
- if (!gst_ebml_read_master (ebml, &id))
- return FALSE;
- if (!gst_matroska_demux_parse_tracks (demux))
- return FALSE;
+ if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+ return ret;
+ if ((ret = gst_matroska_demux_parse_tracks (demux)) != GST_FLOW_OK)
+ return ret;
break;
}
case GST_MATROSKA_ID_CUES:
{
if (!demux->index_parsed) {
- if (!gst_ebml_read_master (ebml, &id))
- return FALSE;
- if (!gst_matroska_demux_parse_index (demux, FALSE))
- return FALSE;
+ if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+ return ret;
+ if ((ret =
+ gst_matroska_demux_parse_index (demux, FALSE)) != GST_FLOW_OK)
+ return ret;
} else {
- if (!gst_ebml_read_skip (ebml))
- return FALSE;
+ if ((ret = gst_ebml_read_skip (ebml)) != GST_FLOW_OK)
+ return ret;
}
break;
}
case GST_MATROSKA_ID_TAGS:
{
if (!demux->index_parsed) {
- if (!gst_ebml_read_master (ebml, &id))
- return FALSE;
- if (!gst_matroska_demux_parse_metadata (demux, FALSE))
- return FALSE;
+ if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+ return ret;
+ if ((ret =
+ gst_matroska_demux_parse_metadata (demux,
+ FALSE)) != GST_FLOW_OK)
+ return ret;
} else {
- if (!gst_ebml_read_skip (ebml))
- return FALSE;
+ if ((ret = gst_ebml_read_skip (ebml)) != GST_FLOW_OK)
+ return ret;
}
break;
}
/* file index (if seekable, seek to Cues/Tags to parse it) */
case GST_MATROSKA_ID_SEEKHEAD:
{
- if (!gst_ebml_read_master (ebml, &id))
- return FALSE;
- if (!gst_matroska_demux_parse_contents (demux, p_run_loop))
- return FALSE;
+ if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+ return ret;
+ if ((ret =
+ gst_matroska_demux_parse_contents (demux,
+ p_run_loop)) != GST_FLOW_OK)
+ return ret;
break;
}
gst_matroska_demux_send_event (demux,
gst_event_new_new_segment (FALSE, 1.0,
GST_FORMAT_TIME, 0,
- (demux->duration > 0) ? demux->duration : -1, 0));
+ (demux->segment.duration > 0) ? demux->segment.duration : -1,
+ 0));
GST_DEBUG_OBJECT (demux, "signaling no more pads");
gst_element_no_more_pads (GST_ELEMENT (demux));
} else {
- if (!gst_ebml_read_master (ebml, &id))
- return FALSE;
+ if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+ return ret;
/* The idea is that we parse one cluster per loop and
* then break out of the loop here. In the next call
* actually push a buffer, but we still want to break
* out of the loop to handle a possible error. We'll
* get back here if it's recoverable. */
- if (!gst_matroska_demux_parse_cluster (demux))
- return FALSE;
+ if ((ret = gst_matroska_demux_parse_cluster (demux)) != GST_FLOW_OK)
+ return ret;
*p_run_loop = FALSE;
}
break;
case GST_EBML_ID_VOID:
{
- if (!gst_ebml_read_skip (ebml))
- return FALSE;
+ if ((ret = gst_ebml_read_skip (ebml)) != GST_FLOW_OK)
+ return ret;
break;
}
}
-
- return TRUE;
+ return GST_FLOW_OK;
}
-static gboolean
+static GstFlowReturn
gst_matroska_demux_loop_stream (GstMatroskaDemux * demux)
{
GstEbmlRead *ebml = GST_EBML_READ (demux);
- gboolean got_error = FALSE;
+ GstFlowReturn ret = GST_FLOW_OK;
gboolean run_loop = TRUE;
guint32 id;
/* we've found our segment, start reading the different contents in here */
- while (run_loop && !got_error) {
- if (!gst_ebml_peek_id (ebml, &demux->level_up, &id))
- return FALSE;
+ while (run_loop && ret == GST_FLOW_OK) {
+ if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK)
+ return ret;
if (demux->level_up) {
demux->level_up--;
break;
}
- if (!gst_matroska_demux_loop_stream_parse_id (demux, id, &run_loop))
- got_error = TRUE;
+ ret = gst_matroska_demux_loop_stream_parse_id (demux, id, &run_loop);
if (demux->level_up) {
demux->level_up--;
break;
}
}
-
- return (!got_error);
+ return ret;
}
static void
{
GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (gst_pad_get_parent (pad));
GstEbmlRead *ebml = GST_EBML_READ (demux);
- gboolean ret;
+ GstFlowReturn ret;
/* first, if we're to start, let's actually get starting */
if (demux->state == GST_MATROSKA_DEMUX_STATE_START) {
- if (!gst_matroska_demux_init_stream (demux)) {
+ ret = gst_matroska_demux_init_stream (demux);
+ if (ret != GST_FLOW_OK) {
GST_WARNING_OBJECT (demux, "init stream failed!");
- goto eos_and_pause;
+ goto pause;
}
demux->state = GST_MATROSKA_DEMUX_STATE_HEADER;
}
ret = gst_matroska_demux_loop_stream (demux);
+ if (ret != GST_FLOW_OK)
+ goto pause;
/* check if we're at the end of a configured segment */
- if (GST_CLOCK_TIME_IS_VALID (demux->segment_stop)) {
+ if (GST_CLOCK_TIME_IS_VALID (demux->segment.stop)) {
guint i;
for (i = 0; i < demux->num_streams; i++) {
- if (demux->src[i]->pos >= demux->segment_stop) {
+ if (demux->src[i]->pos >= demux->segment.stop) {
GST_INFO_OBJECT (demux, "Reached end of segment (%" G_GUINT64_FORMAT
- "-%" G_GUINT64_FORMAT ") on pad %s:%s", demux->segment_start,
- demux->segment_stop, GST_DEBUG_PAD_NAME (demux->src[i]->pad));
-
- if (!demux->segment_play)
- goto eos_and_pause;
-
- gst_element_post_message (GST_ELEMENT (demux),
- gst_message_new_segment_done (GST_OBJECT (demux), GST_FORMAT_TIME,
- demux->segment_stop));
+ "-%" G_GUINT64_FORMAT ") on pad %s:%s", demux->segment.start,
+ demux->segment.stop, GST_DEBUG_PAD_NAME (demux->src[i]->pad));
+ ret = GST_FLOW_UNEXPECTED;
goto pause;
}
}
}
if (ebml->offset == gst_ebml_read_get_length (ebml)) {
- if (demux->segment_play) {
- GST_LOG ("Reached end of stream and segment, posting message");
- gst_element_post_message (GST_ELEMENT (demux),
- gst_message_new_segment_done (GST_OBJECT (demux), GST_FORMAT_TIME,
- demux->duration));
- goto pause;
- }
-
GST_LOG ("Reached end of stream, sending EOS");
- goto eos_and_pause;
- }
-
- if (ret == FALSE) {
- GST_LOG ("Error processing stream, sending EOS");
- goto eos_and_pause;
+ ret = GST_FLOW_UNEXPECTED;
+ goto pause;
}
/* all is fine */
gst_object_unref (demux);
return;
-eos_and_pause:
- gst_matroska_demux_send_event (demux, gst_event_new_eos ());
- /* fallthrough */
+ /* ERRORS */
pause:
- GST_LOG_OBJECT (demux, "pausing task");
- gst_pad_pause_task (demux->sinkpad);
- gst_object_unref (demux);
+ {
+ const gchar *reason = gst_flow_get_name (ret);
+
+ GST_LOG_OBJECT (demux, "pausing task, reason %s", reason);
+ demux->segment_running = FALSE;
+ gst_pad_pause_task (demux->sinkpad);
+
+ if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) {
+ if (ret == GST_FLOW_UNEXPECTED) {
+ /* perform EOS logic */
+ if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
+ gint64 stop;
+
+ /* for segment playback we need to post when (in stream time)
+ * we stopped, this is either stop (when set) or the duration. */
+ if ((stop = demux->segment.stop) == -1)
+ stop = demux->segment.duration;
+
+ GST_LOG_OBJECT (demux, "Sending segment done, at end of segment");
+ gst_element_post_message (GST_ELEMENT (demux),
+ gst_message_new_segment_done (GST_OBJECT (demux), GST_FORMAT_TIME,
+ stop));
+ } else {
+ /* normal playback, send EOS to all linked pads */
+ GST_LOG_OBJECT (demux, "Sending EOS, at end of stream");
+ gst_matroska_demux_send_event (demux, gst_event_new_eos ());
+ }
+ } else {
+ GST_ELEMENT_ERROR (demux, STREAM, FAILED, NULL,
+ ("stream stopped, reason %s", reason));
+ gst_matroska_demux_send_event (demux, gst_event_new_eos ());
+ }
+ }
+ gst_object_unref (demux);
+ return;
+ }
}
static gboolean
static gboolean
gst_matroska_demux_sink_activate_pull (GstPad * sinkpad, gboolean active)
{
+ GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (GST_PAD_PARENT (sinkpad));
+
if (active) {
/* if we have a scheduler we can start the task */
+ demux->segment_running = TRUE;
gst_pad_start_task (sinkpad, (GstTaskFunction) gst_matroska_demux_loop,
sinkpad);
} else {
+ demux->segment_running = FALSE;
gst_pad_stop_task (sinkpad);
}