static gboolean gst_flv_mux_are_all_pads_eos (GstFlvMux * mux);
static GstFlowReturn gst_flv_mux_update_src_caps (GstAggregator * aggregator,
GstCaps * caps, GstCaps ** ret);
+static guint64 gst_flv_mux_query_upstream_duration (GstFlvMux * mux);
static GstFlowReturn
gst_flv_mux_pad_flush (GstAggregatorPad * pad, GstAggregator * aggregator)
}
if (!mux->streamable && mux->duration == GST_CLOCK_TIME_NONE) {
- GList *l;
- guint64 dur;
-
- for (l = GST_ELEMENT_CAST (mux)->sinkpads; l; l = l->next) {
- GstFlvMuxPad *pad = GST_FLV_MUX_PAD (l->data);
-
- if (gst_pad_peer_query_duration (GST_PAD (pad), GST_FORMAT_TIME,
- (gint64 *) & dur) && dur != GST_CLOCK_TIME_NONE) {
- if (mux->duration == GST_CLOCK_TIME_NONE)
- mux->duration = dur;
- else
- mux->duration = MAX (dur, mux->duration);
- }
- }
+ mux->duration = gst_flv_mux_query_upstream_duration (mux);
}
if (!mux->streamable && mux->duration != GST_CLOCK_TIME_NONE) {
video_codec_data = NULL;
audio_codec_data = NULL;
+ GST_OBJECT_LOCK (mux);
for (l = GST_ELEMENT_CAST (mux)->sinkpads; l != NULL; l = l->next) {
GstFlvMuxPad *pad = l->data;
gst_flv_mux_codec_data_buffer_to_tag (mux, pad->codec_data, pad);
}
}
+ GST_OBJECT_UNLOCK (mux);
/* mark buffers that will go in the streamheader */
GST_BUFFER_FLAG_SET (header, GST_BUFFER_FLAG_HEADER);
GST_DEBUG_OBJECT (mux, "trying to determine the duration "
"from pad timestamps");
+ GST_OBJECT_LOCK (mux);
for (l = GST_ELEMENT_CAST (mux)->sinkpads; l != NULL; l = l->next) {
GstFlvMuxPad *pad = GST_FLV_MUX_PAD (l->data);
duration = MAX (duration, pad->last_timestamp);
}
}
+ GST_OBJECT_UNLOCK (mux);
return duration;
}
+struct DurationData
+{
+ GstClockTime duration;
+};
+
+static gboolean
+duration_query_cb (GstElement * element, GstPad * pad,
+ struct DurationData *data)
+{
+ guint64 dur;
+
+ if (gst_pad_peer_query_duration (GST_PAD (pad), GST_FORMAT_TIME,
+ (gint64 *) & dur) && dur != GST_CLOCK_TIME_NONE) {
+ if (data->duration == GST_CLOCK_TIME_NONE)
+ data->duration = dur;
+ else
+ data->duration = MAX (dur, data->duration);
+ }
+
+ return TRUE;
+}
+
+static guint64
+gst_flv_mux_query_upstream_duration (GstFlvMux * mux)
+{
+ struct DurationData cb_data = { GST_CLOCK_TIME_NONE };
+
+ gst_element_foreach_sink_pad (GST_ELEMENT (mux),
+ (GstElementForeachPadFunc) (duration_query_cb), &cb_data);
+
+ return cb_data.duration;
+}
+
+
static gboolean
gst_flv_mux_are_all_pads_eos (GstFlvMux * mux)
{
GList *l;
+ GST_OBJECT_LOCK (mux);
for (l = GST_ELEMENT_CAST (mux)->sinkpads; l; l = l->next) {
GstFlvMuxPad *pad = GST_FLV_MUX_PAD (l->data);
- if (!gst_aggregator_pad_is_eos (GST_AGGREGATOR_PAD (pad)))
+ if (!gst_aggregator_pad_is_eos (GST_AGGREGATOR_PAD (pad))) {
+ GST_OBJECT_UNLOCK (mux);
return FALSE;
+ }
}
+ GST_OBJECT_UNLOCK (mux);
return TRUE;
}
return gst_flv_mux_push (mux, rewrite);
}
+/* Returns NULL, or a reference to the pad with the
+ * buffer with lowest running time */
static GstFlvMuxPad *
gst_flv_mux_find_best_pad (GstAggregator * aggregator, GstClockTime * ts)
{
- GstAggregatorPad *apad;
- GstFlvMuxPad *pad, *best = NULL;
- GList *l;
+ GstFlvMuxPad *best = NULL;
GstBuffer *buffer;
GstClockTime best_ts = GST_CLOCK_TIME_NONE;
-
- for (l = GST_ELEMENT_CAST (aggregator)->sinkpads; l; l = l->next) {
- apad = GST_AGGREGATOR_PAD (l->data);
- pad = GST_FLV_MUX_PAD (l->data);
- buffer = gst_aggregator_pad_peek_buffer (GST_AGGREGATOR_PAD (pad));
- if (!buffer)
- continue;
- if (best_ts == GST_CLOCK_TIME_NONE) {
- best = pad;
- best_ts = gst_flv_mux_segment_to_running_time (&apad->segment,
- GST_BUFFER_DTS_OR_PTS (buffer));
- } else if (GST_BUFFER_DTS_OR_PTS (buffer) != GST_CLOCK_TIME_NONE) {
- gint64 t = gst_flv_mux_segment_to_running_time (&apad->segment,
- GST_BUFFER_DTS_OR_PTS (buffer));
- if (t < best_ts) {
- best = pad;
- best_ts = t;
+ GstIterator *pads;
+ GValue padptr = { 0, };
+ gboolean done = FALSE;
+
+ pads = gst_element_iterate_sink_pads (GST_ELEMENT (aggregator));
+
+ while (!done) {
+ switch (gst_iterator_next (pads, &padptr)) {
+ case GST_ITERATOR_OK:{
+
+ GstAggregatorPad *apad = g_value_get_object (&padptr);
+ buffer = gst_aggregator_pad_peek_buffer (apad);
+ if (!buffer)
+ continue;
+ if (best_ts == GST_CLOCK_TIME_NONE) {
+ gst_object_replace ((GstObject **) & best, GST_OBJECT (apad));
+ best_ts = gst_flv_mux_segment_to_running_time (&apad->segment,
+ GST_BUFFER_DTS_OR_PTS (buffer));
+ } else if (GST_BUFFER_DTS_OR_PTS (buffer) != GST_CLOCK_TIME_NONE) {
+ gint64 t = gst_flv_mux_segment_to_running_time (&apad->segment,
+ GST_BUFFER_DTS_OR_PTS (buffer));
+ if (t < best_ts) {
+ gst_object_replace ((GstObject **) & best, GST_OBJECT (apad));
+ best_ts = t;
+ }
+ }
+ gst_buffer_unref (buffer);
+ g_value_reset (&padptr);
+ break;
}
+ case GST_ITERATOR_DONE:
+ done = TRUE;
+ break;
+ case GST_ITERATOR_RESYNC:
+ gst_iterator_resync (pads);
+ /* Clear the best pad and start again. It might have disappeared */
+ gst_object_replace ((GstObject **) best, NULL);
+ best_ts = GST_CLOCK_TIME_NONE;
+ break;
+ case GST_ITERATOR_ERROR:
+ /* This can't happen if the parameters to gst_iterator_next() are valid */
+ g_assert_not_reached ();
+ break;
}
- gst_buffer_unref (buffer);
}
+ g_value_unset (&padptr);
+ gst_iterator_free (pads);
+
GST_DEBUG_OBJECT (aggregator,
"Best pad found with %" GST_TIME_FORMAT ": %" GST_PTR_FORMAT,
GST_TIME_ARGS (best_ts), best);
gst_buffer_unref (buffer);
buffer = NULL;
}
+ gst_object_unref (best);
best = NULL;
}
if (best) {
- return gst_flv_mux_write_buffer (mux, best, buffer);
+ GstFlowReturn ret = gst_flv_mux_write_buffer (mux, best, buffer);
+ gst_object_unref (best);
+ return ret;
} else {
if (gst_flv_mux_are_all_pads_eos (mux)) {
gst_flv_mux_write_eos (mux);