gboolean sending_cached_buffers;
GQueue *cached_buffers;
+
+ GstClockID clock_id;
};
struct _GstSelectorPadCachedBuffer
gst_segment_init (&pad->segment, GST_FORMAT_UNDEFINED);
pad->sending_cached_buffers = FALSE;
gst_selector_pad_free_cached_buffers (pad);
+ if (pad->clock_id) {
+ gst_clock_id_unschedule (pad->clock_id);
+ gst_clock_id_unref (pad->clock_id);
+ }
+ pad->clock_id = NULL;
GST_OBJECT_UNLOCK (pad);
}
gst_pad_push_event (self->srcpad, gst_event_ref (eos_event));
GST_INPUT_SELECTOR_LOCK (self);
+ if (pad->clock_id) {
+ GST_DEBUG_OBJECT (pad, "unlock clock wait");
+ gst_clock_id_unschedule (pad->clock_id);
+ }
/* Wake up other pads so they can continue when syncing to
* running time, as this pad just switched to EOS and
* may enable others to progress */
selpad->flushing = TRUE;
sel->eos = FALSE;
selpad->group_done = FALSE;
+ if (selpad->clock_id) {
+ GST_DEBUG_OBJECT (selpad, "unlock clock wait");
+ gst_clock_id_unschedule (selpad->clock_id);
+ }
GST_INPUT_SELECTOR_BROADCAST (sel);
break;
case GST_EVENT_FLUSH_STOP:
while (TRUE) {
GstPad *active_sinkpad;
GstSelectorPad *active_selpad;
- GstClock *clock;
gint64 cur_running_time;
GstClockTime running_time;
}
cur_running_time = GST_CLOCK_TIME_NONE;
- if (sel->sync_mode == GST_INPUT_SELECTOR_SYNC_MODE_CLOCK) {
- clock = gst_element_get_clock (GST_ELEMENT_CAST (sel));
- if (clock) {
- GstClockTime base_time;
-
- cur_running_time = gst_clock_get_time (clock);
- base_time = gst_element_get_base_time (GST_ELEMENT_CAST (sel));
- if (base_time <= cur_running_time)
- cur_running_time -= base_time;
- else
- cur_running_time = 0;
-
- gst_object_unref (clock);
- }
- } else {
+ if (sel->sync_mode != GST_INPUT_SELECTOR_SYNC_MODE_CLOCK) {
GstSegment *active_seg;
active_seg = &active_selpad->segment;
break;
}
- if (selpad != active_selpad && !sel->eos && !sel->flushing
- && !selpad->flushing && (cur_running_time == GST_CLOCK_TIME_NONE
- || running_time >= cur_running_time)) {
+ if (selpad == active_selpad || sel->eos || sel->flushing
+ || selpad->flushing) {
+ GST_DEBUG_OBJECT (selpad, "Waiting aborted. Unblocking");
+ GST_INPUT_SELECTOR_UNLOCK (sel);
+ break;
+ }
+
+ if (sel->sync_mode == GST_INPUT_SELECTOR_SYNC_MODE_CLOCK
+ && GST_CLOCK_TIME_IS_VALID (running_time)) {
+ GstClock *clock;
+ GstClockReturn cret;
+ GstClockTime base_time;
+ GstClockTimeDiff jitter;
+ GstClockID clock_id;
+
+ base_time = gst_element_get_base_time (GST_ELEMENT_CAST (sel));
+ if (!GST_CLOCK_TIME_IS_VALID (base_time)) {
+ GST_DEBUG_OBJECT (selpad, "sync-mode=clock but no base time. Blocking");
+ GST_INPUT_SELECTOR_WAIT (sel);
+ continue;
+ }
+
+ clock = gst_element_get_clock (GST_ELEMENT_CAST (sel));
+ if (!clock) {
+ GST_DEBUG_OBJECT (selpad, "sync-mode=clock but no clock. Blocking");
+ GST_INPUT_SELECTOR_WAIT (sel);
+ continue;
+ }
+
+ /* FIXME: If no upstream latency was queried yet, do one now */
+ clock_id =
+ gst_clock_new_single_shot_id (clock,
+ running_time + base_time + sel->upstream_latency);
+ selpad->clock_id = gst_clock_id_ref (clock_id);
+ GST_INPUT_SELECTOR_UNLOCK (sel);
+
+ gst_object_unref (clock);
+ cret = gst_clock_id_wait (clock_id, &jitter);
+ gst_clock_id_unref (clock_id);
+
+ GST_DEBUG_OBJECT (sel, "Clock returned %d, jitter %" GST_STIME_FORMAT,
+ cret, GST_STIME_ARGS (jitter));
+
+ GST_INPUT_SELECTOR_LOCK (sel);
+ if (selpad->clock_id) {
+ gst_clock_id_unref (selpad->clock_id);
+ selpad->clock_id = NULL;
+ }
+ if (cret == GST_CLOCK_OK ||
+ cret == GST_CLOCK_EARLY || cret == GST_CLOCK_DONE) {
+ GST_INPUT_SELECTOR_UNLOCK (sel);
+ break;
+ }
+ } else if (!GST_CLOCK_TIME_IS_VALID (cur_running_time)
+ || running_time >= cur_running_time) {
GST_DEBUG_OBJECT (selpad,
"Waiting for active streams to advance. %" GST_TIME_FORMAT " >= %"
GST_TIME_FORMAT, GST_TIME_ARGS (running_time),
g_cond_init (&sel->cond);
sel->eos = FALSE;
+ sel->upstream_latency = 0;
+
/* lets give a change for downstream to do something on
* active-pad change before we start pushing new buffers */
g_signal_connect_data (sel, "notify::active-pad",
GST_ERROR_OBJECT (pad, "minimum latency bigger than maximum latency");
}
- gst_query_set_latency (query, fold_data.live, fold_data.min, fold_data.max);
+ GST_INPUT_SELECTOR_LOCK (sel);
+ if (fold_data.live)
+ sel->upstream_latency = fold_data.min;
+ else
+ sel->upstream_latency = 0;
+
+ gst_query_set_latency (query, fold_data.live
+ || (sel->sync_mode == GST_INPUT_SELECTOR_SYNC_MODE_CLOCK),
+ fold_data.min, fold_data.max);
+ GST_INPUT_SELECTOR_UNLOCK (sel);
} else {
GST_LOG_OBJECT (pad, "latency query failed");
}
}
}
sel->have_group_id = TRUE;
+ sel->upstream_latency = 0;
GST_INPUT_SELECTOR_UNLOCK (sel);
}
GST_INPUT_SELECTOR_BROADCAST (self);
GST_INPUT_SELECTOR_UNLOCK (self);
break;
+ case GST_STATE_CHANGE_PLAYING_TO_PAUSED:{
+ GList *walk;
+
+ for (walk = GST_ELEMENT_CAST (self)->sinkpads; walk;
+ walk = g_list_next (walk)) {
+ GstSelectorPad *selpad = GST_SELECTOR_PAD_CAST (walk->data);
+ if (selpad->clock_id) {
+ GST_DEBUG_OBJECT (selpad, "unlock clock wait");
+ gst_clock_id_unschedule (selpad->clock_id);
+ }
+ }
+ break;
+ }
default:
break;
}