mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-03 16:09:39 +00:00
matroska: refactor code common to matroskademux and matroskaparse
Move the following function to matroska-read-common.[ch] from matroska-demux.c and matroska-parse.c: - gst_matroska_{demux,parse}_peek_bytes https://bugzilla.gnome.org/show_bug.cgi?id=650877
This commit is contained in:
parent
f885e2721a
commit
72d969b360
6 changed files with 201 additions and 282 deletions
|
@ -242,16 +242,17 @@ static void
|
||||||
gst_matroska_demux_init (GstMatroskaDemux * demux,
|
gst_matroska_demux_init (GstMatroskaDemux * demux,
|
||||||
GstMatroskaDemuxClass * klass)
|
GstMatroskaDemuxClass * klass)
|
||||||
{
|
{
|
||||||
demux->sinkpad = gst_pad_new_from_static_template (&sink_templ, "sink");
|
demux->common.sinkpad = gst_pad_new_from_static_template (&sink_templ,
|
||||||
gst_pad_set_activate_function (demux->sinkpad,
|
"sink");
|
||||||
|
gst_pad_set_activate_function (demux->common.sinkpad,
|
||||||
GST_DEBUG_FUNCPTR (gst_matroska_demux_sink_activate));
|
GST_DEBUG_FUNCPTR (gst_matroska_demux_sink_activate));
|
||||||
gst_pad_set_activatepull_function (demux->sinkpad,
|
gst_pad_set_activatepull_function (demux->common.sinkpad,
|
||||||
GST_DEBUG_FUNCPTR (gst_matroska_demux_sink_activate_pull));
|
GST_DEBUG_FUNCPTR (gst_matroska_demux_sink_activate_pull));
|
||||||
gst_pad_set_chain_function (demux->sinkpad,
|
gst_pad_set_chain_function (demux->common.sinkpad,
|
||||||
GST_DEBUG_FUNCPTR (gst_matroska_demux_chain));
|
GST_DEBUG_FUNCPTR (gst_matroska_demux_chain));
|
||||||
gst_pad_set_event_function (demux->sinkpad,
|
gst_pad_set_event_function (demux->common.sinkpad,
|
||||||
GST_DEBUG_FUNCPTR (gst_matroska_demux_handle_sink_event));
|
GST_DEBUG_FUNCPTR (gst_matroska_demux_handle_sink_event));
|
||||||
gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
|
gst_element_add_pad (GST_ELEMENT (demux), demux->common.sinkpad);
|
||||||
|
|
||||||
/* initial stream no. */
|
/* initial stream no. */
|
||||||
demux->common.src = NULL;
|
demux->common.src = NULL;
|
||||||
|
@ -417,7 +418,7 @@ gst_matroska_demux_reset (GstElement * element)
|
||||||
demux->last_stop_end = GST_CLOCK_TIME_NONE;
|
demux->last_stop_end = GST_CLOCK_TIME_NONE;
|
||||||
demux->seek_block = 0;
|
demux->seek_block = 0;
|
||||||
|
|
||||||
demux->offset = 0;
|
demux->common.offset = 0;
|
||||||
demux->cluster_time = GST_CLOCK_TIME_NONE;
|
demux->cluster_time = GST_CLOCK_TIME_NONE;
|
||||||
demux->cluster_offset = 0;
|
demux->cluster_offset = 0;
|
||||||
demux->next_cluster_offset = 0;
|
demux->next_cluster_offset = 0;
|
||||||
|
@ -454,103 +455,19 @@ gst_matroska_demux_reset (GstElement * element)
|
||||||
}
|
}
|
||||||
demux->global_tags = gst_tag_list_new ();
|
demux->global_tags = gst_tag_list_new ();
|
||||||
|
|
||||||
if (demux->cached_buffer) {
|
if (demux->common.cached_buffer) {
|
||||||
gst_buffer_unref (demux->cached_buffer);
|
gst_buffer_unref (demux->common.cached_buffer);
|
||||||
demux->cached_buffer = NULL;
|
demux->common.cached_buffer = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Calls pull_range for (offset,size) without advancing our offset
|
|
||||||
*/
|
|
||||||
static GstFlowReturn
|
|
||||||
gst_matroska_demux_peek_bytes (GstMatroskaDemux * demux, guint64 offset,
|
|
||||||
guint size, GstBuffer ** p_buf, guint8 ** bytes)
|
|
||||||
{
|
|
||||||
GstFlowReturn ret;
|
|
||||||
|
|
||||||
/* Caching here actually makes much less difference than one would expect.
|
|
||||||
* We do it mainly to avoid pulling buffers of 1 byte all the time */
|
|
||||||
if (demux->cached_buffer) {
|
|
||||||
guint64 cache_offset = GST_BUFFER_OFFSET (demux->cached_buffer);
|
|
||||||
guint cache_size = GST_BUFFER_SIZE (demux->cached_buffer);
|
|
||||||
|
|
||||||
if (cache_offset <= demux->offset &&
|
|
||||||
(demux->offset + size) <= (cache_offset + cache_size)) {
|
|
||||||
if (p_buf)
|
|
||||||
*p_buf = gst_buffer_create_sub (demux->cached_buffer,
|
|
||||||
demux->offset - cache_offset, size);
|
|
||||||
if (bytes)
|
|
||||||
*bytes = GST_BUFFER_DATA (demux->cached_buffer) + demux->offset -
|
|
||||||
cache_offset;
|
|
||||||
return GST_FLOW_OK;
|
|
||||||
}
|
|
||||||
/* not enough data in the cache, free cache and get a new one */
|
|
||||||
gst_buffer_unref (demux->cached_buffer);
|
|
||||||
demux->cached_buffer = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* refill the cache */
|
|
||||||
ret = gst_pad_pull_range (demux->sinkpad, demux->offset,
|
|
||||||
MAX (size, 64 * 1024), &demux->cached_buffer);
|
|
||||||
if (ret != GST_FLOW_OK) {
|
|
||||||
demux->cached_buffer = NULL;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GST_BUFFER_SIZE (demux->cached_buffer) >= size) {
|
|
||||||
if (p_buf)
|
|
||||||
*p_buf = gst_buffer_create_sub (demux->cached_buffer, 0, size);
|
|
||||||
if (bytes)
|
|
||||||
*bytes = GST_BUFFER_DATA (demux->cached_buffer);
|
|
||||||
return GST_FLOW_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Not possible to get enough data, try a last time with
|
|
||||||
* requesting exactly the size we need */
|
|
||||||
gst_buffer_unref (demux->cached_buffer);
|
|
||||||
demux->cached_buffer = NULL;
|
|
||||||
|
|
||||||
ret =
|
|
||||||
gst_pad_pull_range (demux->sinkpad, demux->offset, size,
|
|
||||||
&demux->cached_buffer);
|
|
||||||
if (ret != GST_FLOW_OK) {
|
|
||||||
GST_DEBUG_OBJECT (demux, "pull_range returned %d", ret);
|
|
||||||
if (p_buf)
|
|
||||||
*p_buf = NULL;
|
|
||||||
if (bytes)
|
|
||||||
*bytes = NULL;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GST_BUFFER_SIZE (demux->cached_buffer) < size) {
|
|
||||||
GST_WARNING_OBJECT (demux, "Dropping short buffer at offset %"
|
|
||||||
G_GUINT64_FORMAT ": wanted %u bytes, got %u bytes", demux->offset,
|
|
||||||
size, GST_BUFFER_SIZE (demux->cached_buffer));
|
|
||||||
|
|
||||||
gst_buffer_unref (demux->cached_buffer);
|
|
||||||
demux->cached_buffer = NULL;
|
|
||||||
if (p_buf)
|
|
||||||
*p_buf = NULL;
|
|
||||||
if (bytes)
|
|
||||||
*bytes = NULL;
|
|
||||||
return GST_FLOW_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p_buf)
|
|
||||||
*p_buf = gst_buffer_create_sub (demux->cached_buffer, 0, size);
|
|
||||||
if (bytes)
|
|
||||||
*bytes = GST_BUFFER_DATA (demux->cached_buffer);
|
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const guint8 *
|
static const guint8 *
|
||||||
gst_matroska_demux_peek_pull (GstMatroskaDemux * demux, guint peek)
|
gst_matroska_demux_peek_pull (GstMatroskaDemux * demux, guint peek)
|
||||||
{
|
{
|
||||||
guint8 *data = NULL;
|
guint8 *data = NULL;
|
||||||
|
|
||||||
gst_matroska_demux_peek_bytes (demux, demux->offset, peek, NULL, &data);
|
gst_matroska_read_common_peek_bytes (&demux->common, demux->common.offset,
|
||||||
|
peek, NULL, &data);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -560,7 +477,7 @@ gst_matroska_demux_peek_id_length_pull (GstMatroskaDemux * demux, guint32 * _id,
|
||||||
{
|
{
|
||||||
return gst_ebml_peek_id_length (_id, _length, _needed,
|
return gst_ebml_peek_id_length (_id, _length, _needed,
|
||||||
(GstPeekData) gst_matroska_demux_peek_pull, (gpointer) demux,
|
(GstPeekData) gst_matroska_demux_peek_pull, (gpointer) demux,
|
||||||
GST_ELEMENT_CAST (demux), demux->offset);
|
GST_ELEMENT_CAST (demux), demux->common.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gint64
|
static gint64
|
||||||
|
@ -569,7 +486,7 @@ gst_matroska_demux_get_length (GstMatroskaDemux * demux)
|
||||||
GstFormat fmt = GST_FORMAT_BYTES;
|
GstFormat fmt = GST_FORMAT_BYTES;
|
||||||
gint64 end = -1;
|
gint64 end = -1;
|
||||||
|
|
||||||
if (!gst_pad_query_peer_duration (demux->sinkpad, &fmt, &end) ||
|
if (!gst_pad_query_peer_duration (demux->common.sinkpad, &fmt, &end) ||
|
||||||
fmt != GST_FORMAT_BYTES || end < 0)
|
fmt != GST_FORMAT_BYTES || end < 0)
|
||||||
GST_DEBUG_OBJECT (demux, "no upstream length");
|
GST_DEBUG_OBJECT (demux, "no upstream length");
|
||||||
|
|
||||||
|
@ -1885,7 +1802,7 @@ gst_matroska_demux_move_to_entry (GstMatroskaDemux * demux,
|
||||||
|
|
||||||
/* seek (relative to matroska segment) */
|
/* seek (relative to matroska segment) */
|
||||||
/* position might be invalid; will error when streaming resumes ... */
|
/* position might be invalid; will error when streaming resumes ... */
|
||||||
demux->offset = entry->pos + demux->common.ebml_segment_start;
|
demux->common.offset = entry->pos + demux->common.ebml_segment_start;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (demux, "Seeked to offset %" G_GUINT64_FORMAT ", block %d, "
|
GST_DEBUG_OBJECT (demux, "Seeked to offset %" G_GUINT64_FORMAT ", block %d, "
|
||||||
"time %" GST_TIME_FORMAT, entry->pos + demux->common.ebml_segment_start,
|
"time %" GST_TIME_FORMAT, entry->pos + demux->common.ebml_segment_start,
|
||||||
|
@ -1940,7 +1857,7 @@ gst_matroska_demux_search_cluster (GstMatroskaDemux * demux, gint64 * pos)
|
||||||
guint32 id;
|
guint32 id;
|
||||||
guint needed;
|
guint needed;
|
||||||
|
|
||||||
orig_offset = demux->offset;
|
orig_offset = demux->common.offset;
|
||||||
|
|
||||||
GST_LOG_OBJECT (demux, "searching cluster following offset %" G_GINT64_FORMAT,
|
GST_LOG_OBJECT (demux, "searching cluster following offset %" G_GINT64_FORMAT,
|
||||||
*pos);
|
*pos);
|
||||||
|
@ -1956,7 +1873,7 @@ gst_matroska_demux_search_cluster (GstMatroskaDemux * demux, gint64 * pos)
|
||||||
if (cpos) {
|
if (cpos) {
|
||||||
GST_DEBUG_OBJECT (demux,
|
GST_DEBUG_OBJECT (demux,
|
||||||
"cluster reported at offset %" G_GINT64_FORMAT, *cpos);
|
"cluster reported at offset %" G_GINT64_FORMAT, *cpos);
|
||||||
demux->offset = *cpos;
|
demux->common.offset = *cpos;
|
||||||
ret =
|
ret =
|
||||||
gst_matroska_demux_peek_id_length_pull (demux, &id, &length, &needed);
|
gst_matroska_demux_peek_id_length_pull (demux, &id, &length, &needed);
|
||||||
if (ret == GST_FLOW_OK && id == GST_MATROSKA_ID_CLUSTER) {
|
if (ret == GST_FLOW_OK && id == GST_MATROSKA_ID_CLUSTER) {
|
||||||
|
@ -1971,7 +1888,7 @@ gst_matroska_demux_search_cluster (GstMatroskaDemux * demux, gint64 * pos)
|
||||||
GstByteReader reader;
|
GstByteReader reader;
|
||||||
gint cluster_pos;
|
gint cluster_pos;
|
||||||
|
|
||||||
ret = gst_pad_pull_range (demux->sinkpad, newpos, chunk, &buf);
|
ret = gst_pad_pull_range (demux->common.sinkpad, newpos, chunk, &buf);
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
break;
|
break;
|
||||||
GST_DEBUG_OBJECT (demux, "read buffer size %d at offset %" G_GINT64_FORMAT,
|
GST_DEBUG_OBJECT (demux, "read buffer size %d at offset %" G_GINT64_FORMAT,
|
||||||
|
@ -1996,7 +1913,7 @@ gst_matroska_demux_search_cluster (GstMatroskaDemux * demux, gint64 * pos)
|
||||||
GST_DEBUG_OBJECT (demux, "cluster is first cluster -> OK");
|
GST_DEBUG_OBJECT (demux, "cluster is first cluster -> OK");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
demux->offset = newpos;
|
demux->common.offset = newpos;
|
||||||
ret =
|
ret =
|
||||||
gst_matroska_demux_peek_id_length_pull (demux, &id, &length, &needed);
|
gst_matroska_demux_peek_id_length_pull (demux, &id, &length, &needed);
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
|
@ -2010,7 +1927,7 @@ gst_matroska_demux_search_cluster (GstMatroskaDemux * demux, gint64 * pos)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* skip cluster */
|
/* skip cluster */
|
||||||
demux->offset += length + needed;
|
demux->common.offset += length + needed;
|
||||||
ret =
|
ret =
|
||||||
gst_matroska_demux_peek_id_length_pull (demux, &id, &length, &needed);
|
gst_matroska_demux_peek_id_length_pull (demux, &id, &length, &needed);
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
|
@ -2035,7 +1952,7 @@ gst_matroska_demux_search_cluster (GstMatroskaDemux * demux, gint64 * pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
demux->offset = orig_offset;
|
demux->common.offset = orig_offset;
|
||||||
*pos = newpos;
|
*pos = newpos;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -2069,13 +1986,13 @@ gst_matroska_demux_search_pos (GstMatroskaDemux * demux, GstClockTime time)
|
||||||
|
|
||||||
current_cluster_offset = demux->cluster_offset;
|
current_cluster_offset = demux->cluster_offset;
|
||||||
current_cluster_time = demux->cluster_time;
|
current_cluster_time = demux->cluster_time;
|
||||||
current_offset = demux->offset;
|
current_offset = demux->common.offset;
|
||||||
|
|
||||||
demux->common.state = GST_MATROSKA_READ_STATE_SCANNING;
|
demux->common.state = GST_MATROSKA_READ_STATE_SCANNING;
|
||||||
|
|
||||||
/* estimate using start and current position */
|
/* estimate using start and current position */
|
||||||
GST_OBJECT_LOCK (demux);
|
GST_OBJECT_LOCK (demux);
|
||||||
opos = demux->offset - demux->common.ebml_segment_start;
|
opos = demux->common.offset - demux->common.ebml_segment_start;
|
||||||
otime = demux->segment.last_stop;
|
otime = demux->segment.last_stop;
|
||||||
GST_OBJECT_UNLOCK (demux);
|
GST_OBJECT_UNLOCK (demux);
|
||||||
|
|
||||||
|
@ -2121,7 +2038,7 @@ retry:
|
||||||
|
|
||||||
/* then start scanning and parsing for cluster time,
|
/* then start scanning and parsing for cluster time,
|
||||||
* re-estimate if overshoot, otherwise next cluster and so on */
|
* re-estimate if overshoot, otherwise next cluster and so on */
|
||||||
demux->offset = newpos;
|
demux->common.offset = newpos;
|
||||||
demux->cluster_time = cluster_time = GST_CLOCK_TIME_NONE;
|
demux->cluster_time = cluster_time = GST_CLOCK_TIME_NONE;
|
||||||
while (1) {
|
while (1) {
|
||||||
guint64 cluster_size = 0;
|
guint64 cluster_size = 0;
|
||||||
|
@ -2131,7 +2048,7 @@ retry:
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
goto error;
|
goto error;
|
||||||
GST_LOG_OBJECT (demux, "Offset %" G_GUINT64_FORMAT ", Element id 0x%x, "
|
GST_LOG_OBJECT (demux, "Offset %" G_GUINT64_FORMAT ", Element id 0x%x, "
|
||||||
"size %" G_GUINT64_FORMAT ", needed %d", demux->offset, id,
|
"size %" G_GUINT64_FORMAT ", needed %d", demux->common.offset, id,
|
||||||
length, needed);
|
length, needed);
|
||||||
ret = gst_matroska_demux_parse_id (demux, id, length, needed);
|
ret = gst_matroska_demux_parse_id (demux, id, length, needed);
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
|
@ -2178,7 +2095,7 @@ retry:
|
||||||
* otherwise will be skippingly parsed into */
|
* otherwise will be skippingly parsed into */
|
||||||
if (cluster_size) {
|
if (cluster_size) {
|
||||||
GST_DEBUG_OBJECT (demux, "skipping to next cluster");
|
GST_DEBUG_OBJECT (demux, "skipping to next cluster");
|
||||||
demux->offset = cluster_offset + cluster_size;
|
demux->common.offset = cluster_offset + cluster_size;
|
||||||
demux->cluster_time = GST_CLOCK_TIME_NONE;
|
demux->cluster_time = GST_CLOCK_TIME_NONE;
|
||||||
} else {
|
} else {
|
||||||
GST_DEBUG_OBJECT (demux, "parsing/skipping cluster elements");
|
GST_DEBUG_OBJECT (demux, "parsing/skipping cluster elements");
|
||||||
|
@ -2208,7 +2125,7 @@ exit:
|
||||||
/* restore some state */
|
/* restore some state */
|
||||||
demux->cluster_offset = current_cluster_offset;
|
demux->cluster_offset = current_cluster_offset;
|
||||||
demux->cluster_time = current_cluster_time;
|
demux->cluster_time = current_cluster_time;
|
||||||
demux->offset = current_offset;
|
demux->common.offset = current_offset;
|
||||||
demux->common.state = current_state;
|
demux->common.state = current_state;
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
|
@ -2283,24 +2200,24 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
|
||||||
|
|
||||||
if (flush) {
|
if (flush) {
|
||||||
GST_DEBUG_OBJECT (demux, "Starting flush");
|
GST_DEBUG_OBJECT (demux, "Starting flush");
|
||||||
gst_pad_push_event (demux->sinkpad, gst_event_new_flush_start ());
|
gst_pad_push_event (demux->common.sinkpad, gst_event_new_flush_start ());
|
||||||
gst_matroska_demux_send_event (demux, gst_event_new_flush_start ());
|
gst_matroska_demux_send_event (demux, gst_event_new_flush_start ());
|
||||||
} else {
|
} else {
|
||||||
GST_DEBUG_OBJECT (demux, "Non-flushing seek, pausing task");
|
GST_DEBUG_OBJECT (demux, "Non-flushing seek, pausing task");
|
||||||
gst_pad_pause_task (demux->sinkpad);
|
gst_pad_pause_task (demux->common.sinkpad);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now grab the stream lock so that streaming cannot continue, for
|
/* now grab the stream lock so that streaming cannot continue, for
|
||||||
* non flushing seeks when the element is in PAUSED this could block
|
* non flushing seeks when the element is in PAUSED this could block
|
||||||
* forever. */
|
* forever. */
|
||||||
GST_DEBUG_OBJECT (demux, "Waiting for streaming to stop");
|
GST_DEBUG_OBJECT (demux, "Waiting for streaming to stop");
|
||||||
GST_PAD_STREAM_LOCK (demux->sinkpad);
|
GST_PAD_STREAM_LOCK (demux->common.sinkpad);
|
||||||
|
|
||||||
/* pull mode without index can do some scanning */
|
/* pull mode without index can do some scanning */
|
||||||
if (!demux->streaming && !demux->common.index) {
|
if (!demux->streaming && !demux->common.index) {
|
||||||
/* need to stop flushing upstream as we need it next */
|
/* need to stop flushing upstream as we need it next */
|
||||||
if (flush)
|
if (flush)
|
||||||
gst_pad_push_event (demux->sinkpad, gst_event_new_flush_stop ());
|
gst_pad_push_event (demux->common.sinkpad, gst_event_new_flush_stop ());
|
||||||
entry = gst_matroska_demux_search_pos (demux, seeksegment.last_stop);
|
entry = gst_matroska_demux_search_pos (demux, seeksegment.last_stop);
|
||||||
/* keep local copy */
|
/* keep local copy */
|
||||||
if (entry) {
|
if (entry) {
|
||||||
|
@ -2325,7 +2242,7 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
|
||||||
|
|
||||||
if (flush) {
|
if (flush) {
|
||||||
GST_DEBUG_OBJECT (demux, "Stopping flush");
|
GST_DEBUG_OBJECT (demux, "Stopping flush");
|
||||||
gst_pad_push_event (demux->sinkpad, gst_event_new_flush_stop ());
|
gst_pad_push_event (demux->common.sinkpad, gst_event_new_flush_stop ());
|
||||||
gst_matroska_demux_send_event (demux, gst_event_new_flush_stop ());
|
gst_matroska_demux_send_event (demux, gst_event_new_flush_stop ());
|
||||||
} else if (demux->segment_running) {
|
} else if (demux->segment_running) {
|
||||||
GST_DEBUG_OBJECT (demux, "Closing currently running segment");
|
GST_DEBUG_OBJECT (demux, "Closing currently running segment");
|
||||||
|
@ -2370,17 +2287,17 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
|
||||||
/* restart our task since it might have been stopped when we did the
|
/* restart our task since it might have been stopped when we did the
|
||||||
* flush. */
|
* flush. */
|
||||||
demux->segment_running = TRUE;
|
demux->segment_running = TRUE;
|
||||||
gst_pad_start_task (demux->sinkpad, (GstTaskFunction) gst_matroska_demux_loop,
|
gst_pad_start_task (demux->common.sinkpad,
|
||||||
demux->sinkpad);
|
(GstTaskFunction) gst_matroska_demux_loop, demux->common.sinkpad);
|
||||||
|
|
||||||
/* streaming can continue now */
|
/* streaming can continue now */
|
||||||
GST_PAD_STREAM_UNLOCK (demux->sinkpad);
|
GST_PAD_STREAM_UNLOCK (demux->common.sinkpad);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
seek_error:
|
seek_error:
|
||||||
{
|
{
|
||||||
GST_PAD_STREAM_UNLOCK (demux->sinkpad);
|
GST_PAD_STREAM_UNLOCK (demux->common.sinkpad);
|
||||||
GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), ("Got a seek error"));
|
GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), ("Got a seek error"));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -2519,7 +2436,7 @@ gst_matroska_demux_handle_src_event (GstPad * pad, GstEvent * event)
|
||||||
|
|
||||||
case GST_EVENT_LATENCY:
|
case GST_EVENT_LATENCY:
|
||||||
default:
|
default:
|
||||||
res = gst_pad_push_event (demux->sinkpad, event);
|
res = gst_pad_push_event (demux->common.sinkpad, event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4673,7 +4590,7 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux,
|
||||||
|
|
||||||
/* remember */
|
/* remember */
|
||||||
length = gst_matroska_demux_get_length (demux);
|
length = gst_matroska_demux_get_length (demux);
|
||||||
before_pos = demux->offset;
|
before_pos = demux->common.offset;
|
||||||
|
|
||||||
if (length == (guint64) - 1) {
|
if (length == (guint64) - 1) {
|
||||||
GST_DEBUG_OBJECT (demux, "no upstream length, skipping SeakHead entry");
|
GST_DEBUG_OBJECT (demux, "no upstream length, skipping SeakHead entry");
|
||||||
|
@ -4701,7 +4618,7 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* seek */
|
/* seek */
|
||||||
demux->offset = seek_pos + demux->common.ebml_segment_start;
|
demux->common.offset = seek_pos + demux->common.ebml_segment_start;
|
||||||
|
|
||||||
/* check ID */
|
/* check ID */
|
||||||
if ((ret = gst_matroska_demux_peek_id_length_pull (demux, &id, &length,
|
if ((ret = gst_matroska_demux_peek_id_length_pull (demux, &id, &length,
|
||||||
|
@ -4719,7 +4636,7 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux,
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
/* seek back */
|
/* seek back */
|
||||||
demux->offset = before_pos;
|
demux->common.offset = before_pos;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4823,7 +4740,7 @@ gst_matroska_demux_check_parse_error (GstMatroskaDemux * demux)
|
||||||
/* just repositioning to where next cluster should be and try from there */
|
/* just repositioning to where next cluster should be and try from there */
|
||||||
GST_WARNING_OBJECT (demux, "parse error, trying next cluster expected at %"
|
GST_WARNING_OBJECT (demux, "parse error, trying next cluster expected at %"
|
||||||
G_GUINT64_FORMAT, demux->next_cluster_offset);
|
G_GUINT64_FORMAT, demux->next_cluster_offset);
|
||||||
demux->offset = demux->next_cluster_offset;
|
demux->common.offset = demux->next_cluster_offset;
|
||||||
demux->next_cluster_offset = 0;
|
demux->next_cluster_offset = 0;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
} else {
|
} else {
|
||||||
|
@ -4831,7 +4748,7 @@ gst_matroska_demux_check_parse_error (GstMatroskaDemux * demux)
|
||||||
|
|
||||||
/* sigh, one last attempt above and beyond call of duty ...;
|
/* sigh, one last attempt above and beyond call of duty ...;
|
||||||
* search for cluster mark following current pos */
|
* search for cluster mark following current pos */
|
||||||
pos = demux->offset;
|
pos = demux->common.offset;
|
||||||
GST_WARNING_OBJECT (demux, "parse error, looking for next cluster");
|
GST_WARNING_OBJECT (demux, "parse error, looking for next cluster");
|
||||||
if (gst_matroska_demux_search_cluster (demux, &pos) != GST_FLOW_OK) {
|
if (gst_matroska_demux_search_cluster (demux, &pos) != GST_FLOW_OK) {
|
||||||
/* did not work, give up */
|
/* did not work, give up */
|
||||||
|
@ -4839,7 +4756,7 @@ gst_matroska_demux_check_parse_error (GstMatroskaDemux * demux)
|
||||||
} else {
|
} else {
|
||||||
GST_DEBUG_OBJECT (demux, "... found at %" G_GUINT64_FORMAT, pos);
|
GST_DEBUG_OBJECT (demux, "... found at %" G_GUINT64_FORMAT, pos);
|
||||||
/* try that position */
|
/* try that position */
|
||||||
demux->offset = pos;
|
demux->common.offset = pos;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4849,7 +4766,7 @@ static inline GstFlowReturn
|
||||||
gst_matroska_demux_flush (GstMatroskaDemux * demux, guint flush)
|
gst_matroska_demux_flush (GstMatroskaDemux * demux, guint flush)
|
||||||
{
|
{
|
||||||
GST_LOG_OBJECT (demux, "skipping %d bytes", flush);
|
GST_LOG_OBJECT (demux, "skipping %d bytes", flush);
|
||||||
demux->offset += flush;
|
demux->common.offset += flush;
|
||||||
if (demux->streaming) {
|
if (demux->streaming) {
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
|
|
||||||
|
@ -4895,11 +4812,12 @@ gst_matroska_demux_take (GstMatroskaDemux * demux, guint64 bytes,
|
||||||
else
|
else
|
||||||
ret = GST_FLOW_UNEXPECTED;
|
ret = GST_FLOW_UNEXPECTED;
|
||||||
} else
|
} else
|
||||||
ret = gst_matroska_demux_peek_bytes (demux, demux->offset, bytes, &buffer,
|
ret = gst_matroska_read_common_peek_bytes (&demux->common,
|
||||||
NULL);
|
demux->common.offset, bytes, &buffer, NULL);
|
||||||
if (G_LIKELY (buffer)) {
|
if (G_LIKELY (buffer)) {
|
||||||
gst_ebml_read_init (ebml, GST_ELEMENT_CAST (demux), buffer, demux->offset);
|
gst_ebml_read_init (ebml, GST_ELEMENT_CAST (demux), buffer,
|
||||||
demux->offset += bytes;
|
demux->common.offset);
|
||||||
|
demux->common.offset += bytes;
|
||||||
}
|
}
|
||||||
exit:
|
exit:
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -4913,7 +4831,7 @@ gst_matroska_demux_check_seekability (GstMatroskaDemux * demux)
|
||||||
gint64 start = -1, stop = -1;
|
gint64 start = -1, stop = -1;
|
||||||
|
|
||||||
query = gst_query_new_seeking (GST_FORMAT_BYTES);
|
query = gst_query_new_seeking (GST_FORMAT_BYTES);
|
||||||
if (!gst_pad_peer_query (demux->sinkpad, query)) {
|
if (!gst_pad_peer_query (demux->common.sinkpad, query)) {
|
||||||
GST_DEBUG_OBJECT (demux, "seeking query failed");
|
GST_DEBUG_OBJECT (demux, "seeking query failed");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@ -4925,7 +4843,7 @@ gst_matroska_demux_check_seekability (GstMatroskaDemux * demux)
|
||||||
GstFormat fmt = GST_FORMAT_BYTES;
|
GstFormat fmt = GST_FORMAT_BYTES;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
|
GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
|
||||||
gst_pad_query_peer_duration (demux->sinkpad, &fmt, &stop);
|
gst_pad_query_peer_duration (demux->common.sinkpad, &fmt, &stop);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if upstream doesn't know the size, it's likely that it's not seekable in
|
/* if upstream doesn't know the size, it's likely that it's not seekable in
|
||||||
|
@ -4956,7 +4874,7 @@ gst_matroska_demux_find_tracks (GstMatroskaDemux * demux)
|
||||||
"Found Cluster element before Tracks, searching Tracks");
|
"Found Cluster element before Tracks, searching Tracks");
|
||||||
|
|
||||||
/* remember */
|
/* remember */
|
||||||
before_pos = demux->offset;
|
before_pos = demux->common.offset;
|
||||||
|
|
||||||
/* Search Tracks element */
|
/* Search Tracks element */
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
|
@ -4971,8 +4889,8 @@ gst_matroska_demux_find_tracks (GstMatroskaDemux * demux)
|
||||||
ret = gst_matroska_demux_check_read_size (demux, length);
|
ret = gst_matroska_demux_check_read_size (demux, length);
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
demux->offset += needed;
|
demux->common.offset += needed;
|
||||||
demux->offset += length;
|
demux->common.offset += length;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -4983,7 +4901,7 @@ gst_matroska_demux_find_tracks (GstMatroskaDemux * demux)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* seek back */
|
/* seek back */
|
||||||
demux->offset = before_pos;
|
demux->common.offset = before_pos;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -5039,10 +4957,10 @@ gst_matroska_demux_parse_id (GstMatroskaDemux * demux, guint32 id,
|
||||||
GST_READ_CHECK (gst_matroska_demux_flush (demux, needed));
|
GST_READ_CHECK (gst_matroska_demux_flush (demux, needed));
|
||||||
GST_DEBUG_OBJECT (demux,
|
GST_DEBUG_OBJECT (demux,
|
||||||
"Found Segment start at offset %" G_GUINT64_FORMAT,
|
"Found Segment start at offset %" G_GUINT64_FORMAT,
|
||||||
demux->offset);
|
demux->common.offset);
|
||||||
/* seeks are from the beginning of the segment,
|
/* seeks are from the beginning of the segment,
|
||||||
* after the segment ID/length */
|
* after the segment ID/length */
|
||||||
demux->common.ebml_segment_start = demux->offset;
|
demux->common.ebml_segment_start = demux->common.offset;
|
||||||
demux->common.state = GST_MATROSKA_READ_STATE_HEADER;
|
demux->common.state = GST_MATROSKA_READ_STATE_HEADER;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -5092,7 +5010,7 @@ gst_matroska_demux_parse_id (GstMatroskaDemux * demux, guint32 id,
|
||||||
if (G_UNLIKELY (demux->common.state
|
if (G_UNLIKELY (demux->common.state
|
||||||
== GST_MATROSKA_READ_STATE_HEADER)) {
|
== GST_MATROSKA_READ_STATE_HEADER)) {
|
||||||
demux->common.state = GST_MATROSKA_READ_STATE_DATA;
|
demux->common.state = GST_MATROSKA_READ_STATE_DATA;
|
||||||
demux->first_cluster_offset = demux->offset;
|
demux->first_cluster_offset = demux->common.offset;
|
||||||
GST_DEBUG_OBJECT (demux, "signaling no more pads");
|
GST_DEBUG_OBJECT (demux, "signaling no more pads");
|
||||||
gst_element_no_more_pads (GST_ELEMENT (demux));
|
gst_element_no_more_pads (GST_ELEMENT (demux));
|
||||||
/* send initial newsegment */
|
/* send initial newsegment */
|
||||||
|
@ -5103,7 +5021,7 @@ gst_matroska_demux_parse_id (GstMatroskaDemux * demux, guint32 id,
|
||||||
0) ? demux->segment.duration : -1, 0));
|
0) ? demux->segment.duration : -1, 0));
|
||||||
}
|
}
|
||||||
demux->cluster_time = GST_CLOCK_TIME_NONE;
|
demux->cluster_time = GST_CLOCK_TIME_NONE;
|
||||||
demux->cluster_offset = demux->offset;
|
demux->cluster_offset = demux->common.offset;
|
||||||
if (G_UNLIKELY (!demux->seek_first && demux->seek_block)) {
|
if (G_UNLIKELY (!demux->seek_first && demux->seek_block)) {
|
||||||
GST_DEBUG_OBJECT (demux, "seek target block %" G_GUINT64_FORMAT
|
GST_DEBUG_OBJECT (demux, "seek target block %" G_GUINT64_FORMAT
|
||||||
" not found in Cluster, trying next Cluster's first block instead",
|
" not found in Cluster, trying next Cluster's first block instead",
|
||||||
|
@ -5306,7 +5224,7 @@ gst_matroska_demux_loop (GstPad * pad)
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_LOG_OBJECT (demux, "Offset %" G_GUINT64_FORMAT ", Element id 0x%x, "
|
GST_LOG_OBJECT (demux, "Offset %" G_GUINT64_FORMAT ", Element id 0x%x, "
|
||||||
"size %" G_GUINT64_FORMAT ", needed %d", demux->offset, id,
|
"size %" G_GUINT64_FORMAT ", needed %d", demux->common.offset, id,
|
||||||
length, needed);
|
length, needed);
|
||||||
|
|
||||||
ret = gst_matroska_demux_parse_id (demux, id, length, needed);
|
ret = gst_matroska_demux_parse_id (demux, id, length, needed);
|
||||||
|
@ -5335,7 +5253,8 @@ gst_matroska_demux_loop (GstPad * pad)
|
||||||
}
|
}
|
||||||
|
|
||||||
next:
|
next:
|
||||||
if (G_UNLIKELY (demux->offset == gst_matroska_demux_get_length (demux))) {
|
if (G_UNLIKELY (demux->common.offset ==
|
||||||
|
gst_matroska_demux_get_length (demux))) {
|
||||||
GST_LOG_OBJECT (demux, "Reached end of stream");
|
GST_LOG_OBJECT (demux, "Reached end of stream");
|
||||||
ret = GST_FLOW_UNEXPECTED;
|
ret = GST_FLOW_UNEXPECTED;
|
||||||
goto eos;
|
goto eos;
|
||||||
|
@ -5360,7 +5279,7 @@ pause:
|
||||||
|
|
||||||
GST_LOG_OBJECT (demux, "pausing task, reason %s", reason);
|
GST_LOG_OBJECT (demux, "pausing task, reason %s", reason);
|
||||||
demux->segment_running = FALSE;
|
demux->segment_running = FALSE;
|
||||||
gst_pad_pause_task (demux->sinkpad);
|
gst_pad_pause_task (demux->common.sinkpad);
|
||||||
|
|
||||||
if (ret == GST_FLOW_UNEXPECTED) {
|
if (ret == GST_FLOW_UNEXPECTED) {
|
||||||
/* perform EOS logic */
|
/* perform EOS logic */
|
||||||
|
@ -5428,7 +5347,7 @@ perform_seek_to_offset (GstMatroskaDemux * demux, guint64 offset)
|
||||||
GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
|
GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
|
||||||
GST_SEEK_TYPE_NONE, -1);
|
GST_SEEK_TYPE_NONE, -1);
|
||||||
|
|
||||||
res = gst_pad_push_event (demux->sinkpad, event);
|
res = gst_pad_push_event (demux->common.sinkpad, event);
|
||||||
|
|
||||||
/* newsegment event will update offset */
|
/* newsegment event will update offset */
|
||||||
return res;
|
return res;
|
||||||
|
@ -5446,7 +5365,7 @@ gst_matroska_demux_peek_id_length_push (GstMatroskaDemux * demux, guint32 * _id,
|
||||||
{
|
{
|
||||||
return gst_ebml_peek_id_length (_id, _length, _needed,
|
return gst_ebml_peek_id_length (_id, _length, _needed,
|
||||||
(GstPeekData) gst_matroska_demux_peek_adapter, (gpointer) demux,
|
(GstPeekData) gst_matroska_demux_peek_adapter, (gpointer) demux,
|
||||||
GST_ELEMENT_CAST (demux), demux->offset);
|
GST_ELEMENT_CAST (demux), demux->common.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
|
@ -5478,8 +5397,8 @@ next:
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
GST_LOG_OBJECT (demux, "Offset %" G_GUINT64_FORMAT ", Element id 0x%x, "
|
GST_LOG_OBJECT (demux, "Offset %" G_GUINT64_FORMAT ", Element id 0x%x, "
|
||||||
"size %" G_GUINT64_FORMAT ", needed %d, available %d", demux->offset, id,
|
"size %" G_GUINT64_FORMAT ", needed %d, available %d",
|
||||||
length, needed, available);
|
demux->common.offset, id, length, needed, available);
|
||||||
|
|
||||||
if (needed > available)
|
if (needed > available)
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
|
@ -5538,7 +5457,7 @@ gst_matroska_demux_handle_sink_event (GstPad * pad, GstEvent * event)
|
||||||
/* clear current segment leftover */
|
/* clear current segment leftover */
|
||||||
gst_adapter_clear (demux->adapter);
|
gst_adapter_clear (demux->adapter);
|
||||||
/* and some streaming setup */
|
/* and some streaming setup */
|
||||||
demux->offset = start;
|
demux->common.offset = start;
|
||||||
/* do not know where we are;
|
/* do not know where we are;
|
||||||
* need to come across a cluster and generate newsegment */
|
* need to come across a cluster and generate newsegment */
|
||||||
demux->segment.last_stop = GST_CLOCK_TIME_NONE;
|
demux->segment.last_stop = GST_CLOCK_TIME_NONE;
|
||||||
|
|
|
@ -51,7 +51,6 @@ typedef struct _GstMatroskaDemux {
|
||||||
GstMatroskaReadCommon common;
|
GstMatroskaReadCommon common;
|
||||||
|
|
||||||
/* pads */
|
/* pads */
|
||||||
GstPad *sinkpad;
|
|
||||||
GstClock *clock;
|
GstClock *clock;
|
||||||
guint num_v_streams;
|
guint num_v_streams;
|
||||||
guint num_a_streams;
|
guint num_a_streams;
|
||||||
|
@ -87,11 +86,6 @@ typedef struct _GstMatroskaDemux {
|
||||||
GstEvent *new_segment;
|
GstEvent *new_segment;
|
||||||
GstTagList *global_tags;
|
GstTagList *global_tags;
|
||||||
|
|
||||||
/* pull mode caching */
|
|
||||||
GstBuffer *cached_buffer;
|
|
||||||
|
|
||||||
/* push and pull mode */
|
|
||||||
guint64 offset;
|
|
||||||
/* some state saving */
|
/* some state saving */
|
||||||
GstClockTime cluster_time;
|
GstClockTime cluster_time;
|
||||||
guint64 cluster_offset;
|
guint64 cluster_offset;
|
||||||
|
|
|
@ -204,12 +204,13 @@ static void
|
||||||
gst_matroska_parse_init (GstMatroskaParse * parse,
|
gst_matroska_parse_init (GstMatroskaParse * parse,
|
||||||
GstMatroskaParseClass * klass)
|
GstMatroskaParseClass * klass)
|
||||||
{
|
{
|
||||||
parse->sinkpad = gst_pad_new_from_static_template (&sink_templ, "sink");
|
parse->common.sinkpad = gst_pad_new_from_static_template (&sink_templ,
|
||||||
gst_pad_set_chain_function (parse->sinkpad,
|
"sink");
|
||||||
|
gst_pad_set_chain_function (parse->common.sinkpad,
|
||||||
GST_DEBUG_FUNCPTR (gst_matroska_parse_chain));
|
GST_DEBUG_FUNCPTR (gst_matroska_parse_chain));
|
||||||
gst_pad_set_event_function (parse->sinkpad,
|
gst_pad_set_event_function (parse->common.sinkpad,
|
||||||
GST_DEBUG_FUNCPTR (gst_matroska_parse_handle_sink_event));
|
GST_DEBUG_FUNCPTR (gst_matroska_parse_handle_sink_event));
|
||||||
gst_element_add_pad (GST_ELEMENT (parse), parse->sinkpad);
|
gst_element_add_pad (GST_ELEMENT (parse), parse->common.sinkpad);
|
||||||
|
|
||||||
parse->srcpad = gst_pad_new_from_static_template (&src_templ, "src");
|
parse->srcpad = gst_pad_new_from_static_template (&src_templ, "src");
|
||||||
gst_pad_set_event_function (parse->srcpad,
|
gst_pad_set_event_function (parse->srcpad,
|
||||||
|
@ -340,7 +341,7 @@ gst_matroska_parse_reset (GstElement * element)
|
||||||
parse->last_stop_end = GST_CLOCK_TIME_NONE;
|
parse->last_stop_end = GST_CLOCK_TIME_NONE;
|
||||||
parse->seek_block = 0;
|
parse->seek_block = 0;
|
||||||
|
|
||||||
parse->offset = 0;
|
parse->common.offset = 0;
|
||||||
parse->cluster_time = GST_CLOCK_TIME_NONE;
|
parse->cluster_time = GST_CLOCK_TIME_NONE;
|
||||||
parse->cluster_offset = 0;
|
parse->cluster_offset = 0;
|
||||||
parse->next_cluster_offset = 0;
|
parse->next_cluster_offset = 0;
|
||||||
|
@ -377,103 +378,19 @@ gst_matroska_parse_reset (GstElement * element)
|
||||||
}
|
}
|
||||||
parse->global_tags = gst_tag_list_new ();
|
parse->global_tags = gst_tag_list_new ();
|
||||||
|
|
||||||
if (parse->cached_buffer) {
|
if (parse->common.cached_buffer) {
|
||||||
gst_buffer_unref (parse->cached_buffer);
|
gst_buffer_unref (parse->common.cached_buffer);
|
||||||
parse->cached_buffer = NULL;
|
parse->common.cached_buffer = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Calls pull_range for (offset,size) without advancing our offset
|
|
||||||
*/
|
|
||||||
static GstFlowReturn
|
|
||||||
gst_matroska_parse_peek_bytes (GstMatroskaParse * parse, guint64 offset,
|
|
||||||
guint size, GstBuffer ** p_buf, guint8 ** bytes)
|
|
||||||
{
|
|
||||||
GstFlowReturn ret;
|
|
||||||
|
|
||||||
/* Caching here actually makes much less difference than one would expect.
|
|
||||||
* We do it mainly to avoid pulling buffers of 1 byte all the time */
|
|
||||||
if (parse->cached_buffer) {
|
|
||||||
guint64 cache_offset = GST_BUFFER_OFFSET (parse->cached_buffer);
|
|
||||||
guint cache_size = GST_BUFFER_SIZE (parse->cached_buffer);
|
|
||||||
|
|
||||||
if (cache_offset <= parse->offset &&
|
|
||||||
(parse->offset + size) <= (cache_offset + cache_size)) {
|
|
||||||
if (p_buf)
|
|
||||||
*p_buf = gst_buffer_create_sub (parse->cached_buffer,
|
|
||||||
parse->offset - cache_offset, size);
|
|
||||||
if (bytes)
|
|
||||||
*bytes = GST_BUFFER_DATA (parse->cached_buffer) + parse->offset -
|
|
||||||
cache_offset;
|
|
||||||
return GST_FLOW_OK;
|
|
||||||
}
|
|
||||||
/* not enough data in the cache, free cache and get a new one */
|
|
||||||
gst_buffer_unref (parse->cached_buffer);
|
|
||||||
parse->cached_buffer = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* refill the cache */
|
|
||||||
ret = gst_pad_pull_range (parse->sinkpad, parse->offset,
|
|
||||||
MAX (size, 64 * 1024), &parse->cached_buffer);
|
|
||||||
if (ret != GST_FLOW_OK) {
|
|
||||||
parse->cached_buffer = NULL;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GST_BUFFER_SIZE (parse->cached_buffer) >= size) {
|
|
||||||
if (p_buf)
|
|
||||||
*p_buf = gst_buffer_create_sub (parse->cached_buffer, 0, size);
|
|
||||||
if (bytes)
|
|
||||||
*bytes = GST_BUFFER_DATA (parse->cached_buffer);
|
|
||||||
return GST_FLOW_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Not possible to get enough data, try a last time with
|
|
||||||
* requesting exactly the size we need */
|
|
||||||
gst_buffer_unref (parse->cached_buffer);
|
|
||||||
parse->cached_buffer = NULL;
|
|
||||||
|
|
||||||
ret =
|
|
||||||
gst_pad_pull_range (parse->sinkpad, parse->offset, size,
|
|
||||||
&parse->cached_buffer);
|
|
||||||
if (ret != GST_FLOW_OK) {
|
|
||||||
GST_DEBUG_OBJECT (parse, "pull_range returned %d", ret);
|
|
||||||
if (p_buf)
|
|
||||||
*p_buf = NULL;
|
|
||||||
if (bytes)
|
|
||||||
*bytes = NULL;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GST_BUFFER_SIZE (parse->cached_buffer) < size) {
|
|
||||||
GST_WARNING_OBJECT (parse, "Dropping short buffer at offset %"
|
|
||||||
G_GUINT64_FORMAT ": wanted %u bytes, got %u bytes", parse->offset,
|
|
||||||
size, GST_BUFFER_SIZE (parse->cached_buffer));
|
|
||||||
|
|
||||||
gst_buffer_unref (parse->cached_buffer);
|
|
||||||
parse->cached_buffer = NULL;
|
|
||||||
if (p_buf)
|
|
||||||
*p_buf = NULL;
|
|
||||||
if (bytes)
|
|
||||||
*bytes = NULL;
|
|
||||||
return GST_FLOW_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p_buf)
|
|
||||||
*p_buf = gst_buffer_create_sub (parse->cached_buffer, 0, size);
|
|
||||||
if (bytes)
|
|
||||||
*bytes = GST_BUFFER_DATA (parse->cached_buffer);
|
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const guint8 *
|
static const guint8 *
|
||||||
gst_matroska_parse_peek_pull (GstMatroskaParse * parse, guint peek)
|
gst_matroska_parse_peek_pull (GstMatroskaParse * parse, guint peek)
|
||||||
{
|
{
|
||||||
guint8 *data = NULL;
|
guint8 *data = NULL;
|
||||||
|
|
||||||
gst_matroska_parse_peek_bytes (parse, parse->offset, peek, NULL, &data);
|
gst_matroska_read_common_peek_bytes (&parse->common, parse->common.offset,
|
||||||
|
peek, NULL, &data);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,7 +400,7 @@ gst_matroska_parse_peek_id_length_pull (GstMatroskaParse * parse, guint32 * _id,
|
||||||
{
|
{
|
||||||
return gst_ebml_peek_id_length (_id, _length, _needed,
|
return gst_ebml_peek_id_length (_id, _length, _needed,
|
||||||
(GstPeekData) gst_matroska_parse_peek_pull, (gpointer) parse,
|
(GstPeekData) gst_matroska_parse_peek_pull, (gpointer) parse,
|
||||||
GST_ELEMENT_CAST (parse), parse->offset);
|
GST_ELEMENT_CAST (parse), parse->common.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gint64
|
static gint64
|
||||||
|
@ -492,7 +409,7 @@ gst_matroska_parse_get_length (GstMatroskaParse * parse)
|
||||||
GstFormat fmt = GST_FORMAT_BYTES;
|
GstFormat fmt = GST_FORMAT_BYTES;
|
||||||
gint64 end = -1;
|
gint64 end = -1;
|
||||||
|
|
||||||
if (!gst_pad_query_peer_duration (parse->sinkpad, &fmt, &end) ||
|
if (!gst_pad_query_peer_duration (parse->common.sinkpad, &fmt, &end) ||
|
||||||
fmt != GST_FORMAT_BYTES || end < 0)
|
fmt != GST_FORMAT_BYTES || end < 0)
|
||||||
GST_DEBUG_OBJECT (parse, "no upstream length");
|
GST_DEBUG_OBJECT (parse, "no upstream length");
|
||||||
|
|
||||||
|
@ -1608,14 +1525,14 @@ gst_matroska_parse_search_cluster (GstMatroskaParse * parse, gint64 * pos)
|
||||||
guint32 id;
|
guint32 id;
|
||||||
guint needed;
|
guint needed;
|
||||||
|
|
||||||
orig_offset = parse->offset;
|
orig_offset = parse->common.offset;
|
||||||
|
|
||||||
/* read in at newpos and scan for ebml cluster id */
|
/* read in at newpos and scan for ebml cluster id */
|
||||||
while (1) {
|
while (1) {
|
||||||
GstByteReader reader;
|
GstByteReader reader;
|
||||||
gint cluster_pos;
|
gint cluster_pos;
|
||||||
|
|
||||||
ret = gst_pad_pull_range (parse->sinkpad, newpos, chunk, &buf);
|
ret = gst_pad_pull_range (parse->common.sinkpad, newpos, chunk, &buf);
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
break;
|
break;
|
||||||
GST_DEBUG_OBJECT (parse, "read buffer size %d at offset %" G_GINT64_FORMAT,
|
GST_DEBUG_OBJECT (parse, "read buffer size %d at offset %" G_GINT64_FORMAT,
|
||||||
|
@ -1640,7 +1557,7 @@ gst_matroska_parse_search_cluster (GstMatroskaParse * parse, gint64 * pos)
|
||||||
GST_DEBUG_OBJECT (parse, "cluster is first cluster -> OK");
|
GST_DEBUG_OBJECT (parse, "cluster is first cluster -> OK");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
parse->offset = newpos;
|
parse->common.offset = newpos;
|
||||||
ret =
|
ret =
|
||||||
gst_matroska_parse_peek_id_length_pull (parse, &id, &length, &needed);
|
gst_matroska_parse_peek_id_length_pull (parse, &id, &length, &needed);
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
|
@ -1654,7 +1571,7 @@ gst_matroska_parse_search_cluster (GstMatroskaParse * parse, gint64 * pos)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* skip cluster */
|
/* skip cluster */
|
||||||
parse->offset += length + needed;
|
parse->common.offset += length + needed;
|
||||||
ret =
|
ret =
|
||||||
gst_matroska_parse_peek_id_length_pull (parse, &id, &length, &needed);
|
gst_matroska_parse_peek_id_length_pull (parse, &id, &length, &needed);
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
|
@ -1678,7 +1595,7 @@ gst_matroska_parse_search_cluster (GstMatroskaParse * parse, gint64 * pos)
|
||||||
buf = NULL;
|
buf = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
parse->offset = orig_offset;
|
parse->common.offset = orig_offset;
|
||||||
*pos = newpos;
|
*pos = newpos;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1874,7 +1791,7 @@ gst_matroska_parse_handle_src_event (GstPad * pad, GstEvent * event)
|
||||||
|
|
||||||
case GST_EVENT_LATENCY:
|
case GST_EVENT_LATENCY:
|
||||||
default:
|
default:
|
||||||
res = gst_pad_push_event (parse->sinkpad, event);
|
res = gst_pad_push_event (parse->common.sinkpad, event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3455,7 +3372,7 @@ gst_matroska_parse_check_parse_error (GstMatroskaParse * parse)
|
||||||
|
|
||||||
/* sigh, one last attempt above and beyond call of duty ...;
|
/* sigh, one last attempt above and beyond call of duty ...;
|
||||||
* search for cluster mark following current pos */
|
* search for cluster mark following current pos */
|
||||||
pos = parse->offset;
|
pos = parse->common.offset;
|
||||||
GST_WARNING_OBJECT (parse, "parse error, looking for next cluster");
|
GST_WARNING_OBJECT (parse, "parse error, looking for next cluster");
|
||||||
if (gst_matroska_parse_search_cluster (parse, &pos) != GST_FLOW_OK) {
|
if (gst_matroska_parse_search_cluster (parse, &pos) != GST_FLOW_OK) {
|
||||||
/* did not work, give up */
|
/* did not work, give up */
|
||||||
|
@ -3463,7 +3380,7 @@ gst_matroska_parse_check_parse_error (GstMatroskaParse * parse)
|
||||||
} else {
|
} else {
|
||||||
GST_DEBUG_OBJECT (parse, "... found at %" G_GUINT64_FORMAT, pos);
|
GST_DEBUG_OBJECT (parse, "... found at %" G_GUINT64_FORMAT, pos);
|
||||||
/* try that position */
|
/* try that position */
|
||||||
parse->offset = pos;
|
parse->common.offset = pos;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3491,8 +3408,9 @@ gst_matroska_parse_take (GstMatroskaParse * parse, guint64 bytes,
|
||||||
else
|
else
|
||||||
ret = GST_FLOW_UNEXPECTED;
|
ret = GST_FLOW_UNEXPECTED;
|
||||||
if (G_LIKELY (buffer)) {
|
if (G_LIKELY (buffer)) {
|
||||||
gst_ebml_read_init (ebml, GST_ELEMENT_CAST (parse), buffer, parse->offset);
|
gst_ebml_read_init (ebml, GST_ELEMENT_CAST (parse), buffer,
|
||||||
parse->offset += bytes;
|
parse->common.offset);
|
||||||
|
parse->common.offset += bytes;
|
||||||
}
|
}
|
||||||
exit:
|
exit:
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -3506,7 +3424,7 @@ gst_matroska_parse_check_seekability (GstMatroskaParse * parse)
|
||||||
gint64 start = -1, stop = -1;
|
gint64 start = -1, stop = -1;
|
||||||
|
|
||||||
query = gst_query_new_seeking (GST_FORMAT_BYTES);
|
query = gst_query_new_seeking (GST_FORMAT_BYTES);
|
||||||
if (!gst_pad_peer_query (parse->sinkpad, query)) {
|
if (!gst_pad_peer_query (parse->common.sinkpad, query)) {
|
||||||
GST_DEBUG_OBJECT (parse, "seeking query failed");
|
GST_DEBUG_OBJECT (parse, "seeking query failed");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@ -3518,7 +3436,7 @@ gst_matroska_parse_check_seekability (GstMatroskaParse * parse)
|
||||||
GstFormat fmt = GST_FORMAT_BYTES;
|
GstFormat fmt = GST_FORMAT_BYTES;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (parse, "doing duration query to fix up unset stop");
|
GST_DEBUG_OBJECT (parse, "doing duration query to fix up unset stop");
|
||||||
gst_pad_query_peer_duration (parse->sinkpad, &fmt, &stop);
|
gst_pad_query_peer_duration (parse->common.sinkpad, &fmt, &stop);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if upstream doesn't know the size, it's likely that it's not seekable in
|
/* if upstream doesn't know the size, it's likely that it's not seekable in
|
||||||
|
@ -3550,7 +3468,7 @@ gst_matroska_parse_find_tracks (GstMatroskaParse * parse)
|
||||||
"Found Cluster element before Tracks, searching Tracks");
|
"Found Cluster element before Tracks, searching Tracks");
|
||||||
|
|
||||||
/* remember */
|
/* remember */
|
||||||
before_pos = parse->offset;
|
before_pos = parse->common.offset;
|
||||||
|
|
||||||
/* Search Tracks element */
|
/* Search Tracks element */
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
|
@ -3565,7 +3483,7 @@ gst_matroska_parse_find_tracks (GstMatroskaParse * parse)
|
||||||
ret = gst_matroska_parse_check_read_size (parse, length);
|
ret = gst_matroska_parse_check_read_size (parse, length);
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
parse->offset += needed;
|
parse->common.offset += needed;
|
||||||
parse->offset += length;
|
parse->offset += length;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
@ -3723,10 +3641,10 @@ gst_matroska_parse_parse_id (GstMatroskaParse * parse, guint32 id,
|
||||||
GST_READ_CHECK (gst_matroska_parse_take (parse, needed, &ebml));
|
GST_READ_CHECK (gst_matroska_parse_take (parse, needed, &ebml));
|
||||||
GST_DEBUG_OBJECT (parse,
|
GST_DEBUG_OBJECT (parse,
|
||||||
"Found Segment start at offset %" G_GUINT64_FORMAT,
|
"Found Segment start at offset %" G_GUINT64_FORMAT,
|
||||||
parse->offset);
|
parse->common.offset);
|
||||||
/* seeks are from the beginning of the segment,
|
/* seeks are from the beginning of the segment,
|
||||||
* after the segment ID/length */
|
* after the segment ID/length */
|
||||||
parse->common.ebml_segment_start = parse->offset;
|
parse->common.ebml_segment_start = parse->common.offset;
|
||||||
parse->common.state = GST_MATROSKA_READ_STATE_HEADER;
|
parse->common.state = GST_MATROSKA_READ_STATE_HEADER;
|
||||||
gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
|
gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
|
||||||
break;
|
break;
|
||||||
|
@ -3770,11 +3688,11 @@ gst_matroska_parse_parse_id (GstMatroskaParse * parse, guint32 id,
|
||||||
if (G_UNLIKELY (parse->common.state
|
if (G_UNLIKELY (parse->common.state
|
||||||
== GST_MATROSKA_READ_STATE_HEADER)) {
|
== GST_MATROSKA_READ_STATE_HEADER)) {
|
||||||
parse->common.state = GST_MATROSKA_READ_STATE_DATA;
|
parse->common.state = GST_MATROSKA_READ_STATE_DATA;
|
||||||
parse->first_cluster_offset = parse->offset;
|
parse->first_cluster_offset = parse->common.offset;
|
||||||
GST_DEBUG_OBJECT (parse, "signaling no more pads");
|
GST_DEBUG_OBJECT (parse, "signaling no more pads");
|
||||||
}
|
}
|
||||||
parse->cluster_time = GST_CLOCK_TIME_NONE;
|
parse->cluster_time = GST_CLOCK_TIME_NONE;
|
||||||
parse->cluster_offset = parse->offset;
|
parse->cluster_offset = parse->common.offset;
|
||||||
if (G_UNLIKELY (!parse->seek_first && parse->seek_block)) {
|
if (G_UNLIKELY (!parse->seek_first && parse->seek_block)) {
|
||||||
GST_DEBUG_OBJECT (parse, "seek target block %" G_GUINT64_FORMAT
|
GST_DEBUG_OBJECT (parse, "seek target block %" G_GUINT64_FORMAT
|
||||||
" not found in Cluster, trying next Cluster's first block instead",
|
" not found in Cluster, trying next Cluster's first block instead",
|
||||||
|
@ -4040,7 +3958,7 @@ pause:
|
||||||
|
|
||||||
GST_LOG_OBJECT (parse, "pausing task, reason %s", reason);
|
GST_LOG_OBJECT (parse, "pausing task, reason %s", reason);
|
||||||
parse->segment_running = FALSE;
|
parse->segment_running = FALSE;
|
||||||
gst_pad_pause_task (parse->sinkpad);
|
gst_pad_pause_task (parse->common.sinkpad);
|
||||||
|
|
||||||
if (ret == GST_FLOW_UNEXPECTED) {
|
if (ret == GST_FLOW_UNEXPECTED) {
|
||||||
/* perform EOS logic */
|
/* perform EOS logic */
|
||||||
|
@ -4109,7 +4027,7 @@ perform_seek_to_offset (GstMatroskaParse * parse, guint64 offset)
|
||||||
GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
|
GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
|
||||||
GST_SEEK_TYPE_NONE, -1);
|
GST_SEEK_TYPE_NONE, -1);
|
||||||
|
|
||||||
res = gst_pad_push_event (parse->sinkpad, event);
|
res = gst_pad_push_event (parse->common.sinkpad, event);
|
||||||
|
|
||||||
/* newsegment event will update offset */
|
/* newsegment event will update offset */
|
||||||
return res;
|
return res;
|
||||||
|
@ -4127,7 +4045,7 @@ gst_matroska_parse_peek_id_length_push (GstMatroskaParse * parse, guint32 * _id,
|
||||||
{
|
{
|
||||||
return gst_ebml_peek_id_length (_id, _length, _needed,
|
return gst_ebml_peek_id_length (_id, _length, _needed,
|
||||||
(GstPeekData) gst_matroska_parse_peek_adapter, (gpointer) parse,
|
(GstPeekData) gst_matroska_parse_peek_adapter, (gpointer) parse,
|
||||||
GST_ELEMENT_CAST (parse), parse->offset);
|
GST_ELEMENT_CAST (parse), parse->common.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
|
@ -4159,8 +4077,8 @@ next:
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
GST_LOG_OBJECT (parse, "Offset %" G_GUINT64_FORMAT ", Element id 0x%x, "
|
GST_LOG_OBJECT (parse, "Offset %" G_GUINT64_FORMAT ", Element id 0x%x, "
|
||||||
"size %" G_GUINT64_FORMAT ", needed %d, available %d", parse->offset, id,
|
"size %" G_GUINT64_FORMAT ", needed %d, available %d",
|
||||||
length, needed, available);
|
parse->common.offset, id, length, needed, available);
|
||||||
|
|
||||||
if (needed > available)
|
if (needed > available)
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
|
@ -4218,7 +4136,7 @@ gst_matroska_parse_handle_sink_event (GstPad * pad, GstEvent * event)
|
||||||
/* clear current segment leftover */
|
/* clear current segment leftover */
|
||||||
gst_adapter_clear (parse->adapter);
|
gst_adapter_clear (parse->adapter);
|
||||||
/* and some streaming setup */
|
/* and some streaming setup */
|
||||||
parse->offset = start;
|
parse->common.offset = start;
|
||||||
/* do not know where we are;
|
/* do not know where we are;
|
||||||
* need to come across a cluster and generate newsegment */
|
* need to come across a cluster and generate newsegment */
|
||||||
parse->segment.last_stop = GST_CLOCK_TIME_NONE;
|
parse->segment.last_stop = GST_CLOCK_TIME_NONE;
|
||||||
|
|
|
@ -51,7 +51,6 @@ typedef struct _GstMatroskaParse {
|
||||||
GstMatroskaReadCommon common;
|
GstMatroskaReadCommon common;
|
||||||
|
|
||||||
/* pads */
|
/* pads */
|
||||||
GstPad *sinkpad;
|
|
||||||
GstPad *srcpad;
|
GstPad *srcpad;
|
||||||
GstClock *clock;
|
GstClock *clock;
|
||||||
guint num_v_streams;
|
guint num_v_streams;
|
||||||
|
@ -89,11 +88,6 @@ typedef struct _GstMatroskaParse {
|
||||||
GstEvent *new_segment;
|
GstEvent *new_segment;
|
||||||
GstTagList *global_tags;
|
GstTagList *global_tags;
|
||||||
|
|
||||||
/* pull mode caching */
|
|
||||||
GstBuffer *cached_buffer;
|
|
||||||
|
|
||||||
/* push and pull mode */
|
|
||||||
guint64 offset;
|
|
||||||
/* some state saving */
|
/* some state saving */
|
||||||
GstClockTime cluster_time;
|
GstClockTime cluster_time;
|
||||||
guint64 cluster_offset;
|
guint64 cluster_offset;
|
||||||
|
|
|
@ -624,6 +624,91 @@ gst_matroska_read_common_parse_index (GstMatroskaReadCommon * common,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calls pull_range for (offset,size) without advancing our offset
|
||||||
|
*/
|
||||||
|
GstFlowReturn
|
||||||
|
gst_matroska_read_common_peek_bytes (GstMatroskaReadCommon * common, guint64
|
||||||
|
offset, guint size, GstBuffer ** p_buf, guint8 ** bytes)
|
||||||
|
{
|
||||||
|
GstFlowReturn ret;
|
||||||
|
|
||||||
|
/* Caching here actually makes much less difference than one would expect.
|
||||||
|
* We do it mainly to avoid pulling buffers of 1 byte all the time */
|
||||||
|
if (common->cached_buffer) {
|
||||||
|
guint64 cache_offset = GST_BUFFER_OFFSET (common->cached_buffer);
|
||||||
|
guint cache_size = GST_BUFFER_SIZE (common->cached_buffer);
|
||||||
|
|
||||||
|
if (cache_offset <= common->offset &&
|
||||||
|
(common->offset + size) <= (cache_offset + cache_size)) {
|
||||||
|
if (p_buf)
|
||||||
|
*p_buf = gst_buffer_create_sub (common->cached_buffer,
|
||||||
|
common->offset - cache_offset, size);
|
||||||
|
if (bytes)
|
||||||
|
*bytes = GST_BUFFER_DATA (common->cached_buffer) + common->offset -
|
||||||
|
cache_offset;
|
||||||
|
return GST_FLOW_OK;
|
||||||
|
}
|
||||||
|
/* not enough data in the cache, free cache and get a new one */
|
||||||
|
gst_buffer_unref (common->cached_buffer);
|
||||||
|
common->cached_buffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* refill the cache */
|
||||||
|
ret = gst_pad_pull_range (common->sinkpad, common->offset,
|
||||||
|
MAX (size, 64 * 1024), &common->cached_buffer);
|
||||||
|
if (ret != GST_FLOW_OK) {
|
||||||
|
common->cached_buffer = NULL;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GST_BUFFER_SIZE (common->cached_buffer) >= size) {
|
||||||
|
if (p_buf)
|
||||||
|
*p_buf = gst_buffer_create_sub (common->cached_buffer, 0, size);
|
||||||
|
if (bytes)
|
||||||
|
*bytes = GST_BUFFER_DATA (common->cached_buffer);
|
||||||
|
return GST_FLOW_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not possible to get enough data, try a last time with
|
||||||
|
* requesting exactly the size we need */
|
||||||
|
gst_buffer_unref (common->cached_buffer);
|
||||||
|
common->cached_buffer = NULL;
|
||||||
|
|
||||||
|
ret =
|
||||||
|
gst_pad_pull_range (common->sinkpad, common->offset, size,
|
||||||
|
&common->cached_buffer);
|
||||||
|
if (ret != GST_FLOW_OK) {
|
||||||
|
GST_DEBUG_OBJECT (common, "pull_range returned %d", ret);
|
||||||
|
if (p_buf)
|
||||||
|
*p_buf = NULL;
|
||||||
|
if (bytes)
|
||||||
|
*bytes = NULL;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GST_BUFFER_SIZE (common->cached_buffer) < size) {
|
||||||
|
GST_WARNING_OBJECT (common, "Dropping short buffer at offset %"
|
||||||
|
G_GUINT64_FORMAT ": wanted %u bytes, got %u bytes", common->offset,
|
||||||
|
size, GST_BUFFER_SIZE (common->cached_buffer));
|
||||||
|
|
||||||
|
gst_buffer_unref (common->cached_buffer);
|
||||||
|
common->cached_buffer = NULL;
|
||||||
|
if (p_buf)
|
||||||
|
*p_buf = NULL;
|
||||||
|
if (bytes)
|
||||||
|
*bytes = NULL;
|
||||||
|
return GST_FLOW_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_buf)
|
||||||
|
*p_buf = gst_buffer_create_sub (common->cached_buffer, 0, size);
|
||||||
|
if (bytes)
|
||||||
|
*bytes = GST_BUFFER_DATA (common->cached_buffer);
|
||||||
|
|
||||||
|
return GST_FLOW_OK;
|
||||||
|
}
|
||||||
|
|
||||||
GstFlowReturn
|
GstFlowReturn
|
||||||
gst_matroska_read_common_read_track_encoding (GstMatroskaReadCommon * common,
|
gst_matroska_read_common_read_track_encoding (GstMatroskaReadCommon * common,
|
||||||
GstEbmlRead * ebml, GstMatroskaTrackContext * context)
|
GstEbmlRead * ebml, GstMatroskaTrackContext * context)
|
||||||
|
|
|
@ -44,6 +44,7 @@ typedef struct _GstMatroskaReadCommon {
|
||||||
gint element_index_writer_id;
|
gint element_index_writer_id;
|
||||||
|
|
||||||
/* pads */
|
/* pads */
|
||||||
|
GstPad *sinkpad;
|
||||||
GPtrArray *src;
|
GPtrArray *src;
|
||||||
guint num_streams;
|
guint num_streams;
|
||||||
|
|
||||||
|
@ -61,6 +62,12 @@ typedef struct _GstMatroskaReadCommon {
|
||||||
|
|
||||||
/* timescale in the file */
|
/* timescale in the file */
|
||||||
guint64 time_scale;
|
guint64 time_scale;
|
||||||
|
|
||||||
|
/* pull mode caching */
|
||||||
|
GstBuffer *cached_buffer;
|
||||||
|
|
||||||
|
/* push and pull mode */
|
||||||
|
guint64 offset;
|
||||||
} GstMatroskaReadCommon;
|
} GstMatroskaReadCommon;
|
||||||
|
|
||||||
GstFlowReturn gst_matroska_decode_content_encodings (GArray * encodings);
|
GstFlowReturn gst_matroska_decode_content_encodings (GArray * encodings);
|
||||||
|
@ -71,6 +78,8 @@ GstFlowReturn gst_matroska_read_common_parse_index (GstMatroskaReadCommon *
|
||||||
common, GstEbmlRead * ebml);
|
common, GstEbmlRead * ebml);
|
||||||
GstFlowReturn gst_matroska_read_common_parse_skip (GstMatroskaReadCommon *
|
GstFlowReturn gst_matroska_read_common_parse_skip (GstMatroskaReadCommon *
|
||||||
common, GstEbmlRead * ebml, const gchar * parent_name, guint id);
|
common, GstEbmlRead * ebml, const gchar * parent_name, guint id);
|
||||||
|
GstFlowReturn gst_matroska_read_common_peek_bytes (GstMatroskaReadCommon *
|
||||||
|
common, guint64 offset, guint size, GstBuffer ** p_buf, guint8 ** bytes);
|
||||||
gint gst_matroska_read_common_stream_from_num (GstMatroskaReadCommon * common,
|
gint gst_matroska_read_common_stream_from_num (GstMatroskaReadCommon * common,
|
||||||
guint track_num);
|
guint track_num);
|
||||||
GstFlowReturn gst_matroska_read_common_read_track_encoding (
|
GstFlowReturn gst_matroska_read_common_read_track_encoding (
|
||||||
|
|
Loading…
Reference in a new issue