/** * gst_clock_get_internal_time * @clock: a #GstClock to query * * Gets the current internal time of the given clock. The time is returned * unadjusted for the offset and the rate. * * Returns: the internal time of the clock. Or GST_CLOCK_TIME_NONE when * given invalid input. * * MT safe. */ GstClockTime gst_clock_get_internal_time (GstClock * clock) { GstClockTime ret; GstClockClass *cclass; g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_TIME_NONE); cclass = GST_CLOCK_GET_CLASS (clock); if (G_UNLIKELY (cclass->get_internal_time == NULL)) goto not_supported; ret = cclass->get_internal_time (clock); GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "internal time %" GST_TIME_FORMAT, GST_TIME_ARGS (ret)); return ret; /* ERRORS */ not_supported: { GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "internal time not supported, return 0"); return G_GINT64_CONSTANT (0); } }
static GstClockReturn gst_test_clock_wait_async (GstClock * clock, GstClockEntry * entry) { GstTestClock *test_clock = GST_TEST_CLOCK (clock); GST_OBJECT_LOCK (test_clock); if (GST_CLOCK_ENTRY_STATUS (entry) == GST_CLOCK_UNSCHEDULED) goto was_unscheduled; GST_CAT_DEBUG_OBJECT (GST_CAT_TEST_CLOCK, test_clock, "requesting asynchronous clock notification at %" GST_TIME_FORMAT, GST_TIME_ARGS (GST_CLOCK_ENTRY_TIME (entry))); gst_test_clock_add_entry (test_clock, entry, NULL); GST_OBJECT_UNLOCK (test_clock); return GST_CLOCK_OK; /* ERRORS */ was_unscheduled: { GST_CAT_DEBUG_OBJECT (GST_CAT_TEST_CLOCK, test_clock, "entry was unscheduled"); GST_OBJECT_UNLOCK (test_clock); return GST_CLOCK_UNSCHEDULED; } }
EXPORT_C #endif GstClockReturn gst_clock_id_wait_async (GstClockID id, GstClockCallback func, gpointer user_data) { GstClockEntry *entry; GstClock *clock; GstClockReturn res; GstClockClass *cclass; GstClockTime requested; g_return_val_if_fail (id != NULL, GST_CLOCK_ERROR); g_return_val_if_fail (func != NULL, GST_CLOCK_ERROR); entry = (GstClockEntry *) id; requested = GST_CLOCK_ENTRY_TIME (entry); clock = GST_CLOCK_ENTRY_CLOCK (entry); /* can't sync on invalid times */ if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (requested))) goto invalid_time; /* a previously unscheduled entry cannot be scheduled again */ if (G_UNLIKELY (entry->status == GST_CLOCK_UNSCHEDULED)) goto unscheduled; cclass = GST_CLOCK_GET_CLASS (clock); if (G_UNLIKELY (cclass->wait_async == NULL)) goto not_supported; entry->func = func; entry->user_data = user_data; res = cclass->wait_async (clock, entry); return res; /* ERRORS */ invalid_time: { (func) (clock, GST_CLOCK_TIME_NONE, id, user_data); GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "invalid time requested, returning _BADTIME"); return GST_CLOCK_BADTIME; } unscheduled: { GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "entry was unscheduled return _UNSCHEDULED"); return GST_CLOCK_UNSCHEDULED; } not_supported: { GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "clock wait is not supported"); return GST_CLOCK_UNSUPPORTED; } }
/** * gst_object_set_parent: * @object: a #GstObject * @parent: new parent of object * * Sets the parent of @object to @parent. The object's reference count will * be incremented, and any floating reference will be removed (see gst_object_ref_sink()). * * Returns: TRUE if @parent could be set or FALSE when @object * already had a parent or @object and @parent are the same. * * MT safe. Grabs and releases @object's LOCK. */ gboolean gst_object_set_parent (GstObject * object, GstObject * parent) { g_return_val_if_fail (GST_IS_OBJECT (object), FALSE); g_return_val_if_fail (GST_IS_OBJECT (parent), FALSE); g_return_val_if_fail (object != parent, FALSE); GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object, "set parent (ref and sink)"); GST_OBJECT_LOCK (object); if (G_UNLIKELY (object->parent != NULL)) goto had_parent; object->parent = parent; gst_object_ref_sink (object); GST_OBJECT_UNLOCK (object); /* FIXME, this does not work, the deep notify takes the lock from the parent * object and deadlocks when the parent holds its lock when calling this * function (like _element_add_pad()) */ /* g_object_notify_by_pspec ((GObject *)object, properties[PROP_PARENT]); */ return TRUE; /* ERROR handling */ had_parent: { GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object, "set parent failed, object already had a parent"); GST_OBJECT_UNLOCK (object); return FALSE; } }
/** * gst_clock_get_internal_time: * @clock: a #GstClock to query * * Gets the current internal time of the given clock. The time is returned * unadjusted for the offset and the rate. * * Returns: the internal time of the clock. Or GST_CLOCK_TIME_NONE when * given invalid input. * * MT safe. */ GstClockTime gst_clock_get_internal_time (GstClock * clock) { GstClockTime ret; GstClockClass *cclass; g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_TIME_NONE); if (G_UNLIKELY (GST_OBJECT_FLAG_IS_SET (clock, GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC) && !clock->priv->synced)) GST_CAT_WARNING_OBJECT (GST_CAT_CLOCK, clock, "clocked is not synchronized yet"); cclass = GST_CLOCK_GET_CLASS (clock); if (G_UNLIKELY (cclass->get_internal_time == NULL)) goto not_supported; ret = cclass->get_internal_time (clock); GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "internal time %" GST_TIME_FORMAT, GST_TIME_ARGS (ret)); return ret; /* ERRORS */ not_supported: { GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "internal time not supported, return 0"); return G_GINT64_CONSTANT (0); } }
static void gst_spot_src_init (GstSpotSrc * spot, GstSpotSrcClass * g_class) { GError *err; spot->read_position = 0; /* its childish to use static global variables */ ugly_spot = GST_SPOT_SRC (spot); GST_SPOT_SRC_URI (spot) = g_strdup (DEFAULT_URI); GST_SPOT_SRC_BUFFER_TIME (spot) = BUFFER_TIME_DEFAULT; GST_SPOT_SRC_ADAPTER_MUTEX (spot) = g_mutex_new (); GST_SPOT_SRC_ADAPTER_COND (spot) = g_cond_new (); GST_SPOT_SRC_ADAPTER (spot) = gst_adapter_new (); /* initiate format to default format */ GST_SPOT_SRC_FORMAT (spot) = g_malloc0 (sizeof (sp_audioformat)); GST_SPOT_SRC_FORMAT (spot)->sample_rate = SPOTIFY_DEFAULT_SAMPLE_RATE; GST_SPOT_SRC_FORMAT (spot)->channels = SPOTIFY_DEFAULT_NUMBER_CHANNELS; GST_SPOT_SRC_FORMAT (spot)->sample_type = SP_SAMPLETYPE_INT16_NATIVE_ENDIAN; /* initiate state varables */ spot->spot_works = NULL; spot->play_token_lost = FALSE; spot->end_of_track = FALSE; spot->unlock_state = FALSE; /* initiate user settings */ spot->user = g_strdup (DEFAULT_USER); spot->pass = g_strdup (DEFAULT_PASS); spot->uri = g_strdup (DEFAULT_URI); spot->logged_in = FALSE; /* intiate worker thread and its state variables */ spot->keep_spotify_thread = TRUE; spot->spotify_thread_initiated = FALSE; spot->process_events_mutex = g_mutex_new (); spot->process_events_cond = g_cond_new (); spot->process_events_thread = g_thread_create ((GThreadFunc)spotify_thread_func, spot, TRUE, &err); if (spot->process_events_thread == NULL) { GST_CAT_ERROR_OBJECT (gst_spot_src_debug_threads, spot,"G_thread_create failed: %s!", err->message ); g_error_free (err) ; } /* make sure spotify thread is up and running, before continuing. */ GST_CAT_DEBUG_OBJECT (gst_spot_src_debug_threads, spot, "Broadcast process_events_cond"); g_cond_broadcast (spot->process_events_cond); while (!spot->spotify_thread_initiated) { /* ugly but hey it yields right. */ usleep (40); GST_CAT_DEBUG_OBJECT (gst_spot_src_debug_threads, spot, "Broadcast process_events_cond, in loop"); g_cond_broadcast (spot->process_events_cond); } }
/** * gst_clock_set_master: * @clock: a #GstClock * @master: (allow-none): a master #GstClock * * Set @master as the master clock for @clock. @clock will be automatically * calibrated so that gst_clock_get_time() reports the same time as the * master clock. * * A clock provider that slaves its clock to a master can get the current * calibration values with gst_clock_get_calibration(). * * @master can be %NULL in which case @clock will not be slaved anymore. It will * however keep reporting its time adjusted with the last configured rate * and time offsets. * * Returns: %TRUE if the clock is capable of being slaved to a master clock. * Trying to set a master on a clock without the * #GST_CLOCK_FLAG_CAN_SET_MASTER flag will make this function return %FALSE. * * MT safe. */ gboolean gst_clock_set_master (GstClock * clock, GstClock * master) { GstClock **master_p; GstClockPrivate *priv; g_return_val_if_fail (GST_IS_CLOCK (clock), FALSE); g_return_val_if_fail (master != clock, FALSE); GST_OBJECT_LOCK (clock); /* we always allow setting the master to NULL */ if (master && !GST_OBJECT_FLAG_IS_SET (clock, GST_CLOCK_FLAG_CAN_SET_MASTER)) goto not_supported; GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "slaving %p to master clock %p", clock, master); GST_OBJECT_UNLOCK (clock); priv = clock->priv; GST_CLOCK_SLAVE_LOCK (clock); if (priv->clockid) { gst_clock_id_unschedule (priv->clockid); gst_clock_id_unref (priv->clockid); priv->clockid = NULL; } if (master) { priv->filling = TRUE; priv->time_index = 0; /* use the master periodic id to schedule sampling and * clock calibration. */ priv->clockid = gst_clock_new_periodic_id (master, gst_clock_get_time (master), priv->timeout); gst_clock_id_wait_async (priv->clockid, (GstClockCallback) gst_clock_slave_callback, gst_object_ref (clock), (GDestroyNotify) gst_object_unref); } GST_CLOCK_SLAVE_UNLOCK (clock); GST_OBJECT_LOCK (clock); master_p = &priv->master; gst_object_replace ((GstObject **) master_p, (GstObject *) master); GST_OBJECT_UNLOCK (clock); return TRUE; /* ERRORS */ not_supported: { GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "cannot be slaved to a master clock"); GST_OBJECT_UNLOCK (clock); return FALSE; } }
/** * gst_clock_id_wait: * @id: The #GstClockID to wait on * @jitter: (out) (allow-none): a pointer that will contain the jitter, * can be %NULL. * * Perform a blocking wait on @id. * @id should have been created with gst_clock_new_single_shot_id() * or gst_clock_new_periodic_id() and should not have been unscheduled * with a call to gst_clock_id_unschedule(). * * If the @jitter argument is not %NULL and this function returns #GST_CLOCK_OK * or #GST_CLOCK_EARLY, it will contain the difference * against the clock and the time of @id when this method was * called. * Positive values indicate how late @id was relative to the clock * (in which case this function will return #GST_CLOCK_EARLY). * Negative values indicate how much time was spent waiting on the clock * before this function returned. * * Returns: the result of the blocking wait. #GST_CLOCK_EARLY will be returned * if the current clock time is past the time of @id, #GST_CLOCK_OK if * @id was scheduled in time. #GST_CLOCK_UNSCHEDULED if @id was * unscheduled with gst_clock_id_unschedule(). * * MT safe. */ GstClockReturn gst_clock_id_wait (GstClockID id, GstClockTimeDiff * jitter) { GstClockEntry *entry; GstClock *clock; GstClockReturn res; GstClockTime requested; GstClockClass *cclass; g_return_val_if_fail (id != NULL, GST_CLOCK_ERROR); entry = (GstClockEntry *) id; requested = GST_CLOCK_ENTRY_TIME (entry); clock = GST_CLOCK_ENTRY_CLOCK (entry); /* can't sync on invalid times */ if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (requested))) goto invalid_time; cclass = GST_CLOCK_GET_CLASS (clock); GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "waiting on clock entry %p", id); /* if we have a wait_jitter function, use that */ if (G_UNLIKELY (cclass->wait == NULL)) goto not_supported; res = cclass->wait (clock, entry, jitter); GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "done waiting entry %p, res: %d (%s)", id, res, gst_clock_return_get_name (res)); if (entry->type == GST_CLOCK_ENTRY_PERIODIC) entry->time = requested + entry->interval; return res; /* ERRORS */ invalid_time: { GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "invalid time requested, returning _BADTIME"); return GST_CLOCK_BADTIME; } not_supported: { GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "clock wait is not supported"); return GST_CLOCK_UNSUPPORTED; } }
static void default_release_buffer (GstBufferPool * pool, GstBuffer * buffer) { GST_LOG_OBJECT (pool, "released buffer %p %d", buffer, GST_MINI_OBJECT_FLAGS (buffer)); /* memory should be untouched */ if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY))) goto memory_tagged; /* size should have been reset. This is not a catch all, pool with * size requirement per memory should do their own check. */ if (G_UNLIKELY (gst_buffer_get_size (buffer) != pool->priv->size)) goto size_changed; /* all memory should be exclusive to this buffer (and thus be writable) */ if (G_UNLIKELY (!gst_buffer_is_all_memory_writable (buffer))) goto not_writable; /* keep it around in our queue */ gst_atomic_queue_push (pool->priv->queue, buffer); gst_poll_write_control (pool->priv->poll); return; memory_tagged: { GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, pool, "discarding buffer %p: memory tag set", buffer); goto discard; } size_changed: { GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, pool, "discarding buffer %p: size %" G_GSIZE_FORMAT " != %u", buffer, gst_buffer_get_size (buffer), pool->priv->size); goto discard; } not_writable: { GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, pool, "discarding buffer %p: memory not writable", buffer); goto discard; } discard: { do_free_buffer (pool, buffer); return; } }
static gboolean gst_dshowvideodec_sink_event (GstPad * pad, GstEvent * event) { gboolean ret = TRUE; GstDshowVideoDec *vdec = (GstDshowVideoDec *) gst_pad_get_parent (pad); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_FLUSH_STOP: gst_dshowvideodec_flush (vdec); ret = gst_pad_event_default (pad, event); break; case GST_EVENT_NEWSEGMENT: { GstFormat format; gdouble rate; gint64 start, stop, time; gboolean update; gst_event_parse_new_segment (event, &update, &rate, &format, &start, &stop, &time); /* save the new segment in our local current segment */ gst_segment_set_newsegment (vdec->segment, update, rate, format, start, stop, time); GST_CAT_DEBUG_OBJECT (dshowvideodec_debug, vdec, "new segment received => start=%" GST_TIME_FORMAT " stop=%" GST_TIME_FORMAT, GST_TIME_ARGS (vdec->segment->start), GST_TIME_ARGS (vdec->segment->stop)); if (update) { GST_CAT_DEBUG_OBJECT (dshowvideodec_debug, vdec, "closing current segment flushing.."); gst_dshowvideodec_flush (vdec); } ret = gst_pad_event_default (pad, event); break; } default: ret = gst_pad_event_default (pad, event); break; } gst_object_unref (vdec); return ret; }
/** * gst_clock_id_wait_async: * @id: a #GstClockID to wait on * @func: The callback function * @user_data: User data passed in the callback * @destroy_data: #GDestroyNotify for user_data * * Register a callback on the given #GstClockID @id with the given * function and user_data. When passing a #GstClockID with an invalid * time to this function, the callback will be called immediately * with a time set to GST_CLOCK_TIME_NONE. The callback will * be called when the time of @id has been reached. * * The callback @func can be invoked from any thread, either provided by the * core or from a streaming thread. The application should be prepared for this. * * Returns: the result of the non blocking wait. * * MT safe. */ GstClockReturn gst_clock_id_wait_async (GstClockID id, GstClockCallback func, gpointer user_data, GDestroyNotify destroy_data) { GstClockEntry *entry; GstClock *clock; GstClockReturn res; GstClockClass *cclass; GstClockTime requested; g_return_val_if_fail (id != NULL, GST_CLOCK_ERROR); g_return_val_if_fail (func != NULL, GST_CLOCK_ERROR); entry = (GstClockEntry *) id; requested = GST_CLOCK_ENTRY_TIME (entry); clock = GST_CLOCK_ENTRY_CLOCK (entry); /* can't sync on invalid times */ if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (requested))) goto invalid_time; cclass = GST_CLOCK_GET_CLASS (clock); if (G_UNLIKELY (cclass->wait_async == NULL)) goto not_supported; entry->func = func; entry->user_data = user_data; entry->destroy_data = destroy_data; res = cclass->wait_async (clock, entry); return res; /* ERRORS */ invalid_time: { (func) (clock, GST_CLOCK_TIME_NONE, id, user_data); GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "invalid time requested, returning _BADTIME"); return GST_CLOCK_BADTIME; } not_supported: { GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "clock wait is not supported"); return GST_CLOCK_UNSUPPORTED; } }
EXPORT_C #endif void gst_clock_set_calibration (GstClock * clock, GstClockTime internal, GstClockTime external, GstClockTime rate_num, GstClockTime rate_denom) { g_return_if_fail (GST_IS_CLOCK (clock)); g_return_if_fail (rate_num >= 0); g_return_if_fail (rate_denom > 0); g_return_if_fail (internal <= gst_clock_get_internal_time (clock)); GST_OBJECT_LOCK (clock); GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "internal %" GST_TIME_FORMAT " external %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT " = %f", GST_TIME_ARGS (internal), GST_TIME_ARGS (external), rate_num, rate_denom, gst_guint64_to_gdouble (rate_num / rate_denom)); clock->internal_calibration = internal; clock->external_calibration = external; clock->rate_numerator = rate_num; clock->rate_denominator = rate_denom; GST_OBJECT_UNLOCK (clock); }
static void spotify_cb_notify_main_thread (sp_session *spotify_session) { GST_CAT_LOG_OBJECT (gst_spot_src_debug_cb, ugly_spot, "Notify_main_thread callback"); GST_CAT_DEBUG_OBJECT (gst_spot_src_debug_threads, ugly_spot, "Broadcast process_events_cond"); g_cond_broadcast (ugly_spot->process_events_cond); }
static GstClockID gst_clock_entry_new (GstClock * clock, GstClockTime time, GstClockTime interval, GstClockEntryType type) { GstClockEntry *entry; entry = g_slice_new (GstClockEntry); #ifndef GST_DISABLE_TRACE _gst_alloc_trace_new (_gst_clock_entry_trace, entry); #endif GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "created entry %p, time %" GST_TIME_FORMAT, entry, GST_TIME_ARGS (time)); entry->refcount = 1; entry->clock = clock; entry->type = type; entry->time = time; entry->interval = interval; entry->status = GST_CLOCK_OK; entry->func = NULL; entry->user_data = NULL; entry->destroy_data = NULL; entry->unscheduled = FALSE; entry->woken_up = FALSE; return (GstClockID) entry; }
void GSTGLAPI _gst_gl_debug_callback (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const gchar * message, gpointer user_data) { GstGLContext *context = user_data; const gchar *severity_str = _debug_severity_to_string (severity); const gchar *source_str = _debug_source_to_string (source); const gchar *type_str = _debug_type_to_string (type); _init_debug (); switch (type) { case GL_DEBUG_TYPE_ERROR: case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOUR: GST_ERROR_OBJECT (context, "%s: GL %s from %s id:%u, %s", severity_str, type_str, source_str, id, message); break; case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOUR: case GL_DEBUG_TYPE_PORTABILITY: GST_FIXME_OBJECT (context, "%s: GL %s from %s id:%u, %s", severity_str, type_str, source_str, id, message); break; case GL_DEBUG_TYPE_PERFORMANCE: GST_CAT_DEBUG_OBJECT (gst_performance, context, "%s: GL %s from %s id:%u," " %s", severity_str, type_str, source_str, id, message); break; default: GST_DEBUG_OBJECT (context, "%s: GL %s from %s id:%u, %s", severity_str, type_str, source_str, id, message); break; } }
static void gst_spot_src_finalize (GObject * object) { GstSpotSrc *spot; spot = GST_SPOT_SRC (object); /* make thread quit */ g_mutex_lock (spot->process_events_mutex); spot->keep_spotify_thread = FALSE; GST_CAT_DEBUG_OBJECT (gst_spot_src_debug_threads, spot, "Broadcast process_events_cond"); g_cond_broadcast (spot->process_events_cond); g_mutex_unlock (spot->process_events_mutex); g_thread_join (spot->process_events_thread); /* free user variables */ g_free (spot->user); g_free (spot->pass); g_free (spot->uri); g_free (spot->format); g_list_free (spot->spot_works); g_cond_free (spot->process_events_cond); g_mutex_free (spot->process_events_mutex); g_mutex_free (GST_SPOT_SRC_ADAPTER_MUTEX (spot)); g_cond_free (GST_SPOT_SRC_ADAPTER_COND (spot)); g_object_unref (GST_SPOT_SRC_ADAPTER (spot)); G_OBJECT_CLASS (parent_class)->finalize (object); }
/** * gst_clock_set_calibration: * @clock: a #GstClock to calibrate * @internal: a reference internal time * @external: a reference external time * @rate_num: the numerator of the rate of the clock relative to its * internal time * @rate_denom: the denominator of the rate of the clock * * Adjusts the rate and time of @clock. A rate of 1/1 is the normal speed of * the clock. Values bigger than 1/1 make the clock go faster. * * @internal and @external are calibration parameters that arrange that * gst_clock_get_time() should have been @external at internal time @internal. * This internal time should not be in the future; that is, it should be less * than the value of gst_clock_get_internal_time() when this function is called. * * Subsequent calls to gst_clock_get_time() will return clock times computed as * follows: * * <programlisting> * time = (internal_time - internal) * rate_num / rate_denom + external * </programlisting> * * This formula is implemented in gst_clock_adjust_unlocked(). Of course, it * tries to do the integer arithmetic as precisely as possible. * * Note that gst_clock_get_time() always returns increasing values so when you * move the clock backwards, gst_clock_get_time() will report the previous value * until the clock catches up. * * MT safe. */ void gst_clock_set_calibration (GstClock * clock, GstClockTime internal, GstClockTime external, GstClockTime rate_num, GstClockTime rate_denom) { GstClockPrivate *priv; g_return_if_fail (GST_IS_CLOCK (clock)); g_return_if_fail (rate_num != GST_CLOCK_TIME_NONE); g_return_if_fail (rate_denom > 0 && rate_denom != GST_CLOCK_TIME_NONE); priv = clock->priv; write_seqlock (clock); GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "internal %" GST_TIME_FORMAT " external %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT " = %f", GST_TIME_ARGS (internal), GST_TIME_ARGS (external), rate_num, rate_denom, gst_guint64_to_gdouble (rate_num) / gst_guint64_to_gdouble (rate_denom)); priv->internal_calibration = internal; priv->external_calibration = external; priv->rate_numerator = rate_num; priv->rate_denominator = rate_denom; write_sequnlock (clock); }
static GstFlowReturn gst_dshowaudiodec_chain (GstPad * pad, GstBuffer * buffer) { GstDshowAudioDec *adec = (GstDshowAudioDec *) gst_pad_get_parent (pad); bool discont = FALSE; if (!adec->setup) { /* we are not set up */ GST_WARNING_OBJECT (adec, "Decoder not set up, failing"); adec->last_ret = GST_FLOW_WRONG_STATE; goto beach; } if (GST_FLOW_IS_FATAL (adec->last_ret)) { GST_DEBUG_OBJECT (adec, "last decoding iteration generated a fatal error " "%s", gst_flow_get_name (adec->last_ret)); goto beach; } GST_CAT_DEBUG_OBJECT (dshowaudiodec_debug, adec, "chain (size %d)=> pts %" GST_TIME_FORMAT " stop %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buffer), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer))); /* if the incoming buffer has discont flag set => flush decoder data */ if (buffer && GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) { GST_CAT_DEBUG_OBJECT (dshowaudiodec_debug, adec, "this buffer has a DISCONT flag (%" GST_TIME_FORMAT "), flushing", GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer))); gst_dshowaudiodec_flush (adec); discont = TRUE; } /* push the buffer to the directshow decoder */ adec->fakesrc->GetOutputPin()->PushBuffer ( GST_BUFFER_DATA (buffer), GST_BUFFER_TIMESTAMP (buffer), GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer), GST_BUFFER_SIZE (buffer), (bool)discont); beach: gst_buffer_unref (buffer); gst_object_unref (adec); return adec->last_ret; }
static void spotify_cb_end_of_track (sp_session *session) { GST_CAT_DEBUG_OBJECT (gst_spot_src_debug_cb, ugly_spot, "End_of_track callback"); g_mutex_lock (GST_SPOT_SRC_ADAPTER_MUTEX (ugly_spot)); ugly_spot->end_of_track = TRUE; g_cond_broadcast (GST_SPOT_SRC_ADAPTER_COND (ugly_spot)); g_mutex_unlock (GST_SPOT_SRC_ADAPTER_MUTEX (ugly_spot)); }
EXPORT_C #endif gboolean gst_object_set_parent (GstObject * object, GstObject * parent) { g_return_val_if_fail (GST_IS_OBJECT (object), FALSE); g_return_val_if_fail (GST_IS_OBJECT (parent), FALSE); g_return_val_if_fail (object != parent, FALSE); GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object, "set parent (ref and sink)"); GST_OBJECT_LOCK (object); if (G_UNLIKELY (object->parent != NULL)) goto had_parent; /* sink object, we don't call our own function because we don't * need to release/acquire the lock needlessly or touch the refcount * in the floating case. */ object->parent = parent; if (G_LIKELY (GST_OBJECT_IS_FLOATING (object))) { GST_CAT_LOG_OBJECT (GST_CAT_REFCOUNTING, object, "unsetting floating flag"); GST_OBJECT_FLAG_UNSET (object, GST_OBJECT_FLOATING); GST_OBJECT_UNLOCK (object); } else { GST_OBJECT_UNLOCK (object); gst_object_ref (object); } g_signal_emit (object, gst_object_signals[PARENT_SET], 0, parent); return TRUE; /* ERROR handling */ had_parent: { GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object, "set parent failed, object already had a parent"); GST_OBJECT_UNLOCK (object); return FALSE; } }
static GstFlowReturn gst_dshowvideodec_chain (GstPad * pad, GstBuffer * buffer) { GstDshowVideoDec *vdec = (GstDshowVideoDec *) gst_pad_get_parent (pad); bool discont = FALSE; GstClockTime stop; if (!vdec->setup) { /* we are not setup */ GST_WARNING_OBJECT (vdec, "Decoder not set up, failing"); vdec->last_ret = GST_FLOW_FLUSHING; goto beach; } if (GST_FLOW_IS_FATAL (vdec->last_ret)) { GST_DEBUG_OBJECT (vdec, "last decoding iteration generated a fatal error " "%s", gst_flow_get_name (vdec->last_ret)); goto beach; } /* check if duration is valid and use duration only when it's valid /* because dshow is not decoding frames having stop smaller than start */ if (GST_BUFFER_DURATION_IS_VALID (buffer)) { stop = GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer); } else { stop = GST_BUFFER_TIMESTAMP (buffer); } GST_CAT_LOG_OBJECT (dshowvideodec_debug, vdec, "chain (size %d)=> pts %" GST_TIME_FORMAT " stop %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buffer), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), GST_TIME_ARGS (stop)); /* if the incoming buffer has discont flag set => flush decoder data */ if (buffer && GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) { GST_CAT_DEBUG_OBJECT (dshowvideodec_debug, vdec, "this buffer has a DISCONT flag (%" GST_TIME_FORMAT "), flushing", GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer))); gst_dshowvideodec_flush (vdec); discont = TRUE; } /* push the buffer to the directshow decoder */ vdec->fakesrc->GetOutputPin()->PushBuffer( GST_BUFFER_DATA (buffer), GST_BUFFER_TIMESTAMP (buffer), stop, GST_BUFFER_SIZE (buffer), discont); beach: gst_buffer_unref (buffer); gst_object_unref (vdec); return vdec->last_ret; }
static GstFlowReturn gst_video_scale_transform_frame (GstVideoFilter * filter, GstVideoFrame * in_frame, GstVideoFrame * out_frame) { GstVideoScale *videoscale = GST_VIDEO_SCALE_CAST (filter); GstFlowReturn ret = GST_FLOW_OK; GST_CAT_DEBUG_OBJECT (CAT_PERFORMANCE, filter, "doing video scaling"); gst_video_converter_frame (videoscale->convert, in_frame, out_frame); return ret; }
static void gst_pipeline_dispose (GObject * object) { GstPipeline *pipeline = GST_PIPELINE (object); GstClock **clock_p = &pipeline->fixed_clock; GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, pipeline, "dispose"); /* clear and unref any fixed clock */ gst_object_replace ((GstObject **) clock_p, NULL); G_OBJECT_CLASS (parent_class)->dispose (object); }
static GstClockReturn gst_test_clock_wait (GstClock * clock, GstClockEntry * entry, GstClockTimeDiff * jitter) { GstTestClock *test_clock = GST_TEST_CLOCK (clock); GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock); GST_OBJECT_LOCK (test_clock); GST_CAT_DEBUG_OBJECT (GST_CAT_TEST_CLOCK, test_clock, "requesting synchronous clock notification at %" GST_TIME_FORMAT, GST_TIME_ARGS (GST_CLOCK_ENTRY_TIME (entry))); if (GST_CLOCK_ENTRY_STATUS (entry) == GST_CLOCK_UNSCHEDULED) goto was_unscheduled; if (gst_test_clock_lookup_entry_context (test_clock, entry) == NULL) gst_test_clock_add_entry (test_clock, entry, jitter); GST_CLOCK_ENTRY_STATUS (entry) = GST_CLOCK_BUSY; while (GST_CLOCK_ENTRY_STATUS (entry) == GST_CLOCK_BUSY) g_cond_wait (&priv->entry_processed_cond, GST_OBJECT_GET_LOCK (test_clock)); GST_OBJECT_UNLOCK (test_clock); return GST_CLOCK_ENTRY_STATUS (entry); /* ERRORS */ was_unscheduled: { GST_CAT_DEBUG_OBJECT (GST_CAT_TEST_CLOCK, test_clock, "entry was unscheduled"); GST_OBJECT_UNLOCK (test_clock); return GST_CLOCK_UNSCHEDULED; } }
static int spotify_cb_music_delivery (sp_session *spotify_session, const sp_audioformat *format,const void *frames, int num_frames) { GstBuffer *buffer; guint sample_rate = format->sample_rate; guint channels = format->channels; guint bufsize = num_frames * sizeof (int16_t) * channels; guint availible; GST_CAT_DEBUG_OBJECT (gst_spot_src_debug_cb, ugly_spot, "Music_delivery callback"); GST_SPOT_SRC_FORMAT (ugly_spot)->sample_rate = sample_rate; GST_SPOT_SRC_FORMAT (ugly_spot)->channels = channels; GST_SPOT_SRC_FORMAT (ugly_spot)->sample_type = format->sample_type; GST_CAT_LOG_OBJECT (gst_spot_src_debug_audio, ugly_spot, "Start %p with %d frames with size=%d", frames, num_frames, bufsize); if (num_frames == 0) { /* we have a seek */ return 0; } buffer = gst_buffer_new_and_alloc (bufsize); memcpy (GST_BUFFER_DATA (buffer), (guint8*)frames, bufsize); g_mutex_lock (GST_SPOT_SRC_ADAPTER_MUTEX (ugly_spot)); availible = gst_adapter_available (GST_SPOT_SRC_ADAPTER (ugly_spot)); GST_CAT_LOG_OBJECT (gst_spot_src_debug_audio, ugly_spot, "Availiable before push = %d", availible); /* see if we have buffertime of audio */ if (availible >= (GST_SPOT_SRC_BUFFER_TIME (ugly_spot)/1000000) * sample_rate * 4) { GST_CAT_LOG_OBJECT (gst_spot_src_debug_audio, ugly_spot, "Return 0, adapter is full = %d", availible); gst_buffer_unref (buffer); /* data is available broadcast read thread */ g_cond_broadcast (GST_SPOT_SRC_ADAPTER_COND (ugly_spot)); g_mutex_unlock (GST_SPOT_SRC_ADAPTER_MUTEX (ugly_spot)); return 0; } gst_adapter_push (GST_SPOT_SRC_ADAPTER (ugly_spot), buffer); availible = gst_adapter_available (GST_SPOT_SRC_ADAPTER (ugly_spot)); GST_CAT_LOG_OBJECT (gst_spot_src_debug_audio, ugly_spot, "Availiable after push = %d", availible); /* data is available broadcast read thread */ g_cond_broadcast (GST_SPOT_SRC_ADAPTER_COND (ugly_spot)); g_mutex_unlock (GST_SPOT_SRC_ADAPTER_MUTEX (ugly_spot)); GST_CAT_LOG_OBJECT (gst_spot_src_debug_audio, ugly_spot, "Return num_frames=%d", num_frames); return num_frames; }
static void gst_test_clock_unschedule (GstClock * clock, GstClockEntry * entry) { GstTestClock *test_clock = GST_TEST_CLOCK (clock); GST_OBJECT_LOCK (test_clock); GST_CAT_DEBUG_OBJECT (GST_CAT_TEST_CLOCK, test_clock, "unscheduling requested clock notification at %" GST_TIME_FORMAT, GST_TIME_ARGS (GST_CLOCK_ENTRY_TIME (entry))); GST_CLOCK_ENTRY_STATUS (entry) = GST_CLOCK_UNSCHEDULED; gst_test_clock_remove_entry (test_clock, entry); GST_OBJECT_UNLOCK (test_clock); }
static GstFlowReturn gst_video_convert_transform_frame (GstVideoFilter * filter, GstVideoFrame * in_frame, GstVideoFrame * out_frame) { GstVideoConvert *space; space = GST_VIDEO_CONVERT_CAST (filter); GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, filter, "doing colorspace conversion from %s -> to %s", GST_VIDEO_INFO_NAME (&filter->in_info), GST_VIDEO_INFO_NAME (&filter->out_info)); gst_video_converter_frame (space->convert, in_frame, out_frame); return GST_FLOW_OK; }
static void spotify_cb_logged_in (sp_session *spotify_session, sp_error error) { if (SP_ERROR_OK != error) { GST_CAT_ERROR_OBJECT (gst_spot_src_debug_cb, ugly_spot, "Failed to log in to Spotify: %s", sp_error_message (error)); return; } sp_user *me = sp_session_user (spotify_session); const char *my_name = (sp_user_is_loaded (me) ? sp_user_display_name (me) : sp_user_canonical_name (me)); GST_CAT_DEBUG_OBJECT (gst_spot_src_debug_cb, ugly_spot, "Logged_in callback, user=%s", my_name); /* set default bitrate to audiofility */ sp_session_preferred_bitrate(spotify_session, SP_BITRATE_320k); GST_SPOT_SRC_LOGGED_IN (ugly_spot) = TRUE; }
/* will be called repeatedly to sample the master and slave clock * to recalibrate the clock */ static gboolean gst_clock_slave_callback (GstClock * master, GstClockTime time, GstClockID id, GstClock * clock) { GstClockTime stime, mtime; gdouble r_squared; stime = gst_clock_get_internal_time (clock); mtime = gst_clock_get_time (master); GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "master %" GST_TIME_FORMAT ", slave %" GST_TIME_FORMAT, GST_TIME_ARGS (mtime), GST_TIME_ARGS (stime)); gst_clock_add_observation (clock, stime, mtime, &r_squared); /* FIXME, we can use the r_squared value to adjust the timeout * value of the clockid */ return TRUE; }
EXPORT_C #endif GstClockTime gst_clock_get_time (GstClock * clock) { GstClockTime ret; g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_TIME_NONE); ret = gst_clock_get_internal_time (clock); GST_OBJECT_LOCK (clock); /* this will scale for rate and offset */ ret = gst_clock_adjust_unlocked (clock, ret); GST_OBJECT_UNLOCK (clock); GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "adjusted time %" GST_TIME_FORMAT, GST_TIME_ARGS (ret)); return ret; }