From 72d969b3605aff4bfde3f97716a718eb40cdb484 Mon Sep 17 00:00:00 2001 From: Debarshi Ray Date: Mon, 23 May 2011 18:06:44 +0300 Subject: [PATCH] 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 --- gst/matroska/matroska-demux.c | 219 ++++++++++++------------------------ gst/matroska/matroska-demux.h | 6 - gst/matroska/matroska-parse.c | 158 +++++++------------------- gst/matroska/matroska-parse.h | 6 - gst/matroska/matroska-read-common.c | 85 ++++++++++++++ gst/matroska/matroska-read-common.h | 9 ++ 6 files changed, 201 insertions(+), 282 deletions(-) diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c index 8c09145..522af9a 100644 --- a/gst/matroska/matroska-demux.c +++ b/gst/matroska/matroska-demux.c @@ -242,16 +242,17 @@ static void gst_matroska_demux_init (GstMatroskaDemux * demux, GstMatroskaDemuxClass * klass) { - demux->sinkpad = gst_pad_new_from_static_template (&sink_templ, "sink"); - gst_pad_set_activate_function (demux->sinkpad, + demux->common.sinkpad = gst_pad_new_from_static_template (&sink_templ, + "sink"); + gst_pad_set_activate_function (demux->common.sinkpad, 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_pad_set_chain_function (demux->sinkpad, + gst_pad_set_chain_function (demux->common.sinkpad, 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_element_add_pad (GST_ELEMENT (demux), demux->sinkpad); + gst_element_add_pad (GST_ELEMENT (demux), demux->common.sinkpad); /* initial stream no. */ demux->common.src = NULL; @@ -417,7 +418,7 @@ gst_matroska_demux_reset (GstElement * element) demux->last_stop_end = GST_CLOCK_TIME_NONE; demux->seek_block = 0; - demux->offset = 0; + demux->common.offset = 0; demux->cluster_time = GST_CLOCK_TIME_NONE; demux->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 (); - if (demux->cached_buffer) { - gst_buffer_unref (demux->cached_buffer); - demux->cached_buffer = NULL; + if (demux->common.cached_buffer) { + gst_buffer_unref (demux->common.cached_buffer); + 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 * gst_matroska_demux_peek_pull (GstMatroskaDemux * demux, guint peek) { 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; } @@ -560,7 +477,7 @@ gst_matroska_demux_peek_id_length_pull (GstMatroskaDemux * demux, guint32 * _id, { return gst_ebml_peek_id_length (_id, _length, _needed, (GstPeekData) gst_matroska_demux_peek_pull, (gpointer) demux, - GST_ELEMENT_CAST (demux), demux->offset); + GST_ELEMENT_CAST (demux), demux->common.offset); } static gint64 @@ -569,7 +486,7 @@ gst_matroska_demux_get_length (GstMatroskaDemux * demux) GstFormat fmt = GST_FORMAT_BYTES; 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) GST_DEBUG_OBJECT (demux, "no upstream length"); @@ -1885,7 +1802,7 @@ gst_matroska_demux_move_to_entry (GstMatroskaDemux * demux, /* seek (relative to matroska segment) */ /* 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, " "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; guint needed; - orig_offset = demux->offset; + orig_offset = demux->common.offset; GST_LOG_OBJECT (demux, "searching cluster following offset %" G_GINT64_FORMAT, *pos); @@ -1956,7 +1873,7 @@ gst_matroska_demux_search_cluster (GstMatroskaDemux * demux, gint64 * pos) if (cpos) { GST_DEBUG_OBJECT (demux, "cluster reported at offset %" G_GINT64_FORMAT, *cpos); - demux->offset = *cpos; + demux->common.offset = *cpos; ret = gst_matroska_demux_peek_id_length_pull (demux, &id, &length, &needed); 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; 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) break; 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"); break; } - demux->offset = newpos; + demux->common.offset = newpos; ret = gst_matroska_demux_peek_id_length_pull (demux, &id, &length, &needed); if (ret != GST_FLOW_OK) @@ -2010,7 +1927,7 @@ gst_matroska_demux_search_cluster (GstMatroskaDemux * demux, gint64 * pos) break; } /* skip cluster */ - demux->offset += length + needed; + demux->common.offset += length + needed; ret = gst_matroska_demux_peek_id_length_pull (demux, &id, &length, &needed); if (ret != GST_FLOW_OK) @@ -2035,7 +1952,7 @@ gst_matroska_demux_search_cluster (GstMatroskaDemux * demux, gint64 * pos) } exit: - demux->offset = orig_offset; + demux->common.offset = orig_offset; *pos = newpos; return ret; } @@ -2069,13 +1986,13 @@ gst_matroska_demux_search_pos (GstMatroskaDemux * demux, GstClockTime time) current_cluster_offset = demux->cluster_offset; current_cluster_time = demux->cluster_time; - current_offset = demux->offset; + current_offset = demux->common.offset; demux->common.state = GST_MATROSKA_READ_STATE_SCANNING; /* estimate using start and current position */ 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; GST_OBJECT_UNLOCK (demux); @@ -2121,7 +2038,7 @@ retry: /* then start scanning and parsing for cluster time, * 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; while (1) { guint64 cluster_size = 0; @@ -2131,7 +2048,7 @@ retry: if (ret != GST_FLOW_OK) goto error; 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); ret = gst_matroska_demux_parse_id (demux, id, length, needed); if (ret != GST_FLOW_OK) @@ -2178,7 +2095,7 @@ retry: * otherwise will be skippingly parsed into */ if (cluster_size) { 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; } else { GST_DEBUG_OBJECT (demux, "parsing/skipping cluster elements"); @@ -2208,7 +2125,7 @@ exit: /* restore some state */ demux->cluster_offset = current_cluster_offset; demux->cluster_time = current_cluster_time; - demux->offset = current_offset; + demux->common.offset = current_offset; demux->common.state = current_state; return entry; @@ -2283,24 +2200,24 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux, if (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 ()); } else { 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 * non flushing seeks when the element is in PAUSED this could block * forever. */ 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 */ if (!demux->streaming && !demux->common.index) { /* need to stop flushing upstream as we need it next */ 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); /* keep local copy */ if (entry) { @@ -2325,7 +2242,7 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux, if (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 ()); } else if (demux->segment_running) { 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 * flush. */ demux->segment_running = TRUE; - gst_pad_start_task (demux->sinkpad, (GstTaskFunction) gst_matroska_demux_loop, - demux->sinkpad); + gst_pad_start_task (demux->common.sinkpad, + (GstTaskFunction) gst_matroska_demux_loop, demux->common.sinkpad); /* streaming can continue now */ - GST_PAD_STREAM_UNLOCK (demux->sinkpad); + GST_PAD_STREAM_UNLOCK (demux->common.sinkpad); return TRUE; 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")); return FALSE; } @@ -2519,7 +2436,7 @@ gst_matroska_demux_handle_src_event (GstPad * pad, GstEvent * event) case GST_EVENT_LATENCY: default: - res = gst_pad_push_event (demux->sinkpad, event); + res = gst_pad_push_event (demux->common.sinkpad, event); break; } @@ -4673,7 +4590,7 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux, /* remember */ length = gst_matroska_demux_get_length (demux); - before_pos = demux->offset; + before_pos = demux->common.offset; if (length == (guint64) - 1) { GST_DEBUG_OBJECT (demux, "no upstream length, skipping SeakHead entry"); @@ -4701,7 +4618,7 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux, } /* seek */ - demux->offset = seek_pos + demux->common.ebml_segment_start; + demux->common.offset = seek_pos + demux->common.ebml_segment_start; /* check ID */ 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: /* seek back */ - demux->offset = before_pos; + demux->common.offset = before_pos; 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 */ GST_WARNING_OBJECT (demux, "parse error, trying next cluster expected at %" 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; return FALSE; } else { @@ -4831,7 +4748,7 @@ gst_matroska_demux_check_parse_error (GstMatroskaDemux * demux) /* sigh, one last attempt above and beyond call of duty ...; * search for cluster mark following current pos */ - pos = demux->offset; + pos = demux->common.offset; GST_WARNING_OBJECT (demux, "parse error, looking for next cluster"); if (gst_matroska_demux_search_cluster (demux, &pos) != GST_FLOW_OK) { /* did not work, give up */ @@ -4839,7 +4756,7 @@ gst_matroska_demux_check_parse_error (GstMatroskaDemux * demux) } else { GST_DEBUG_OBJECT (demux, "... found at %" G_GUINT64_FORMAT, pos); /* try that position */ - demux->offset = pos; + demux->common.offset = pos; return FALSE; } } @@ -4849,7 +4766,7 @@ static inline GstFlowReturn gst_matroska_demux_flush (GstMatroskaDemux * demux, guint flush) { GST_LOG_OBJECT (demux, "skipping %d bytes", flush); - demux->offset += flush; + demux->common.offset += flush; if (demux->streaming) { GstFlowReturn ret; @@ -4895,11 +4812,12 @@ gst_matroska_demux_take (GstMatroskaDemux * demux, guint64 bytes, else ret = GST_FLOW_UNEXPECTED; } else - ret = gst_matroska_demux_peek_bytes (demux, demux->offset, bytes, &buffer, - NULL); + ret = gst_matroska_read_common_peek_bytes (&demux->common, + demux->common.offset, bytes, &buffer, NULL); if (G_LIKELY (buffer)) { - gst_ebml_read_init (ebml, GST_ELEMENT_CAST (demux), buffer, demux->offset); - demux->offset += bytes; + gst_ebml_read_init (ebml, GST_ELEMENT_CAST (demux), buffer, + demux->common.offset); + demux->common.offset += bytes; } exit: return ret; @@ -4913,7 +4831,7 @@ gst_matroska_demux_check_seekability (GstMatroskaDemux * demux) gint64 start = -1, stop = -1; 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"); goto done; } @@ -4925,7 +4843,7 @@ gst_matroska_demux_check_seekability (GstMatroskaDemux * demux) GstFormat fmt = GST_FORMAT_BYTES; 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 @@ -4956,7 +4874,7 @@ gst_matroska_demux_find_tracks (GstMatroskaDemux * demux) "Found Cluster element before Tracks, searching Tracks"); /* remember */ - before_pos = demux->offset; + before_pos = demux->common.offset; /* Search Tracks element */ while (TRUE) { @@ -4971,8 +4889,8 @@ gst_matroska_demux_find_tracks (GstMatroskaDemux * demux) ret = gst_matroska_demux_check_read_size (demux, length); break; } else { - demux->offset += needed; - demux->offset += length; + demux->common.offset += needed; + demux->common.offset += length; } continue; } @@ -4983,7 +4901,7 @@ gst_matroska_demux_find_tracks (GstMatroskaDemux * demux) } /* seek back */ - demux->offset = before_pos; + demux->common.offset = before_pos; 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_DEBUG_OBJECT (demux, "Found Segment start at offset %" G_GUINT64_FORMAT, - demux->offset); + demux->common.offset); /* seeks are from the beginning of the segment, * 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; break; default: @@ -5092,7 +5010,7 @@ gst_matroska_demux_parse_id (GstMatroskaDemux * demux, guint32 id, if (G_UNLIKELY (demux->common.state == GST_MATROSKA_READ_STATE_HEADER)) { 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_element_no_more_pads (GST_ELEMENT (demux)); /* send initial newsegment */ @@ -5103,7 +5021,7 @@ gst_matroska_demux_parse_id (GstMatroskaDemux * demux, guint32 id, 0) ? demux->segment.duration : -1, 0)); } 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)) { GST_DEBUG_OBJECT (demux, "seek target block %" G_GUINT64_FORMAT " 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, " - "size %" G_GUINT64_FORMAT ", needed %d", demux->offset, id, + "size %" G_GUINT64_FORMAT ", needed %d", demux->common.offset, id, length, needed); ret = gst_matroska_demux_parse_id (demux, id, length, needed); @@ -5335,7 +5253,8 @@ gst_matroska_demux_loop (GstPad * pad) } 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"); ret = GST_FLOW_UNEXPECTED; goto eos; @@ -5360,7 +5279,7 @@ pause: GST_LOG_OBJECT (demux, "pausing task, reason %s", reason); demux->segment_running = FALSE; - gst_pad_pause_task (demux->sinkpad); + gst_pad_pause_task (demux->common.sinkpad); if (ret == GST_FLOW_UNEXPECTED) { /* 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_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 */ 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, (GstPeekData) gst_matroska_demux_peek_adapter, (gpointer) demux, - GST_ELEMENT_CAST (demux), demux->offset); + GST_ELEMENT_CAST (demux), demux->common.offset); } static GstFlowReturn @@ -5478,8 +5397,8 @@ next: return ret; GST_LOG_OBJECT (demux, "Offset %" G_GUINT64_FORMAT ", Element id 0x%x, " - "size %" G_GUINT64_FORMAT ", needed %d, available %d", demux->offset, id, - length, needed, available); + "size %" G_GUINT64_FORMAT ", needed %d, available %d", + demux->common.offset, id, length, needed, available); if (needed > available) return GST_FLOW_OK; @@ -5538,7 +5457,7 @@ gst_matroska_demux_handle_sink_event (GstPad * pad, GstEvent * event) /* clear current segment leftover */ gst_adapter_clear (demux->adapter); /* and some streaming setup */ - demux->offset = start; + demux->common.offset = start; /* do not know where we are; * need to come across a cluster and generate newsegment */ demux->segment.last_stop = GST_CLOCK_TIME_NONE; diff --git a/gst/matroska/matroska-demux.h b/gst/matroska/matroska-demux.h index d0df0ac..1b63a70 100644 --- a/gst/matroska/matroska-demux.h +++ b/gst/matroska/matroska-demux.h @@ -51,7 +51,6 @@ typedef struct _GstMatroskaDemux { GstMatroskaReadCommon common; /* pads */ - GstPad *sinkpad; GstClock *clock; guint num_v_streams; guint num_a_streams; @@ -87,11 +86,6 @@ typedef struct _GstMatroskaDemux { GstEvent *new_segment; GstTagList *global_tags; - /* pull mode caching */ - GstBuffer *cached_buffer; - - /* push and pull mode */ - guint64 offset; /* some state saving */ GstClockTime cluster_time; guint64 cluster_offset; diff --git a/gst/matroska/matroska-parse.c b/gst/matroska/matroska-parse.c index aba4b75..6f30055 100644 --- a/gst/matroska/matroska-parse.c +++ b/gst/matroska/matroska-parse.c @@ -204,12 +204,13 @@ static void gst_matroska_parse_init (GstMatroskaParse * parse, GstMatroskaParseClass * klass) { - parse->sinkpad = gst_pad_new_from_static_template (&sink_templ, "sink"); - gst_pad_set_chain_function (parse->sinkpad, + parse->common.sinkpad = gst_pad_new_from_static_template (&sink_templ, + "sink"); + gst_pad_set_chain_function (parse->common.sinkpad, 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_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"); 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->seek_block = 0; - parse->offset = 0; + parse->common.offset = 0; parse->cluster_time = GST_CLOCK_TIME_NONE; parse->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 (); - if (parse->cached_buffer) { - gst_buffer_unref (parse->cached_buffer); - parse->cached_buffer = NULL; + if (parse->common.cached_buffer) { + gst_buffer_unref (parse->common.cached_buffer); + 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 * gst_matroska_parse_peek_pull (GstMatroskaParse * parse, guint peek) { 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; } @@ -483,7 +400,7 @@ gst_matroska_parse_peek_id_length_pull (GstMatroskaParse * parse, guint32 * _id, { return gst_ebml_peek_id_length (_id, _length, _needed, (GstPeekData) gst_matroska_parse_peek_pull, (gpointer) parse, - GST_ELEMENT_CAST (parse), parse->offset); + GST_ELEMENT_CAST (parse), parse->common.offset); } static gint64 @@ -492,7 +409,7 @@ gst_matroska_parse_get_length (GstMatroskaParse * parse) GstFormat fmt = GST_FORMAT_BYTES; 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) GST_DEBUG_OBJECT (parse, "no upstream length"); @@ -1608,14 +1525,14 @@ gst_matroska_parse_search_cluster (GstMatroskaParse * parse, gint64 * pos) guint32 id; guint needed; - orig_offset = parse->offset; + orig_offset = parse->common.offset; /* read in at newpos and scan for ebml cluster id */ while (1) { GstByteReader reader; 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) break; 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"); break; } - parse->offset = newpos; + parse->common.offset = newpos; ret = gst_matroska_parse_peek_id_length_pull (parse, &id, &length, &needed); if (ret != GST_FLOW_OK) @@ -1654,7 +1571,7 @@ gst_matroska_parse_search_cluster (GstMatroskaParse * parse, gint64 * pos) break; } /* skip cluster */ - parse->offset += length + needed; + parse->common.offset += length + needed; ret = gst_matroska_parse_peek_id_length_pull (parse, &id, &length, &needed); if (ret != GST_FLOW_OK) @@ -1678,7 +1595,7 @@ gst_matroska_parse_search_cluster (GstMatroskaParse * parse, gint64 * pos) buf = NULL; } - parse->offset = orig_offset; + parse->common.offset = orig_offset; *pos = newpos; return ret; } @@ -1874,7 +1791,7 @@ gst_matroska_parse_handle_src_event (GstPad * pad, GstEvent * event) case GST_EVENT_LATENCY: default: - res = gst_pad_push_event (parse->sinkpad, event); + res = gst_pad_push_event (parse->common.sinkpad, event); break; } @@ -3455,7 +3372,7 @@ gst_matroska_parse_check_parse_error (GstMatroskaParse * parse) /* sigh, one last attempt above and beyond call of duty ...; * search for cluster mark following current pos */ - pos = parse->offset; + pos = parse->common.offset; GST_WARNING_OBJECT (parse, "parse error, looking for next cluster"); if (gst_matroska_parse_search_cluster (parse, &pos) != GST_FLOW_OK) { /* did not work, give up */ @@ -3463,7 +3380,7 @@ gst_matroska_parse_check_parse_error (GstMatroskaParse * parse) } else { GST_DEBUG_OBJECT (parse, "... found at %" G_GUINT64_FORMAT, pos); /* try that position */ - parse->offset = pos; + parse->common.offset = pos; return FALSE; } } @@ -3491,8 +3408,9 @@ gst_matroska_parse_take (GstMatroskaParse * parse, guint64 bytes, else ret = GST_FLOW_UNEXPECTED; if (G_LIKELY (buffer)) { - gst_ebml_read_init (ebml, GST_ELEMENT_CAST (parse), buffer, parse->offset); - parse->offset += bytes; + gst_ebml_read_init (ebml, GST_ELEMENT_CAST (parse), buffer, + parse->common.offset); + parse->common.offset += bytes; } exit: return ret; @@ -3506,7 +3424,7 @@ gst_matroska_parse_check_seekability (GstMatroskaParse * parse) gint64 start = -1, stop = -1; 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"); goto done; } @@ -3518,7 +3436,7 @@ gst_matroska_parse_check_seekability (GstMatroskaParse * parse) GstFormat fmt = GST_FORMAT_BYTES; 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 @@ -3550,7 +3468,7 @@ gst_matroska_parse_find_tracks (GstMatroskaParse * parse) "Found Cluster element before Tracks, searching Tracks"); /* remember */ - before_pos = parse->offset; + before_pos = parse->common.offset; /* Search Tracks element */ while (TRUE) { @@ -3565,7 +3483,7 @@ gst_matroska_parse_find_tracks (GstMatroskaParse * parse) ret = gst_matroska_parse_check_read_size (parse, length); break; } else { - parse->offset += needed; + parse->common.offset += needed; parse->offset += length; } 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_DEBUG_OBJECT (parse, "Found Segment start at offset %" G_GUINT64_FORMAT, - parse->offset); + parse->common.offset); /* seeks are from the beginning of the segment, * 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; gst_matroska_parse_accumulate_streamheader (parse, ebml.buf); break; @@ -3770,11 +3688,11 @@ gst_matroska_parse_parse_id (GstMatroskaParse * parse, guint32 id, if (G_UNLIKELY (parse->common.state == GST_MATROSKA_READ_STATE_HEADER)) { 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"); } 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)) { GST_DEBUG_OBJECT (parse, "seek target block %" G_GUINT64_FORMAT " 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); parse->segment_running = FALSE; - gst_pad_pause_task (parse->sinkpad); + gst_pad_pause_task (parse->common.sinkpad); if (ret == GST_FLOW_UNEXPECTED) { /* 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_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 */ 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, (GstPeekData) gst_matroska_parse_peek_adapter, (gpointer) parse, - GST_ELEMENT_CAST (parse), parse->offset); + GST_ELEMENT_CAST (parse), parse->common.offset); } static GstFlowReturn @@ -4159,8 +4077,8 @@ next: return ret; GST_LOG_OBJECT (parse, "Offset %" G_GUINT64_FORMAT ", Element id 0x%x, " - "size %" G_GUINT64_FORMAT ", needed %d, available %d", parse->offset, id, - length, needed, available); + "size %" G_GUINT64_FORMAT ", needed %d, available %d", + parse->common.offset, id, length, needed, available); if (needed > available) return GST_FLOW_OK; @@ -4218,7 +4136,7 @@ gst_matroska_parse_handle_sink_event (GstPad * pad, GstEvent * event) /* clear current segment leftover */ gst_adapter_clear (parse->adapter); /* and some streaming setup */ - parse->offset = start; + parse->common.offset = start; /* do not know where we are; * need to come across a cluster and generate newsegment */ parse->segment.last_stop = GST_CLOCK_TIME_NONE; diff --git a/gst/matroska/matroska-parse.h b/gst/matroska/matroska-parse.h index 98b399d..3add6956 100644 --- a/gst/matroska/matroska-parse.h +++ b/gst/matroska/matroska-parse.h @@ -51,7 +51,6 @@ typedef struct _GstMatroskaParse { GstMatroskaReadCommon common; /* pads */ - GstPad *sinkpad; GstPad *srcpad; GstClock *clock; guint num_v_streams; @@ -89,11 +88,6 @@ typedef struct _GstMatroskaParse { GstEvent *new_segment; GstTagList *global_tags; - /* pull mode caching */ - GstBuffer *cached_buffer; - - /* push and pull mode */ - guint64 offset; /* some state saving */ GstClockTime cluster_time; guint64 cluster_offset; diff --git a/gst/matroska/matroska-read-common.c b/gst/matroska/matroska-read-common.c index ad79e66..efd0ce0 100644 --- a/gst/matroska/matroska-read-common.c +++ b/gst/matroska/matroska-read-common.c @@ -624,6 +624,91 @@ gst_matroska_read_common_parse_index (GstMatroskaReadCommon * common, 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 gst_matroska_read_common_read_track_encoding (GstMatroskaReadCommon * common, GstEbmlRead * ebml, GstMatroskaTrackContext * context) diff --git a/gst/matroska/matroska-read-common.h b/gst/matroska/matroska-read-common.h index db69e4c..c2cf024 100644 --- a/gst/matroska/matroska-read-common.h +++ b/gst/matroska/matroska-read-common.h @@ -44,6 +44,7 @@ typedef struct _GstMatroskaReadCommon { gint element_index_writer_id; /* pads */ + GstPad *sinkpad; GPtrArray *src; guint num_streams; @@ -61,6 +62,12 @@ typedef struct _GstMatroskaReadCommon { /* timescale in the file */ guint64 time_scale; + + /* pull mode caching */ + GstBuffer *cached_buffer; + + /* push and pull mode */ + guint64 offset; } GstMatroskaReadCommon; GstFlowReturn gst_matroska_decode_content_encodings (GArray * encodings); @@ -71,6 +78,8 @@ GstFlowReturn gst_matroska_read_common_parse_index (GstMatroskaReadCommon * common, GstEbmlRead * ebml); GstFlowReturn gst_matroska_read_common_parse_skip (GstMatroskaReadCommon * 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, guint track_num); GstFlowReturn gst_matroska_read_common_read_track_encoding ( -- 2.7.4