gboolean shmdata_base_reader_reset_time (GstPad *pad, GstMiniObject * mini_obj, gpointer user_data) { shmdata_base_reader_t *context = (shmdata_base_reader_t *) user_data; if (GST_IS_EVENT (mini_obj)) { //g_debug ("EVENT %s", GST_EVENT_TYPE_NAME (GST_EVENT_CAST(mini_obj))); } else if (GST_IS_BUFFER (mini_obj)) { GstBuffer *buffer = GST_BUFFER_CAST (mini_obj); /* g_debug ("shmdata writer data frame (%p), data size %d, timestamp %llu, caps %s", */ /* GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer), */ /* GST_TIME_AS_MSECONDS (GST_BUFFER_TIMESTAMP (buffer)), */ /* gst_caps_to_string (GST_BUFFER_CAPS (buffer))); */ if (context->timereset_) { context->timeshift_ = GST_BUFFER_TIMESTAMP (buffer); context->timereset_ = FALSE; } GST_BUFFER_TIMESTAMP (buffer) = GST_BUFFER_TIMESTAMP (buffer) - context->timeshift_; } else if (GST_IS_MESSAGE (mini_obj)) { } return TRUE; }
/** * gst_is_missing_plugin_message: * @msg: a #GstMessage * * Checks whether @msg is a missing plugins message. * * Returns: %TRUE if @msg is a missing-plugins message, otherwise %FALSE. */ gboolean gst_is_missing_plugin_message (GstMessage * msg) { g_return_val_if_fail (msg != NULL, FALSE); g_return_val_if_fail (GST_IS_MESSAGE (msg), FALSE); if (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ELEMENT || msg->structure == NULL) return FALSE; return gst_structure_has_name (msg->structure, "missing-plugin"); }
/** * gst_bus_post: * @bus: a #GstBus to post on * @message: The #GstMessage to post * * Post a message on the given bus. Ownership of the message * is taken by the bus. * * Returns: TRUE if the message could be posted, FALSE if the bus is flushing. * * MT safe. */ gboolean gst_bus_post (GstBus * bus, GstMessage * message) { GstBusSyncReply reply = GST_BUS_PASS; GstBusSyncHandler handler; gboolean emit_sync_message; gpointer handler_data; g_return_val_if_fail (GST_IS_BUS (bus), FALSE); g_return_val_if_fail (GST_IS_MESSAGE (message), FALSE); GST_DEBUG_OBJECT (bus, "[msg %p] posting on bus, type %s, %" GST_PTR_FORMAT " from source %" GST_PTR_FORMAT, message, GST_MESSAGE_TYPE_NAME (message), message->structure, message->src); GST_OBJECT_LOCK (bus); /* check if the bus is flushing */ if (GST_OBJECT_FLAG_IS_SET (bus, GST_BUS_FLUSHING)) goto is_flushing; handler = bus->sync_handler; handler_data = bus->sync_handler_data; emit_sync_message = bus->priv->num_sync_message_emitters > 0; GST_OBJECT_UNLOCK (bus); /* first call the sync handler if it is installed */ if (handler) reply = handler (bus, message, handler_data); /* emit sync-message if requested to do so via gst_bus_enable_sync_message_emission. terrible but effective */ if (emit_sync_message && reply != GST_BUS_DROP && handler != gst_bus_sync_signal_handler) gst_bus_sync_signal_handler (bus, message, NULL); /* now see what we should do with the message */ switch (reply) { case GST_BUS_DROP: /* drop the message */ GST_DEBUG_OBJECT (bus, "[msg %p] dropped", message); break; case GST_BUS_PASS: /* pass the message to the async queue, refcount passed in the queue */ GST_DEBUG_OBJECT (bus, "[msg %p] pushing on async queue", message); g_mutex_lock (bus->queue_lock); g_queue_push_tail (bus->queue, message); g_cond_broadcast (bus->priv->queue_cond); g_mutex_unlock (bus->queue_lock); GST_DEBUG_OBJECT (bus, "[msg %p] pushed on async queue", message); gst_bus_wakeup_main_context (bus); break; case GST_BUS_ASYNC: { /* async delivery, we need a mutex and a cond to block * on */ GMutex *lock = g_mutex_new (); GCond *cond = g_cond_new (); GST_MESSAGE_COND (message) = cond; GST_MESSAGE_GET_LOCK (message) = lock; GST_DEBUG_OBJECT (bus, "[msg %p] waiting for async delivery", message); /* now we lock the message mutex, send the message to the async * queue. When the message is handled by the app and destroyed, * the cond will be signalled and we can continue */ g_mutex_lock (lock); g_mutex_lock (bus->queue_lock); g_queue_push_tail (bus->queue, message); g_cond_broadcast (bus->priv->queue_cond); g_mutex_unlock (bus->queue_lock); gst_bus_wakeup_main_context (bus); /* now block till the message is freed */ g_cond_wait (cond, lock); g_mutex_unlock (lock); GST_DEBUG_OBJECT (bus, "[msg %p] delivered asynchronously", message); g_mutex_free (lock); g_cond_free (cond); break; } default: g_warning ("invalid return from bus sync handler"); break; } return TRUE; /* ERRORS */ is_flushing: { GST_DEBUG_OBJECT (bus, "bus is flushing"); gst_message_unref (message); GST_OBJECT_UNLOCK (bus); return FALSE; } }
/** * gst_bus_post: * @bus: a #GstBus to post on * @message: (transfer full): the #GstMessage to post * * Post a message on the given bus. Ownership of the message * is taken by the bus. * * Returns: %TRUE if the message could be posted, %FALSE if the bus is flushing. * * MT safe. */ gboolean gst_bus_post (GstBus * bus, GstMessage * message) { GstBusSyncReply reply = GST_BUS_PASS; GstBusSyncHandler handler; gboolean emit_sync_message; gpointer handler_data; g_return_val_if_fail (GST_IS_BUS (bus), FALSE); g_return_val_if_fail (GST_IS_MESSAGE (message), FALSE); GST_DEBUG_OBJECT (bus, "[msg %p] posting on bus %" GST_PTR_FORMAT, message, message); /* check we didn't accidentally add a public flag that maps to same value */ g_assert (!GST_MINI_OBJECT_FLAG_IS_SET (message, GST_MESSAGE_FLAG_ASYNC_DELIVERY)); GST_OBJECT_LOCK (bus); /* check if the bus is flushing */ if (GST_OBJECT_FLAG_IS_SET (bus, GST_BUS_FLUSHING)) goto is_flushing; handler = bus->priv->sync_handler; handler_data = bus->priv->sync_handler_data; emit_sync_message = bus->priv->num_sync_message_emitters > 0; GST_OBJECT_UNLOCK (bus); /* first call the sync handler if it is installed */ if (handler) reply = handler (bus, message, handler_data); /* emit sync-message if requested to do so via gst_bus_enable_sync_message_emission. terrible but effective */ if (emit_sync_message && reply != GST_BUS_DROP && handler != gst_bus_sync_signal_handler) gst_bus_sync_signal_handler (bus, message, NULL); /* If this is a bus without async message delivery * always drop the message */ if (!bus->priv->poll) reply = GST_BUS_DROP; /* now see what we should do with the message */ switch (reply) { case GST_BUS_DROP: /* drop the message */ GST_DEBUG_OBJECT (bus, "[msg %p] dropped", message); break; case GST_BUS_PASS: /* pass the message to the async queue, refcount passed in the queue */ GST_DEBUG_OBJECT (bus, "[msg %p] pushing on async queue", message); gst_atomic_queue_push (bus->priv->queue, message); gst_poll_write_control (bus->priv->poll); GST_DEBUG_OBJECT (bus, "[msg %p] pushed on async queue", message); break; case GST_BUS_ASYNC: { /* async delivery, we need a mutex and a cond to block * on */ GCond *cond = GST_MESSAGE_GET_COND (message); GMutex *lock = GST_MESSAGE_GET_LOCK (message); g_cond_init (cond); g_mutex_init (lock); GST_MINI_OBJECT_FLAG_SET (message, GST_MESSAGE_FLAG_ASYNC_DELIVERY); GST_DEBUG_OBJECT (bus, "[msg %p] waiting for async delivery", message); /* now we lock the message mutex, send the message to the async * queue. When the message is handled by the app and destroyed, * the cond will be signalled and we can continue */ g_mutex_lock (lock); gst_atomic_queue_push (bus->priv->queue, message); gst_poll_write_control (bus->priv->poll); /* now block till the message is freed */ g_cond_wait (cond, lock); /* we acquired a new ref from gst_message_dispose() so we can clean up */ g_mutex_unlock (lock); GST_DEBUG_OBJECT (bus, "[msg %p] delivered asynchronously", message); GST_MINI_OBJECT_FLAG_UNSET (message, GST_MESSAGE_FLAG_ASYNC_DELIVERY); g_mutex_clear (lock); g_cond_clear (cond); gst_message_unref (message); break; } default: g_warning ("invalid return from bus sync handler"); break; } return TRUE; /* ERRORS */ is_flushing: { GST_DEBUG_OBJECT (bus, "bus is flushing"); GST_OBJECT_UNLOCK (bus); gst_message_unref (message); return FALSE; } }
void __mm_player_streaming_buffering(mm_player_streaming_t* streamer, GstMessage *buffering_msg) { GstBufferingMode mode = GST_BUFFERING_STREAM; gint byte_in_rate = 0; gint byte_out_rate = 0; gint64 buffering_left = -1; gdouble buffering_time = DEFAULT_BUFFERING_TIME; gdouble low_percent = 0.0; gdouble high_percent = 0.0; guint high_percent_byte = 0; gint buffer_percent = 0; guint buffer_criteria = 0; return_if_fail ( streamer ); return_if_fail ( buffering_msg ); return_if_fail ( GST_IS_MESSAGE ( buffering_msg ) ); return_if_fail ( GST_MESSAGE_TYPE ( buffering_msg ) == GST_MESSAGE_BUFFERING ); /* update when buffering has started. */ if ( !streamer->is_buffering ) { debug_log ( "buffering has started.\n" ); streamer->is_buffering = TRUE; streamer->buffering_percent = -1; streamer->need_update = TRUE; } /* update buffer percent */ gst_message_parse_buffering ( buffering_msg, &buffer_percent ); if ( streamer->buffering_percent < buffer_percent ) { debug_log ( "buffering %d%%....\n", buffer_percent ); streamer->buffering_percent = buffer_percent; } if ( streamer->buffering_percent == MAX_BUFFER_PERCENT ) { debug_log ( "buffering had done.\n" ); streamer->is_buffering = FALSE; } if (!streamer->need_update) { debug_log ( "don't need to update buffering stats during buffering.\n" ); return; } /* Note : Parse the buffering message to get the in/out throughput. * avg_in is the network throughput and avg_out is the consumed throughtput by the linkded element. */ gst_message_parse_buffering_stats ( buffering_msg, &mode, &byte_in_rate, &byte_out_rate, &buffering_left ); if (streamer->buffer_max_bitrate > 0) { buffer_criteria = GET_BYTE_FROM_BIT(streamer->buffer_max_bitrate); byte_out_rate = GET_BYTE_FROM_BIT(streamer->buffer_max_bitrate /3); } else if (streamer->buffer_avg_bitrate > 0) { buffer_criteria = GET_BYTE_FROM_BIT(streamer->buffer_avg_bitrate * 3); byte_out_rate = GET_BYTE_FROM_BIT(streamer->buffer_avg_bitrate); } debug_log ( "in rate is %d, out rate is %d (bytes/sec).\n", byte_in_rate, byte_out_rate ); if ( byte_in_rate > 0 && byte_out_rate > 0) buffering_time = byte_out_rate / byte_in_rate; else if (byte_in_rate <= 0 && byte_out_rate > 0) buffering_time = MAX_BUFFERING_TIME; else buffering_time = DEFAULT_BUFFERING_TIME; streaming_set_buffering_time(streamer, buffering_time); /* calculate buffer low/high percent */ low_percent = DEFAULT_BUFFER_LOW_PERCENT; if ( buffer_criteria > 0 ) { high_percent_byte = buffer_criteria * streamer->buffering_time; high_percent = ( (gdouble)high_percent_byte * 100.0 ) / (gdouble)streamer->buffer_size; } else { high_percent_byte = streamer->buffer_high_percent * streamer->buffer_size / 100; high_percent= streamer->buffer_high_percent; } if ( streamer->buffer_size < high_percent_byte ) { debug_log ( "buffer size[%d bytes] is smaller than high threshold[%d bytes]. update it. \n", streamer->buffer_size, high_percent_byte ); streaming_set_buffer_size(streamer, high_percent_byte * 1.1); } streaming_set_buffer_percent(streamer, low_percent, high_percent); streamer->need_update = FALSE; return; }