GstBusSyncReply GstEnginePipeline::BusCallbackSync(GstBus*, GstMessage* msg,
                                                   gpointer self) {
  GstEnginePipeline* instance = reinterpret_cast<GstEnginePipeline*>(self);

  qLog(Debug) << instance->id() << "sync bus message"
              << GST_MESSAGE_TYPE_NAME(msg);

  switch (GST_MESSAGE_TYPE(msg)) {
    case GST_MESSAGE_EOS:
      emit instance->EndOfStreamReached(instance->id(), false);
      break;

    case GST_MESSAGE_TAG:
      instance->TagMessageReceived(msg);
      break;

    case GST_MESSAGE_ERROR:
      instance->ErrorMessageReceived(msg);
      break;

    case GST_MESSAGE_ELEMENT:
      instance->ElementMessageReceived(msg);
      break;

    case GST_MESSAGE_STATE_CHANGED:
      instance->StateChangedMessageReceived(msg);
      break;

    case GST_MESSAGE_BUFFERING:
      instance->BufferingMessageReceived(msg);
      break;

    case GST_MESSAGE_STREAM_STATUS:
      instance->StreamStatusMessageReceived(msg);
      break;

    case GST_MESSAGE_STREAM_START:
      if (instance->emit_track_ended_on_stream_start_) {
        qLog(Debug) << "New segment started, EOS will signal on next buffer "
                       "discontinuity";
        instance->emit_track_ended_on_stream_start_ = false;
        instance->emit_track_ended_on_time_discontinuity_ = true;
      }
      break;

    default:
      break;
  }

  return GST_BUS_PASS;
}
Beispiel #2
0
static void
do_post_message_pre (GstStatsTracer * self, guint64 ts, GstElement * elem,
    GstMessage * msg)
{
  GstElementStats *stats = get_element_stats (self, elem);
  const GstStructure *msg_s = gst_message_get_structure (msg);
  GstStructure *s =
      msg_s ? (GstStructure *) msg_s : gst_structure_new_empty ("dummy");

  stats->last_ts = ts;
  /* FIXME: work out whether using NULL instead of a dummy struct would work */
  gst_tracer_record_log (tr_message, (guint64) (guintptr) g_thread_self (), ts,
      stats->index, GST_MESSAGE_TYPE_NAME (msg), s);
  if (s != msg_s)
    gst_structure_free (s);
}
static gboolean my_bus_callback (GstBus *bus, GstMessage *message, gpointer data)
{
	g_print ("Got %s message\n", GST_MESSAGE_TYPE_NAME (message));

	switch (GST_MESSAGE_TYPE (message)) {
	case GST_MESSAGE_QOS:
		g_print("GST_MESSAGE_QOS\n");
		break;
	default:
		g_print("GST_MESSAGE_*\n");
		break;
	}

	/* we want to be notified again the next time there is a message
	 * on the bus, so returning TRUE (FALSE means we want to stop watching
	 * for messages on the bus and our callback should not be called again)
	 */
	return TRUE;
}
Beispiel #4
0
GstBusSyncReply GstEnginePipeline::BusCallbackSync(GstBus*, GstMessage* msg,
                                                   gpointer self) {
  GstEnginePipeline* instance = reinterpret_cast<GstEnginePipeline*>(self);

  qLog(Debug) << instance->id() << "sync bus message"
              << GST_MESSAGE_TYPE_NAME(msg);

  switch (GST_MESSAGE_TYPE(msg)) {
    case GST_MESSAGE_EOS:
      emit instance->EndOfStreamReached(instance->id(), false);
      break;

    case GST_MESSAGE_TAG:
      instance->TagMessageReceived(msg);
      break;

    case GST_MESSAGE_ERROR:
      instance->ErrorMessageReceived(msg);
      break;

    case GST_MESSAGE_ELEMENT:
      instance->ElementMessageReceived(msg);
      break;

    case GST_MESSAGE_STATE_CHANGED:
      instance->StateChangedMessageReceived(msg);
      break;

    case GST_MESSAGE_BUFFERING:
      instance->BufferingMessageReceived(msg);
      break;

    case GST_MESSAGE_STREAM_STATUS:
      instance->StreamStatusMessageReceived(msg);
      break;

    default:
      break;
  }

  return GST_BUS_PASS;
}
gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpointer data)
{
    GOwnPtr<GError> err;
    GOwnPtr<gchar> debug;
    MediaPlayer::NetworkState error;
    MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data);
    gint percent = 0;

    switch (GST_MESSAGE_TYPE(message)) {
    case GST_MESSAGE_ERROR:
        gst_message_parse_error(message, &err.outPtr(), &debug.outPtr());
        LOG_VERBOSE(Media, "Error: %d, %s", err->code,  err->message);

        error = MediaPlayer::Empty;
        if (err->domain == GST_CORE_ERROR || err->domain == GST_LIBRARY_ERROR)
            error = MediaPlayer::DecodeError;
        else if (err->domain == GST_RESOURCE_ERROR)
            error = MediaPlayer::FormatError;
        else if (err->domain == GST_STREAM_ERROR)
            error = MediaPlayer::NetworkError;

        if (mp)
            mp->loadingFailed(error);
        break;
    case GST_MESSAGE_EOS:
        LOG_VERBOSE(Media, "End of Stream");
        mp->didEnd();
        break;
    case GST_MESSAGE_STATE_CHANGED:
        mp->updateStates();
        break;
    case GST_MESSAGE_BUFFERING:
        gst_message_parse_buffering(message, &percent);
        LOG_VERBOSE(Media, "Buffering %d", percent);
        break;
    default:
        LOG_VERBOSE(Media, "Unhandled GStreamer message type: %s",
                    GST_MESSAGE_TYPE_NAME(message));
        break;
    }
    return true;
}
Beispiel #6
0
static void
do_post_message_pre (GstStatsTracer * self, guint64 ts, GstElement * elem,
    GstMessage * msg)
{
  GstElementStats *stats = get_element_stats (self, elem);
  const GstStructure *msg_s = gst_message_get_structure (msg);
  GstStructure *s;

  stats->last_ts = ts;

  s = gst_structure_new ("message",
      "thread-id", G_TYPE_UINT, GPOINTER_TO_UINT (g_thread_self ()),
      "ts", G_TYPE_UINT64, ts,
      "elem-ix", G_TYPE_UINT, stats->index,
      "name", G_TYPE_STRING, GST_MESSAGE_TYPE_NAME (msg), NULL);
  if (msg_s) {
    gst_structure_set (s, "structure", GST_TYPE_STRUCTURE, msg_s, NULL);
  }
  gst_tracer_log_trace (s);
}
Beispiel #7
0
static gboolean mybusfunc(GstBus *bus, GstMessage *message, gpointer user_data)
{
	GMainLoop *loop = (GMainLoop *) user_data;
	GstState prev_state, curr_state;
	GError *err = NULL;
	gchar *debug_info = NULL;

	g_print("Got %s\n", GST_MESSAGE_TYPE_NAME(message));

	switch (GST_MESSAGE_TYPE(message)) {
		case GST_MESSAGE_EOS:
			g_print("End of stream\n");
			g_main_loop_quit(loop);
			break;

		case GST_MESSAGE_ERROR:
			gst_message_parse_error(message, &err, &debug_info);
			g_printerr("Error from element %s: %s\n", GST_OBJECT_NAME(message->src), err->message);
			g_printerr("Debugging info: %s\n", (debug_info) ? debug_info : "none");
			g_error_free(err);
			g_free(debug_info);
			g_main_loop_quit(loop);
			break;

		case GST_MESSAGE_STATE_CHANGED:
			gst_message_parse_state_changed(message, &prev_state, &curr_state, NULL);
			g_print("Element %s changed from %s to %s\n", 
				GST_OBJECT_NAME(message->src), 
				gst_element_state_get_name(prev_state),
				gst_element_state_get_name(curr_state));
			break;

		default:
			g_print("Unhandled messages");
			break;
	}

	g_print("\n");

	return TRUE;
}
Beispiel #8
0
void media_bus_message(GstBus     *bus,
                              GstMessage *message,
                              gpointer    user_data) {
  switch (GST_MESSAGE_TYPE (message)) {
  case GST_MESSAGE_ERROR: {
    GError *err = NULL;
    gchar *dbg = NULL;
    gst_message_parse_error(message, &err, &dbg);
    if (err) {
      g_error("RTSP Pipeline ERROR: %s", err->message);
      g_error_free(err);
    }
    if (dbg) {
      g_message("Debug details: %s", dbg);
      g_free(dbg);
    }
    break;
  }
    /*
  case GST_MESSAGE_STATE_CHANGED:
  case GST_MESSAGE_STREAM_STATUS:
  case GST_MESSAGE_TAG:
  case GST_MESSAGE_NEW_CLOCK: {
    // Ignore
    break;
  }
    */
  default: {
    const GstStructure* mstruct = gst_message_get_structure(message);
    char* struct_info =
      mstruct ? gst_structure_to_string(mstruct) : g_strdup("no-struct");
    g_message("RTSP bus Message '%s' from '%s': %s",
              GST_MESSAGE_TYPE_NAME(message),
              GST_MESSAGE_SRC_NAME(message),
              struct_info);
    g_free(struct_info);
    break;
  }
  }
}
gboolean GstEnginePipeline::BusCallback(GstBus*, GstMessage* msg, gpointer self) {
    GstEnginePipeline* instance = reinterpret_cast<GstEnginePipeline*>(self);

    qLog(Debug) << instance->id() << "bus message" << GST_MESSAGE_TYPE_NAME(msg);

    switch (GST_MESSAGE_TYPE(msg)) {
    case GST_MESSAGE_ERROR:
        instance->ErrorMessageReceived(msg);
        break;

    case GST_MESSAGE_TAG:
        instance->TagMessageReceived(msg);
        break;

    case GST_MESSAGE_STATE_CHANGED:
        instance->StateChangedMessageReceived(msg);
        break;

    default:
        break;
    }

    return FALSE;
}
Beispiel #10
0
void QGstreamerGLTextureRenderer::handleBusMessage(GstMessage* gm)
{
#ifdef GL_TEXTURE_SINK_DEBUG
    qDebug() << Q_FUNC_INFO << GST_MESSAGE_TYPE_NAME(gm);
#endif

    if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_STATE_CHANGED) {
        GstState oldState;
        GstState newState;
        gst_message_parse_state_changed(gm, &oldState, &newState, 0);

#ifdef GL_TEXTURE_SINK_DEBUG
        qDebug() << Q_FUNC_INFO << "State changed:" << oldState << newState;
#endif

        if (newState == GST_STATE_READY || newState == GST_STATE_NULL) {
            stopRenderer();
        }

        if (oldState == GST_STATE_READY && newState == GST_STATE_PAUSED) {
            updateNativeVideoSize();
        }
    }
}
Beispiel #11
0
static void
do_perfect_stream_test (guint rate, guint width, gdouble drop_probability,
    gdouble inject_probability)
{
  GstElement *pipe, *src, *conv, *filter, *injector, *audiorate, *sink;
  GstMessage *msg;
  GstCaps *caps;
  GstPad *srcpad;
  GList *l, *bufs = NULL;
  GstClockTime next_time = GST_CLOCK_TIME_NONE;
  guint64 next_offset = GST_BUFFER_OFFSET_NONE;

  caps = gst_caps_new_simple ("audio/x-raw-int", "rate", G_TYPE_INT,
      rate, "width", G_TYPE_INT, width, NULL);

  GST_INFO ("-------- drop=%.0f%% caps = %" GST_PTR_FORMAT " ---------- ",
      drop_probability * 100.0, caps);

  g_assert (drop_probability >= 0.0 && drop_probability <= 1.0);
  g_assert (inject_probability >= 0.0 && inject_probability <= 1.0);
  g_assert (width > 0 && (width % 8) == 0);

  pipe = gst_pipeline_new ("pipeline");
  fail_unless (pipe != NULL);

  src = gst_element_factory_make ("audiotestsrc", "audiotestsrc");
  fail_unless (src != NULL);

  g_object_set (src, "num-buffers", 100, NULL);

  

  conv = gst_element_factory_make ("audioconvert", "audioconvert");
  fail_unless (conv != NULL);

  filter = gst_element_factory_make ("capsfilter", "capsfilter");

   fail_unless (filter != NULL);
   g_object_set (filter, "caps", caps, NULL);

  injector_inject_probability = inject_probability;
  injector = GST_ELEMENT (g_object_new (test_injector_get_type (), NULL));

  srcpad = gst_element_get_pad (injector, "src");
  fail_unless (srcpad != NULL);
   gst_pad_add_buffer_probe (srcpad, G_CALLBACK (probe_cb), &drop_probability);
  gst_object_unref (srcpad);
         audiorate = gst_element_factory_make ("audiorate", "audiorate");
         fail_unless (audiorate != NULL);
   sink = gst_element_factory_make ("fakesink", "fakesink");
  fail_unless (sink != NULL);
   g_object_set (sink, "signal-handoffs", TRUE, NULL);
   g_signal_connect (sink, "handoff", G_CALLBACK (got_buf), &bufs);

  gst_bin_add_many (GST_BIN (pipe), src, conv, filter, injector, audiorate,
      sink, NULL);
  gst_element_link_many (src, conv, filter, injector, audiorate, sink, NULL);

  fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_PLAYING),
      GST_STATE_CHANGE_ASYNC);

  fail_unless_equals_int (gst_element_get_state (pipe, NULL, NULL, -1),
      GST_STATE_CHANGE_SUCCESS);

  msg = gst_bus_poll (GST_ELEMENT_BUS (pipe),
      GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1);
  fail_unless_equals_string (GST_MESSAGE_TYPE_NAME (msg), "eos");

  for (l = bufs; l != NULL; l = l->next) {
    GstBuffer *buf = GST_BUFFER (l->data);
    guint num_samples;

    fail_unless (GST_BUFFER_TIMESTAMP_IS_VALID (buf));
    fail_unless (GST_BUFFER_DURATION_IS_VALID (buf));
    fail_unless (GST_BUFFER_OFFSET_IS_VALID (buf));
    fail_unless (GST_BUFFER_OFFSET_END_IS_VALID (buf));

    GST_LOG ("buffer: ts=%" GST_TIME_FORMAT ", end_ts=%" GST_TIME_FORMAT
        " off=%" G_GINT64_FORMAT ", end_off=%" G_GINT64_FORMAT,
        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf)),
        GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf));

    if (GST_CLOCK_TIME_IS_VALID (next_time)) {
      fail_unless_equals_uint64 (next_time, GST_BUFFER_TIMESTAMP (buf));
    }
    if (next_offset != GST_BUFFER_OFFSET_NONE) {
      fail_unless_equals_uint64 (next_offset, GST_BUFFER_OFFSET (buf));
    }

    /* check buffer size for sanity */
    fail_unless_equals_int (GST_BUFFER_SIZE (buf) % (width / 8), 0);

    /* check there is actually as much data as there should be */
    num_samples = GST_BUFFER_OFFSET_END (buf) - GST_BUFFER_OFFSET (buf);
    fail_unless_equals_int (GST_BUFFER_SIZE (buf), num_samples * (width / 8));

    next_time = GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf);
    next_offset = GST_BUFFER_OFFSET_END (buf);
  }

  gst_message_unref (msg);
  gst_element_set_state (pipe, GST_STATE_NULL);
  gst_object_unref (pipe);

  g_list_foreach (bufs, (GFunc) gst_mini_object_unref, NULL);
  g_list_free (bufs);

  gst_caps_unref (caps);
}
static void
gst_alloc_trace_print (const GstAllocTrace * trace)
{
  GSList *mem_live;

  g_return_if_fail (trace != NULL);

  if (trace->flags & GST_ALLOC_TRACE_LIVE) {
    g_print ("%-22.22s : %d\n", trace->name, trace->live);
  } else {
    g_print ("%-22.22s : (no live count)\n", trace->name);
  }

  if (trace->flags & GST_ALLOC_TRACE_MEM_LIVE) {
    mem_live = trace->mem_live;

    while (mem_live) {
      gpointer data = mem_live->data;
      const gchar *type_name;
      gchar *extra = NULL;
      gint refcount = -1;

      if (trace->offset == -2) {
        if (G_IS_OBJECT (data)) {
          type_name = G_OBJECT_TYPE_NAME (data);
          refcount = G_OBJECT (data)->ref_count;
        } else
          type_name = "<invalid>";
      } else if (trace->offset == -1) {
        type_name = "<unknown>";
      } else {
        GType type;

        type = G_STRUCT_MEMBER (GType, data, trace->offset);
        type_name = g_type_name (type);

        if (type == GST_TYPE_CAPS) {
          extra = gst_caps_to_string (data);
        } else if (type == GST_TYPE_EVENT) {
          const GstStructure *s = gst_event_get_structure (data);

          if (s == NULL)
            extra = g_strdup_printf ("%s", GST_EVENT_TYPE_NAME (data));
          else
            extra = gst_structure_to_string (s);
        } else if (type == GST_TYPE_MESSAGE) {
          const GstStructure *s = gst_message_get_structure (data);

          if (s == NULL)
            extra = g_strdup_printf ("%s", GST_MESSAGE_TYPE_NAME (data));
          else
            extra = gst_structure_to_string (s);
        } else if (type == GST_TYPE_BUFFER) {
          guint size = gst_buffer_get_size (data);

          extra = g_strdup_printf ("%u bytes", size);
        } else if (type == GST_TYPE_MEMORY) {
          GstMemory *mem = (GstMemory *) data;

          extra = g_strdup_printf ("%u bytes, %s allocator", (guint) mem->size,
              mem->allocator ? mem->allocator->mem_type : "unknown");
        }
        refcount = GST_MINI_OBJECT_REFCOUNT_VALUE (data);
      }

      if (extra) {
        g_print ("  %-20.20s : (%d) %p (\"%s\")\n", type_name, refcount, data,
            extra);
        g_free (extra);
      } else
        g_print ("  %-20.20s : (%d) %p\n", type_name, refcount, data);

      mem_live = mem_live->next;
    }
  }
}
Beispiel #13
0
/**
 * gst_bus_timed_pop_filtered:
 * @bus: a #GstBus to pop from
 * @timeout: a timeout in nanoseconds, or GST_CLOCK_TIME_NONE to wait forever
 * @types: message types to take into account, GST_MESSAGE_ANY for any type
 *
 * Get a message from the bus whose type matches the message type mask @types,
 * waiting up to the specified timeout (and discarding any messages that do not
 * match the mask provided).
 *
 * If @timeout is 0, this function behaves like gst_bus_pop_filtered(). If
 * @timeout is #GST_CLOCK_TIME_NONE, this function will block forever until a
 * matching message was posted on the bus.
 *
 * Returns: a #GstMessage matching the filter in @types, or NULL if no matching
 * message was found on the bus until the timeout expired.
 * The message is taken from the bus and needs to be unreffed with
 * gst_message_unref() after usage.
 *
 * MT safe.
 *
 * Since: 0.10.15
 */
GstMessage *
gst_bus_timed_pop_filtered (GstBus * bus, GstClockTime timeout,
    GstMessageType types)
{
  GstMessage *message;
  GTimeVal *timeval, abstimeout;
  gboolean first_round = TRUE;

  g_return_val_if_fail (GST_IS_BUS (bus), NULL);
  g_return_val_if_fail (types != 0, NULL);

  g_mutex_lock (bus->queue_lock);

  while (TRUE) {
    GST_LOG_OBJECT (bus, "have %d messages", g_queue_get_length (bus->queue));

    while ((message = g_queue_pop_head (bus->queue))) {
      GST_DEBUG_OBJECT (bus, "got message %p, %s, type mask is %u",
          message, GST_MESSAGE_TYPE_NAME (message), (guint) types);
      if ((GST_MESSAGE_TYPE (message) & types) != 0) {
        /* exit the loop, we have a message */
        goto beach;
      } else {
        GST_DEBUG_OBJECT (bus, "discarding message, does not match mask");
        gst_message_unref (message);
        message = NULL;
      }
    }

    /* no need to wait, exit loop */
    if (timeout == 0)
      break;

    if (timeout == GST_CLOCK_TIME_NONE) {
      /* wait forever */
      timeval = NULL;
    } else if (first_round) {
      glong add = timeout / 1000;

      if (add == 0)
        /* no need to wait */
        break;

      /* make timeout absolute */
      g_get_current_time (&abstimeout);
      g_time_val_add (&abstimeout, add);
      timeval = &abstimeout;
      first_round = FALSE;
      GST_DEBUG_OBJECT (bus, "blocking for message, timeout %ld", add);
    } else {
      /* calculated the absolute end time already, no need to do it again */
      GST_DEBUG_OBJECT (bus, "blocking for message, again");
      timeval = &abstimeout;    /* fool compiler */
    }
    if (!g_cond_timed_wait (bus->priv->queue_cond, bus->queue_lock, timeval)) {
      GST_INFO_OBJECT (bus, "timed out, breaking loop");
      break;
    } else {
      GST_INFO_OBJECT (bus, "we got woken up, recheck for message");
    }
  }

beach:

  g_mutex_unlock (bus->queue_lock);

  return message;
}
Beispiel #14
0
/**
 * 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;
  }
}
Beispiel #15
0
void eServiceMP3::gstBusCall(GstMessage *msg)
{
	if (!msg)
		return;
	gchar *sourceName;
	GstObject *source;
	source = GST_MESSAGE_SRC(msg);
	if (!GST_IS_OBJECT(source))
		return;
	sourceName = gst_object_get_name(source);
#if 0
	gchar *string;
	if (gst_message_get_structure(msg))
		string = gst_structure_to_string(gst_message_get_structure(msg));
	else
		string = g_strdup(GST_MESSAGE_TYPE_NAME(msg));
	eDebug("eTsRemoteSource::gst_message from %s: %s", sourceName, string);
	g_free(string);
#endif
	switch (GST_MESSAGE_TYPE (msg))
	{
		case GST_MESSAGE_EOS:
			m_event((iPlayableService*)this, evEOF);
			break;
		case GST_MESSAGE_STATE_CHANGED:
		{
			if(GST_MESSAGE_SRC(msg) != GST_OBJECT(m_gst_playbin))
				break;

			GstState old_state, new_state;
			gst_message_parse_state_changed(msg, &old_state, &new_state, NULL);
		
			if(old_state == new_state)
				break;
	
			eDebug("eServiceMP3::state transition %s -> %s", gst_element_state_get_name(old_state), gst_element_state_get_name(new_state));
	
			GstStateChange transition = (GstStateChange)GST_STATE_TRANSITION(old_state, new_state);
	
			switch(transition)
			{
				case GST_STATE_CHANGE_NULL_TO_READY:
				{
				}	break;
				case GST_STATE_CHANGE_READY_TO_PAUSED:
				{
					GstElement *subsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink");
					if (subsink)
					{
#ifdef GSTREAMER_SUBTITLE_SYNC_MODE_BUG
						/* 
						 * HACK: disable sync mode for now, gstreamer suffers from a bug causing sparse streams to loose sync, after pause/resume / skip
						 * see: https://bugzilla.gnome.org/show_bug.cgi?id=619434
						 * Sideeffect of using sync=false is that we receive subtitle buffers (far) ahead of their
						 * display time.
						 * Not too far ahead for subtitles contained in the media container.
						 * But for external srt files, we could receive all subtitles at once.
						 * And not just once, but after each pause/resume / skip.
						 * So as soon as gstreamer has been fixed to keep sync in sparse streams, sync needs to be re-enabled.
						 */
						g_object_set (G_OBJECT (subsink), "sync", FALSE, NULL);
#endif
#if 0
						/* we should not use ts-offset to sync with the decoder time, we have to do our own decoder timekeeping */
						g_object_set (G_OBJECT (subsink), "ts-offset", -2L * GST_SECOND, NULL);
						/* late buffers probably will not occur very often */
						g_object_set (G_OBJECT (subsink), "max-lateness", 0L, NULL);
						/* avoid prerolling (it might not be a good idea to preroll a sparse stream) */
						g_object_set (G_OBJECT (subsink), "async", TRUE, NULL);
#endif
						eDebug("eServiceMP3::subsink properties set!");
						gst_object_unref(subsink);
					}
					setAC3Delay(ac3_delay);
					setPCMDelay(pcm_delay);
				}	break;
				case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
				{
					if ( m_sourceinfo.is_streaming && m_streamingsrc_timeout )
						m_streamingsrc_timeout->stop();
				}	break;
				case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
				{
				}	break;
				case GST_STATE_CHANGE_PAUSED_TO_READY:
				{
				}	break;
				case GST_STATE_CHANGE_READY_TO_NULL:
				{
				}	break;
			}
			break;
		}
		case GST_MESSAGE_ERROR:
		{
			gchar *debug;
			GError *err;
			gst_message_parse_error (msg, &err, &debug);
			g_free (debug);
			eWarning("Gstreamer error: %s (%i) from %s", err->message, err->code, sourceName );
			if ( err->domain == GST_STREAM_ERROR )
			{
				if ( err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND )
				{
					if ( g_strrstr(sourceName, "videosink") )
						m_event((iPlayableService*)this, evUser+11);
					else if ( g_strrstr(sourceName, "audiosink") )
						m_event((iPlayableService*)this, evUser+10);
				}
			}
			g_error_free(err);
			break;
		}
		case GST_MESSAGE_INFO:
		{
			gchar *debug;
			GError *inf;
	
			gst_message_parse_info (msg, &inf, &debug);
			g_free (debug);
			if ( inf->domain == GST_STREAM_ERROR && inf->code == GST_STREAM_ERROR_DECODE )
			{
				if ( g_strrstr(sourceName, "videosink") )
					m_event((iPlayableService*)this, evUser+14);
			}
			g_error_free(inf);
			break;
		}
		case GST_MESSAGE_TAG:
		{
			GstTagList *tags, *result;
			gst_message_parse_tag(msg, &tags);
	
			result = gst_tag_list_merge(m_stream_tags, tags, GST_TAG_MERGE_REPLACE);
			if (result)
			{
				if (m_stream_tags)
					gst_tag_list_free(m_stream_tags);
				m_stream_tags = result;
			}
	
			const GValue *gv_image = gst_tag_list_get_value_index(tags, GST_TAG_IMAGE, 0);
			if ( gv_image )
			{
				GstBuffer *buf_image;
				buf_image = gst_value_get_buffer (gv_image);
				int fd = open("/tmp/.id3coverart", O_CREAT|O_WRONLY|O_TRUNC, 0644);
				int ret = write(fd, GST_BUFFER_DATA(buf_image), GST_BUFFER_SIZE(buf_image));
				close(fd);
				eDebug("eServiceMP3::/tmp/.id3coverart %d bytes written ", ret);
				m_event((iPlayableService*)this, evUser+13);
			}
			gst_tag_list_free(tags);
			m_event((iPlayableService*)this, evUpdatedInfo);
			break;
		}
		case GST_MESSAGE_ASYNC_DONE:
		{
			if(GST_MESSAGE_SRC(msg) != GST_OBJECT(m_gst_playbin))
				break;

			GstTagList *tags;
			gint i, active_idx, n_video = 0, n_audio = 0, n_text = 0;

			g_object_get (m_gst_playbin, "n-video", &n_video, NULL);
			g_object_get (m_gst_playbin, "n-audio", &n_audio, NULL);
			g_object_get (m_gst_playbin, "n-text", &n_text, NULL);

			eDebug("eServiceMP3::async-done - %d video, %d audio, %d subtitle", n_video, n_audio, n_text);

			if ( n_video + n_audio <= 0 )
				stop();

			active_idx = 0;

			m_audioStreams.clear();
			m_subtitleStreams.clear();

			for (i = 0; i < n_audio; i++)
			{
				audioStream audio;
				gchar *g_codec, *g_lang;
				GstPad* pad = 0;
				g_signal_emit_by_name (m_gst_playbin, "get-audio-pad", i, &pad);
				GstCaps* caps = gst_pad_get_negotiated_caps(pad);
				if (!caps)
					continue;
				GstStructure* str = gst_caps_get_structure(caps, 0);
				const gchar *g_type = gst_structure_get_name(str);
				eDebug("AUDIO STRUCT=%s", g_type);
				audio.type = gstCheckAudioPad(str);
				g_codec = g_strdup(g_type);
				g_lang = g_strdup_printf ("und");
				g_signal_emit_by_name (m_gst_playbin, "get-audio-tags", i, &tags);
				if ( tags && gst_is_tag_list(tags) )
				{
					gst_tag_list_get_string(tags, GST_TAG_AUDIO_CODEC, &g_codec);
					gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang);
					gst_tag_list_free(tags);
				}
				audio.language_code = std::string(g_lang);
				audio.codec = std::string(g_codec);
				eDebug("eServiceMP3::audio stream=%i codec=%s language=%s", i, g_codec, g_lang);
				m_audioStreams.push_back(audio);
				g_free (g_lang);
				g_free (g_codec);
				gst_caps_unref(caps);
			}

			for (i = 0; i < n_text; i++)
			{	
				gchar *g_codec = NULL, *g_lang = NULL;
				g_signal_emit_by_name (m_gst_playbin, "get-text-tags", i, &tags);
				subtitleStream subs;

				g_lang = g_strdup_printf ("und");
				if ( tags && gst_is_tag_list(tags) )
				{
					gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang);
					gst_tag_list_get_string(tags, GST_TAG_SUBTITLE_CODEC, &g_codec);
					gst_tag_list_free(tags);
				}

				subs.language_code = std::string(g_lang);
				eDebug("eServiceMP3::subtitle stream=%i language=%s codec=%s", i, g_lang, g_codec);
				
				GstPad* pad = 0;
				g_signal_emit_by_name (m_gst_playbin, "get-text-pad", i, &pad);
				if ( pad )
					g_signal_connect (G_OBJECT (pad), "notify::caps", G_CALLBACK (gstTextpadHasCAPS), this);
				subs.type = getSubtitleType(pad, g_codec);

				m_subtitleStreams.push_back(subs);
				g_free (g_lang);
			}
			m_event((iPlayableService*)this, evUpdatedInfo);

			if ( m_errorInfo.missing_codec != "" )
			{
				if ( m_errorInfo.missing_codec.find("video/") == 0 || ( m_errorInfo.missing_codec.find("audio/") == 0 && getNumberOfTracks() == 0 ) )
					m_event((iPlayableService*)this, evUser+12);
			}
			break;
		}
		case GST_MESSAGE_ELEMENT:
		{
			if (const GstStructure *msgstruct = gst_message_get_structure(msg))
			{
				if ( gst_is_missing_plugin_message(msg) )
				{
					GstCaps *caps;
					gst_structure_get (msgstruct, "detail", GST_TYPE_CAPS, &caps, NULL); 
					std::string codec = (const char*) gst_caps_to_string(caps);
					gchar *description = gst_missing_plugin_message_get_description(msg);
					if ( description )
					{
						eDebug("eServiceMP3::m_errorInfo.missing_codec = %s", codec.c_str());
						m_errorInfo.error_message = "GStreamer plugin " + (std::string)description + " not available!\n";
						m_errorInfo.missing_codec = codec.substr(0,(codec.find_first_of(',')));
						g_free(description);
					}
					gst_caps_unref(caps);
				}
				else
				{
					const gchar *eventname = gst_structure_get_name(msgstruct);
					if ( eventname )
					{
						if (!strcmp(eventname, "eventSizeChanged") || !strcmp(eventname, "eventSizeAvail"))
						{
							gst_structure_get_int (msgstruct, "aspect_ratio", &m_aspect);
							gst_structure_get_int (msgstruct, "width", &m_width);
							gst_structure_get_int (msgstruct, "height", &m_height);
							if (strstr(eventname, "Changed"))
								m_event((iPlayableService*)this, evVideoSizeChanged);
						}
						else if (!strcmp(eventname, "eventFrameRateChanged") || !strcmp(eventname, "eventFrameRateAvail"))
						{
							gst_structure_get_int (msgstruct, "frame_rate", &m_framerate);
							if (strstr(eventname, "Changed"))
								m_event((iPlayableService*)this, evVideoFramerateChanged);
						}
						else if (!strcmp(eventname, "eventProgressiveChanged") || !strcmp(eventname, "eventProgressiveAvail"))
						{
							gst_structure_get_int (msgstruct, "progressive", &m_progressive);
							if (strstr(eventname, "Changed"))
								m_event((iPlayableService*)this, evVideoProgressiveChanged);
						}
					}
				}
			}
			break;
		}
		case GST_MESSAGE_BUFFERING:
		{
			GstBufferingMode mode;
			gst_message_parse_buffering(msg, &(m_bufferInfo.bufferPercent));
			gst_message_parse_buffering_stats(msg, &mode, &(m_bufferInfo.avgInRate), &(m_bufferInfo.avgOutRate), &(m_bufferInfo.bufferingLeft));
			m_event((iPlayableService*)this, evBuffering);
			break;
		}
		case GST_MESSAGE_STREAM_STATUS:
		{
			GstStreamStatusType type;
			GstElement *owner;
			gst_message_parse_stream_status (msg, &type, &owner);
			if ( type == GST_STREAM_STATUS_TYPE_CREATE && m_sourceinfo.is_streaming )
			{
				if ( GST_IS_PAD(source) )
					owner = gst_pad_get_parent_element(GST_PAD(source));
				else if ( GST_IS_ELEMENT(source) )
					owner = GST_ELEMENT(source);
				else
					owner = 0;
				if ( owner )
				{
					GstElementFactory *factory = gst_element_get_factory(GST_ELEMENT(owner));
					const gchar *name = gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(factory));
					if (!strcmp(name, "souphttpsrc"))
					{
						m_streamingsrc_timeout->start(HTTP_TIMEOUT*1000, true);
						g_object_set (G_OBJECT (owner), "timeout", HTTP_TIMEOUT, NULL);
						eDebug("eServiceMP3::GST_STREAM_STATUS_TYPE_CREATE -> setting timeout on %s to %is", name, HTTP_TIMEOUT);
					}
					
				}
				if ( GST_IS_PAD(source) )
					gst_object_unref(owner);
			}
			break;
		}
		default:
			break;
	}
	g_free (sourceName);
}
Beispiel #16
0
void ofGstUtils::gstHandleMessage(){
	GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(gstPipeline));
	while(gst_bus_have_pending(bus)) {
		GstMessage* msg = gst_bus_pop(bus);
		if(appsink && appsink->on_message(msg)) continue;

		ofLog(OF_LOG_VERBOSE,"GStreamer: Got %s message", GST_MESSAGE_TYPE_NAME(msg));

		switch (GST_MESSAGE_TYPE (msg)) {

			case GST_MESSAGE_BUFFERING:
				gint pctBuffered;
				gst_message_parse_buffering(msg,&pctBuffered);
				ofLog(OF_LOG_VERBOSE,"GStreamer: buffering %i\%", pctBuffered);
				if(isStream && !bLoaded && appsink){
					appsink->on_stream_prepared();
				}
				if(pctBuffered<100){
					gst_element_set_state (gstPipeline, GST_STATE_PAUSED);
				}else if(!bPaused){
					gst_element_set_state (gstPipeline, GST_STATE_PLAYING);
				}
			break;

			case GST_MESSAGE_DURATION:{
				GstFormat format=GST_FORMAT_TIME;
				gst_element_query_duration(gstPipeline,&format,&durationNanos);
			}break;

			case GST_MESSAGE_STATE_CHANGED:{
				GstState oldstate, newstate, pendstate;
				gst_message_parse_state_changed(msg, &oldstate, &newstate, &pendstate);
				if(isStream && !bLoaded && appsink){
					appsink->on_stream_prepared();
				}
				/*seek_lock();
				if(posChangingPaused && newstate==GST_STATE_PLAYING){
					gst_element_set_state (gstPipeline, GST_STATE_PAUSED);
					posChangingPaused=false;
				}
				seek_unlock();*/

				ofLog(OF_LOG_VERBOSE,"GStreamer: state changed from " + getName(oldstate) + " to " + getName(newstate) + " (" + getName(pendstate) + ")");
			}break;

			case GST_MESSAGE_ASYNC_DONE:
				ofLog(OF_LOG_VERBOSE,"GStreamer: async done");
			break;

			case GST_MESSAGE_ERROR: {
				GError *err;
				gchar *debug;
				gst_message_parse_error(msg, &err, &debug);

				ofLog(OF_LOG_ERROR, "GStreamer Plugin: Embedded video playback halted; module %s reported: %s",
					  gst_element_get_name(GST_MESSAGE_SRC (msg)), err->message);

				g_error_free(err);
				g_free(debug);

				gst_element_set_state(GST_ELEMENT(gstPipeline), GST_STATE_NULL);

			}break;

			case GST_MESSAGE_EOS:
				ofLog(OF_LOG_VERBOSE,"GStreamer: end of the stream.");
				bIsMovieDone = true;

				switch(loopMode){

					case OF_LOOP_NORMAL:{
						GstFormat format = GST_FORMAT_TIME;
						GstSeekFlags flags = (GstSeekFlags) (GST_SEEK_FLAG_FLUSH |GST_SEEK_FLAG_KEY_UNIT);
						gint64 pos;
						gst_element_query_position(GST_ELEMENT(gstPipeline),&format,&pos);

						float loopSpeed;
						if(pos>0)
							loopSpeed=-speed;
						else
							loopSpeed=speed;
						if(!gst_element_seek(GST_ELEMENT(gstPipeline),
											speed,
											format,
											flags,
											GST_SEEK_TYPE_SET,
											0,
											GST_SEEK_TYPE_SET,
											durationNanos)) {
							ofLog(OF_LOG_WARNING,"GStreamer: unable to seek");
						}
					}break;

					case OF_LOOP_PALINDROME:{
						GstFormat format = GST_FORMAT_TIME;
						GstSeekFlags flags = (GstSeekFlags) (GST_SEEK_FLAG_FLUSH |GST_SEEK_FLAG_KEY_UNIT);
						gint64 pos;
						gst_element_query_position(GST_ELEMENT(gstPipeline),&format,&pos);
						float loopSpeed;
						if(pos>0)
							loopSpeed=-speed;
						else
							loopSpeed=speed;
						if(!gst_element_seek(GST_ELEMENT(gstPipeline),
											loopSpeed,
											GST_FORMAT_UNDEFINED,
											flags,
											GST_SEEK_TYPE_NONE,
											0,
											GST_SEEK_TYPE_NONE,
											0)) {
							ofLog(OF_LOG_WARNING,"GStreamer: unable to seek");
						}
					}break;

					default:
					break;
				}

			break;

			default:
				ofLog(OF_LOG_VERBOSE,"GStreamer: unhandled message");
			break;
		}
		gst_message_unref(msg);
	}

	gst_object_unref(GST_OBJECT(bus));
}
Beispiel #17
0
bool ofGstUtils::gstHandleMessage(GstBus * bus, GstMessage * msg){
	if(appsink && appsink->on_message(msg)) return true;

		ofLogVerbose("ofGstUtils") << "gstHandleMessage(): got " << GST_MESSAGE_TYPE_NAME(msg)
			<< " message from " << GST_MESSAGE_SRC_NAME(msg);

	switch (GST_MESSAGE_TYPE (msg)) {

		case GST_MESSAGE_BUFFERING:
			gint pctBuffered;
			gst_message_parse_buffering(msg,&pctBuffered);
			ofLogVerbose("ofGstUtils") << "gstHandleMessage(): buffering " << pctBuffered;
			/*if(pctBuffered<100){
				gst_element_set_state (gstPipeline, GST_STATE_PAUSED);
			}else if(!bPaused){
				gst_element_set_state (gstPipeline, GST_STATE_PLAYING);
			}*/
		break;

#if GST_VERSION_MAJOR==0
		case GST_MESSAGE_DURATION:{
			GstFormat format=GST_FORMAT_TIME;
			gst_element_query_duration(gstPipeline,&format,&durationNanos);
		}break;
#else
		case GST_MESSAGE_DURATION_CHANGED:
			gst_element_query_duration(gstPipeline,GST_FORMAT_TIME,&durationNanos);
			break;

#endif

		case GST_MESSAGE_STATE_CHANGED:{
			GstState oldstate, newstate, pendstate;
			gst_message_parse_state_changed(msg, &oldstate, &newstate, &pendstate);
			if(isStream && newstate==GST_STATE_PAUSED && !bPlaying ){
				bLoaded = true;
				bPlaying = true;
				if(!bPaused){
					ofLogVerbose("ofGstUtils") << "gstHandleMessage(): setting stream pipeline to play";
					play();
				}
			}

			ofLogVerbose("ofGstUtils") << "gstHandleMessage(): " << GST_MESSAGE_SRC_NAME(msg) << " state changed from "
					<< getName(oldstate) << " to " << getName(newstate) << " (" + getName(pendstate) << ")";
		}break;

		case GST_MESSAGE_ASYNC_DONE:
			ofLogVerbose("ofGstUtils") << "gstHandleMessage(): async done";
		break;

		case GST_MESSAGE_ERROR: {
			GError *err;
			gchar *debug;
			gst_message_parse_error(msg, &err, &debug);

			ofLogVerbose("ofGstUtils") << "gstHandleMessage(): embedded video playback halted for plugin, module "
				<< gst_element_get_name(GST_MESSAGE_SRC (msg)) << "  reported: " << err->message;

			g_error_free(err);
			g_free(debug);

			gst_element_set_state(GST_ELEMENT(gstPipeline), GST_STATE_NULL);

		}break;

			case GST_MESSAGE_EOS:
				ofLogVerbose("ofGstUtils") << "gstHandleMessage(): end of the stream";
				bIsMovieDone = true;


			if(appsink && !isAppSink) appsink->on_eos();

			switch(loopMode){

				case OF_LOOP_NORMAL:{
					GstFormat format = GST_FORMAT_TIME;
					GstSeekFlags flags = (GstSeekFlags) (GST_SEEK_FLAG_FLUSH |GST_SEEK_FLAG_KEY_UNIT);
					gint64 pos;
#if GST_VERSION_MAJOR==0
					gst_element_query_position(GST_ELEMENT(gstPipeline),&format,&pos);
#else
					gst_element_query_position(GST_ELEMENT(gstPipeline),format,&pos);
#endif
					if(!gst_element_seek(GST_ELEMENT(gstPipeline),
										speed,
										format,
										flags,
										GST_SEEK_TYPE_SET,
										0,
										GST_SEEK_TYPE_SET,
										durationNanos)) {
						ofLogWarning("ofGstUtils") << "gstHandleMessage(): unable to seek";
					}
				}break;

				case OF_LOOP_PALINDROME:{
					GstFormat format = GST_FORMAT_TIME;
					GstSeekFlags flags = (GstSeekFlags) (GST_SEEK_FLAG_FLUSH |GST_SEEK_FLAG_KEY_UNIT);
					gint64 pos;
#if GST_VERSION_MAJOR==0
					gst_element_query_position(GST_ELEMENT(gstPipeline),&format,&pos);
#else
					gst_element_query_position(GST_ELEMENT(gstPipeline),format,&pos);
#endif
					float loopSpeed;
					if(pos>0)
						loopSpeed=-speed;
					else
						loopSpeed=speed;
					if(!gst_element_seek(GST_ELEMENT(gstPipeline),
										loopSpeed,
										GST_FORMAT_UNDEFINED,
										flags,
										GST_SEEK_TYPE_NONE,
										0,
										GST_SEEK_TYPE_NONE,
										0)) {
						ofLogWarning("ofGstUtils") << "gstHandleMessage(): unable to seek";
					}
				}break;

				default:
				break;
			}

		break;

		default:
			ofLogVerbose("ofGstUtils") << "gstHandleMessage(): unhandled message from " << GST_MESSAGE_SRC_NAME(msg);
		break;
	}
	return true;
}
/* Returns TRUE if processing should stop */
static gboolean
handle_message (GstDiscoverer * dc, GstMessage * msg)
{
  gboolean done = FALSE;

  GST_DEBUG_OBJECT (GST_MESSAGE_SRC (msg), "got a %s message",
      GST_MESSAGE_TYPE_NAME (msg));

  switch (GST_MESSAGE_TYPE (msg)) {
    case GST_MESSAGE_ERROR:{
      GError *gerr;
      gchar *debug;

      gst_message_parse_error (msg, &gerr, &debug);
      GST_WARNING_OBJECT (GST_MESSAGE_SRC (msg),
          "Got an error [debug:%s], [message:%s]", debug, gerr->message);
      dc->priv->current_error = gerr;
      g_free (debug);

      /* We need to stop */
      done = TRUE;

      GST_DEBUG ("Setting result to ERROR");
      dc->priv->current_info->result = GST_DISCOVERER_ERROR;
    }
      break;

    case GST_MESSAGE_EOS:
      GST_DEBUG ("Got EOS !");
      done = TRUE;
      break;

    case GST_MESSAGE_ASYNC_DONE:
      if (GST_MESSAGE_SRC (msg) == (GstObject *) dc->priv->pipeline) {
        GST_DEBUG ("Finished changing state asynchronously");
        done = TRUE;

      }
      break;

    case GST_MESSAGE_ELEMENT:
    {
      GQuark sttype = gst_structure_get_name_id (msg->structure);
      GST_DEBUG_OBJECT (GST_MESSAGE_SRC (msg),
          "structure %" GST_PTR_FORMAT, msg->structure);
      if (sttype == _MISSING_PLUGIN_QUARK) {
        GST_DEBUG_OBJECT (GST_MESSAGE_SRC (msg),
            "Setting result to MISSING_PLUGINS");
        dc->priv->current_info->result = GST_DISCOVERER_MISSING_PLUGINS;
        dc->priv->current_info->misc = gst_structure_copy (msg->structure);
      } else if (sttype == _STREAM_TOPOLOGY_QUARK) {
        dc->priv->current_topology = gst_structure_copy (msg->structure);
      }
    }
      break;

    case GST_MESSAGE_TAG:
    {
      GstTagList *tl, *tmp;

      gst_message_parse_tag (msg, &tl);
      GST_DEBUG_OBJECT (GST_MESSAGE_SRC (msg), "Got tags %" GST_PTR_FORMAT, tl);
      /* Merge with current tags */
      tmp =
          gst_tag_list_merge (dc->priv->current_info->tags, tl,
          GST_TAG_MERGE_APPEND);
      gst_tag_list_free (tl);
      if (dc->priv->current_info->tags)
        gst_tag_list_free (dc->priv->current_info->tags);
      dc->priv->current_info->tags = tmp;
      GST_DEBUG_OBJECT (GST_MESSAGE_SRC (msg), "Current info %p, tags %"
          GST_PTR_FORMAT, dc->priv->current_info, tmp);
    }
      break;

    default:
      break;
  }

  return done;
}
//static
gboolean LLMediaImplGStreamer::bus_callback(GstBus *bus, GstMessage *message, gpointer data)
{
#ifdef LL_GST_REPORT_STATE_CHANGES
	LL_DEBUGS("MediaCallback") << "Got GST message type: " << GST_MESSAGE_TYPE_NAME (message) << LL_ENDL;
#endif

	LLMediaImplGStreamer *impl = (LLMediaImplGStreamer*)data;

	switch (GST_MESSAGE_TYPE (message)) 
	{
		case GST_MESSAGE_BUFFERING: 
		{
			gint percent = 0;
			gst_message_parse_buffering(message, &percent);
#ifdef LL_GST_REPORT_STATE_CHANGES
			LL_DEBUGS("MediaBuffering") << "GST buffering: " << percent << "%%" << LL_ENDL;
#endif
			LLMediaEvent event( impl, percent );
			impl->getEventEmitter().update( &LLMediaObserver::onUpdateProgress, event );
		}
			break;
		case GST_MESSAGE_STATE_CHANGED: 
		{
			GstState old_state;
			GstState new_state;
			GstState pending_state;
			gst_message_parse_state_changed(message,
						&old_state,
						&new_state,
						&pending_state);
#ifdef LL_GST_REPORT_STATE_CHANGES
		// not generally very useful, and rather spammy.
		LL_DEBUGS("MediaState") << "GST state change (old,<new>,pending): "<< get_gst_state_name(old_state) << ",<" << get_gst_state_name(new_state) << ">," << get_gst_state_name(pending_state) << LL_ENDL;
#endif // LL_GST_REPORT_STATE_CHANGES

			switch (new_state) 
			{
			case GST_STATE_VOID_PENDING:
				break;
			case GST_STATE_NULL:
#ifdef LL_GST_REPORT_STATE_CHANGES
				LL_DEBUGS("MediaImpl") << "State changed to NULL" << LL_ENDL;
#endif
				if (impl->getState() == GST_STATE_PLAYING) 
				{ 
					// Stream was probably dropped, trying to restart
				    impl->play();
#ifdef LL_GST_REPORT_STATE_CHANGES
				    LL_DEBUGS("MediaImpl") << "Trying to restart." << LL_ENDL;
#endif
				}
				break;
			case GST_STATE_READY:
				break;
			case GST_STATE_PAUSED:
				break;
			case GST_STATE_PLAYING:
				//impl->mLastTitle = "";

				LLMediaEvent event( impl, 100 );
				impl->getEventEmitter().update( &LLMediaObserver::onUpdateProgress, event );
				// emit an event to say that a media source was loaded
				LLMediaEvent event2( impl );
				impl->getEventEmitter().update( &LLMediaObserver::onMediaLoaded, event2 );
				break;
			}
			break;
		}
		case GST_MESSAGE_ERROR: 
		{
			GError *err = NULL;
			gchar *debug = NULL;

			gst_message_parse_error (message, &err, &debug);
			LL_WARNS("MediaImpl") << "GST Error: " << err->message << LL_ENDL;
			g_error_free (err);
			g_free (debug);

			impl->addCommand(LLMediaBase::COMMAND_STOP);
			//impl->addCommand(LLMediaBase::COMMAND_START);

			break;
		}
		case GST_MESSAGE_INFO: 
		{
			GError *err = NULL;
			gchar *debug = NULL;
			
			gst_message_parse_info (message, &err, &debug);
			LL_INFOS("MediaImpl") << "GST info: " << err->message
														<< LL_ENDL;
			g_error_free (err);
			g_free (debug);
			break;
		}
		case GST_MESSAGE_WARNING: 
		{
			GError *err = NULL;
			gchar *debug = NULL;

			gst_message_parse_warning (message, &err, &debug);
			LL_WARNS("MediaImpl") << "GST warning: " <<  err->message
		    << LL_ENDL;
			g_error_free (err);
			g_free (debug);

			break;
		}
		case GST_MESSAGE_TAG: 
		{
			GstTagList *new_tags;

			gst_message_parse_tag( message, &new_tags );

			gchar *title;

			if ( gst_tag_list_get_string(new_tags, GST_TAG_TITLE, &title) )
			{
				LL_INFOS("MediaInfo") << "Title: " << title << LL_ENDL;
				std::string newtitle(title);
				gst_tag_list_free(new_tags);

				if ( newtitle != impl->mLastTitle && newtitle != "" )
				{
					impl->mLastTitle = newtitle;
					LLMediaEvent event( impl, impl->mLastTitle );
					impl->getEventEmitter().update( &LLMediaObserver::onMediaTitleChange, event );
				}

				g_free(title);
			}

			break;
		}
		case GST_MESSAGE_EOS:
		{
			/* end-of-stream */
			LL_DEBUGS("MediaImpl") << "GST end-of-stream." << LL_ENDL;
			if (impl->isLooping())
			{
				LL_DEBUGS("MediaImpl") << "looping media..." << LL_ENDL;
				impl->stop();
				impl->play();
			}
			else
			{
				// inject a COMMAND_STOP
				impl->addCommand(LLMediaBase::COMMAND_STOP);
			}
			break;
		}
		default:
			/* unhandled message */
			break;
	}
	/* we want to be notified again the next time there is a message
	 * on the bus, so return true (false means we want to stop watching
	 * for messages on the bus and our callback should not be called again)
	 */
	return TRUE;
}
Beispiel #20
0
QString Message::typeName() const
{
    return QString::fromUtf8(GST_MESSAGE_TYPE_NAME(object<GstMessage>()));
}
gboolean
MediaPluginGStreamer010::processGSTEvents(GstBus     *bus,
					  GstMessage *message)
{
	if (!message) 
		return TRUE; // shield against GStreamer bug

	if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_STATE_CHANGED &&
	    GST_MESSAGE_TYPE(message) != GST_MESSAGE_BUFFERING)
	{
		DEBUGMSG("Got GST message type: %s",
			GST_MESSAGE_TYPE_NAME (message));
	}
	else
	{
		// TODO: grok 'duration' message type
		DEBUGMSG("Got GST message type: %s",
			 GST_MESSAGE_TYPE_NAME (message));
	}

	switch (GST_MESSAGE_TYPE (message))
	{
		case GST_MESSAGE_BUFFERING:
		{
			// NEEDS GST 0.10.11+ and America discovered by C.Columbus
			gint percent = 0;
			gst_message_parse_buffering(message, &percent);
			DEBUGMSG("GST buffering: %d%%", percent);

			break;
		}
		case GST_MESSAGE_STATE_CHANGED: {
			GstState old_state;
			GstState new_state;
			GstState pending_state;
			gst_message_parse_state_changed(message,
							&old_state,
							&new_state,
							&pending_state);
			#ifdef LL_GST_REPORT_STATE_CHANGES
			// not generally very useful, and rather spammy.
			DEBUGMSG("state change (old,<new>,pending): %s,<%s>,%s",
				get_gst_state_name(old_state),
				get_gst_state_name(new_state),
				get_gst_state_name(pending_state));
			#endif // LL_GST_REPORT_STATE_CHANGES

			switch (new_state) 
			{
				case GST_STATE_VOID_PENDING:
					break;
				case GST_STATE_NULL:
					break;
				case GST_STATE_READY:
					setStatus(STATUS_LOADED);
					break;
				case GST_STATE_PAUSED:
					setStatus(STATUS_PAUSED);
					break;
				case GST_STATE_PLAYING:
					setStatus(STATUS_PLAYING);
					break;
			}
			break;
		}
		case GST_MESSAGE_ERROR:
		{
			GError *err = NULL;
			gchar *debug = NULL;
	
			gst_message_parse_error (message, &err, &debug);
			WARNMSG("GST error: %s", err?err->message:"(unknown)");
			if (err)
				g_error_free (err);
			g_free (debug);
	
			mCommand = COMMAND_STOP;
	
			setStatus(STATUS_ERROR);
	
			break;
		}
		case GST_MESSAGE_INFO:
		{
			GError *err = NULL;
			gchar *debug = NULL;
			
			gst_message_parse_info (message, &err, &debug);
			INFOMSG("GST info: %s", err?err->message:"(unknown)");
			if (err)
				g_error_free (err);
			g_free (debug);

			break;
		}
		case GST_MESSAGE_WARNING:
		{
			GError *err = NULL;
			gchar *debug = NULL;
	
			gst_message_parse_warning (message, &err, &debug);
			WARNMSG("GST warning: %s", err?err->message:"(unknown)");
			if (err)
				g_error_free (err);
			g_free (debug);
	
			break;
		}
		case GST_MESSAGE_TAG: 
		{
			GstTagList *new_tags;

			gst_message_parse_tag( message, &new_tags );

			gchar *title = NULL;

			if ( gst_tag_list_get_string(new_tags, GST_TAG_TITLE, &title) )
			{
				//WARMING("Title: %s", title);
				std::string newtitle(title);
				gst_tag_list_free(new_tags);

				if ( newtitle != mLastTitle && !newtitle.empty() )
				{
					LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text");
					message.setValue("name", newtitle );
					sendMessage( message );
					mLastTitle = newtitle;
				}
				g_free(title);
			}

			break;
		}
		case GST_MESSAGE_EOS:
		{
			/* end-of-stream */
			DEBUGMSG("GST end-of-stream.");
			if (mIsLooping)
			{
				DEBUGMSG("looping media...");
				double eos_pos_sec = 0.0F;
				bool got_eos_position = getTimePos(eos_pos_sec);
	
				if (got_eos_position && eos_pos_sec < MIN_LOOP_SEC)
				{
					// if we know that the movie is really short, don't
					// loop it else it can easily become a time-hog
					// because of GStreamer spin-up overhead
					DEBUGMSG("really short movie (%0.3fsec) - not gonna loop this, pausing instead.", eos_pos_sec);
					// inject a COMMAND_PAUSE
					mCommand = COMMAND_PAUSE;
				}
				else
				{
					#undef LLGST_LOOP_BY_SEEKING
					// loop with a stop-start instead of a seek, because it actually seems rather
					// faster than seeking on remote streams.
					#ifdef LLGST_LOOP_BY_SEEKING
					// first, try looping by an explicit rewind
					bool seeksuccess = seek(0.0);
					if (seeksuccess)
					{
						play(1.0);
					}
					else
					#endif // LLGST_LOOP_BY_SEEKING
					{  // use clumsy stop-start to loop
						DEBUGMSG("didn't loop by rewinding - stopping and starting instead...");
						stop();
						play(1.0);
					}
				}
			}
			else // not a looping media
			{
				// inject a COMMAND_STOP
				mCommand = COMMAND_STOP;
			}
		} break;

		default:
			/* unhandled message */
			break;
	}

	/* we want to be notified again the next time there is a message
	 * on the bus, so return true (false means we want to stop watching
	 * for messages on the bus and our callback should not be called again)
	 */
	return TRUE;
}
Beispiel #22
0
static gboolean
gst_PlayRegion_handle_message (GstBus * bus, GstMessage * message, gpointer data)
{
  GstPlayRegion *PlayRegion = (GstPlayRegion *) data;

  switch (GST_MESSAGE_TYPE (message)) {

    case GST_MESSAGE_APPLICATION:
      if (gst_message_has_name (message, "ExPrerolled")) {
        /* it's our message */
        g_print ("we are all prerolled, do seek\n");
        gst_element_seek (PlayRegion->pipeline,
          1.0, GST_FORMAT_TIME,
          GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE,
          GST_SEEK_TYPE_SET, 2 * GST_SECOND,
          GST_SEEK_TYPE_SET, 5 * GST_SECOND);

        gst_element_set_state (PlayRegion->pipeline, GST_STATE_PLAYING);
      }
      break;

    case GST_MESSAGE_EOS:
      gst_PlayRegion_handle_eos (PlayRegion);
      break;
    case GST_MESSAGE_ERROR:
    {
      GError *error = NULL;
      gchar *debug;

      gst_message_parse_error (message, &error, &debug);
      gst_PlayRegion_handle_error (PlayRegion, error, debug);
    }
      break;
    case GST_MESSAGE_WARNING:
    {
      GError *error = NULL;
      gchar *debug;

      gst_message_parse_warning (message, &error, &debug);
      gst_PlayRegion_handle_warning (PlayRegion, error, debug);
    }
      break;
    case GST_MESSAGE_INFO:
    {
      GError *error = NULL;
      gchar *debug;

      gst_message_parse_info (message, &error, &debug);
      gst_PlayRegion_handle_info (PlayRegion, error, debug);
    }
      break;
    case GST_MESSAGE_TAG:
    {
      GstTagList *tag_list;

      gst_message_parse_tag (message, &tag_list);
      if (verbose)
        g_print ("tag\n");
    }
      break;
    case GST_MESSAGE_STATE_CHANGED:
    {
      GstState oldstate, newstate, pending;

      gst_message_parse_state_changed (message, &oldstate, &newstate, &pending);
      if (GST_ELEMENT (message->src) == PlayRegion->pipeline) {
        if (verbose)
          g_print ("state change from %s to %s\n",
              gst_element_state_get_name (oldstate),
              gst_element_state_get_name (newstate));
        switch (GST_STATE_TRANSITION (oldstate, newstate)) {
          case GST_STATE_CHANGE_NULL_TO_READY:
            gst_PlayRegion_handle_null_to_ready (PlayRegion);
            break;
          case GST_STATE_CHANGE_READY_TO_PAUSED:
            gst_PlayRegion_handle_ready_to_paused (PlayRegion);
            break;
          case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
            gst_PlayRegion_handle_paused_to_playing (PlayRegion);
            break;
          case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
            gst_PlayRegion_handle_playing_to_paused (PlayRegion);
            break;
          case GST_STATE_CHANGE_PAUSED_TO_READY:
            gst_PlayRegion_handle_paused_to_ready (PlayRegion);
            break;
          case GST_STATE_CHANGE_READY_TO_NULL:
            gst_PlayRegion_handle_ready_to_null (PlayRegion);
            break;
          default:
            if (verbose)
              g_print ("unknown state change from %s to %s\n",
                  gst_element_state_get_name (oldstate),
                  gst_element_state_get_name (newstate));
        }
      }
    }
      break;
    case GST_MESSAGE_BUFFERING:
    {
      int percent;
      gst_message_parse_buffering (message, &percent);
      //g_print("buffering %d\n", percent);
      if (!PlayRegion->paused_for_buffering && percent < 100) {
        g_print ("pausing for buffing\n");
        PlayRegion->paused_for_buffering = TRUE;
        gst_element_set_state (PlayRegion->pipeline, GST_STATE_PAUSED);
      } else if (PlayRegion->paused_for_buffering && percent == 100) {
        g_print ("unpausing for buffing\n");
        PlayRegion->paused_for_buffering = FALSE;
        gst_element_set_state (PlayRegion->pipeline, GST_STATE_PLAYING);
      }
    }
      break;
    case GST_MESSAGE_STATE_DIRTY:
    case GST_MESSAGE_CLOCK_PROVIDE:
    case GST_MESSAGE_CLOCK_LOST:
    case GST_MESSAGE_NEW_CLOCK:
    case GST_MESSAGE_STRUCTURE_CHANGE:
    case GST_MESSAGE_STREAM_STATUS:
      break;
    case GST_MESSAGE_STEP_DONE:
    case GST_MESSAGE_ELEMENT:
    case GST_MESSAGE_SEGMENT_START:
    case GST_MESSAGE_SEGMENT_DONE:
    case GST_MESSAGE_DURATION:
    case GST_MESSAGE_LATENCY:
    case GST_MESSAGE_ASYNC_START:
    case GST_MESSAGE_ASYNC_DONE:
    case GST_MESSAGE_REQUEST_STATE:
    case GST_MESSAGE_STEP_START:
    case GST_MESSAGE_QOS:
    default:
      if (verbose) {
        g_print ("message: %s\n", GST_MESSAGE_TYPE_NAME (message));
      }
      break;
  }

  return TRUE;
}
/**
 * gst_bus_timed_pop_filtered:
 * @bus: a #GstBus to pop from
 * @timeout: a timeout in nanoseconds, or GST_CLOCK_TIME_NONE to wait forever
 * @types: message types to take into account, GST_MESSAGE_ANY for any type
 *
 * Get a message from the bus whose type matches the message type mask @types,
 * waiting up to the specified timeout (and discarding any messages that do not
 * match the mask provided).
 *
 * If @timeout is 0, this function behaves like gst_bus_pop_filtered(). If
 * @timeout is #GST_CLOCK_TIME_NONE, this function will block forever until a
 * matching message was posted on the bus.
 *
 * Returns: (transfer full) (nullable): a #GstMessage matching the
 *     filter in @types, or %NULL if no matching message was found on
 *     the bus until the timeout expired. The message is taken from
 *     the bus and needs to be unreffed with gst_message_unref() after
 *     usage.
 *
 * MT safe.
 */
GstMessage *
gst_bus_timed_pop_filtered (GstBus * bus, GstClockTime timeout,
    GstMessageType types)
{
  GstMessage *message;
  GTimeVal now, then;
  gboolean first_round = TRUE;
  GstClockTime elapsed = 0;

  g_return_val_if_fail (GST_IS_BUS (bus), NULL);
  g_return_val_if_fail (types != 0, NULL);
  g_return_val_if_fail (timeout == 0 || bus->priv->poll != NULL, NULL);

  g_mutex_lock (&bus->priv->queue_lock);

  while (TRUE) {
    gint ret;

    GST_LOG_OBJECT (bus, "have %d messages",
        gst_atomic_queue_length (bus->priv->queue));

    while ((message = gst_atomic_queue_pop (bus->priv->queue))) {
      if (bus->priv->poll)
        gst_poll_read_control (bus->priv->poll);

      GST_DEBUG_OBJECT (bus, "got message %p, %s from %s, type mask is %u",
          message, GST_MESSAGE_TYPE_NAME (message),
          GST_MESSAGE_SRC_NAME (message), (guint) types);
      if ((GST_MESSAGE_TYPE (message) & types) != 0) {
        /* Extra check to ensure extended types don't get matched unless
         * asked for */
        if ((!GST_MESSAGE_TYPE_IS_EXTENDED (message))
            || (types & GST_MESSAGE_EXTENDED)) {
          /* exit the loop, we have a message */
          goto beach;
        }
      }

      GST_DEBUG_OBJECT (bus, "discarding message, does not match mask");
      gst_message_unref (message);
      message = NULL;
    }

    /* no need to wait, exit loop */
    if (timeout == 0)
      break;

    else if (timeout != GST_CLOCK_TIME_NONE) {
      if (first_round) {
        g_get_current_time (&then);
        first_round = FALSE;
      } else {
        g_get_current_time (&now);

        elapsed = GST_TIMEVAL_TO_TIME (now) - GST_TIMEVAL_TO_TIME (then);

        if (elapsed > timeout)
          break;
      }
    }

    /* only here in timeout case */
    g_assert (bus->priv->poll);
    g_mutex_unlock (&bus->priv->queue_lock);
    ret = gst_poll_wait (bus->priv->poll, timeout - elapsed);
    g_mutex_lock (&bus->priv->queue_lock);

    if (ret == 0) {
      GST_INFO_OBJECT (bus, "timed out, breaking loop");
      break;
    } else {
      GST_INFO_OBJECT (bus, "we got woken up, recheck for message");
    }
  }

beach:

  g_mutex_unlock (&bus->priv->queue_lock);

  return message;
}
Beispiel #24
0
static gboolean
bus_message (GstBus * bus, GstMessage * message, App * app)
{
    gchar *sourceName;
    GstObject *source;
    gchar *string;
    GstState current_state;

    if (!message)
        return FALSE;
    source = GST_MESSAGE_SRC (message);
    if (!GST_IS_OBJECT (source))
        return FALSE;
    sourceName = gst_object_get_name (source);

    if (gst_message_get_structure (message))
        string = gst_structure_to_string (gst_message_get_structure (message));
    else
        string = g_strdup (GST_MESSAGE_TYPE_NAME (message));
    GST_DEBUG("gst_message from %s: %s", sourceName, string);
    g_free (string);

    switch (GST_MESSAGE_TYPE (message)) {
    case GST_MESSAGE_ERROR:
    {
        GError *gerror;
        gchar *debug;

        gst_message_parse_error (message, &gerror, &debug);
        gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
        g_error_free (gerror);
        g_free (debug);

        g_main_loop_quit (app->loop);
        break;
    }
    case GST_MESSAGE_WARNING:
    {
        GError *gerror;
        gchar *debug;

        gst_message_parse_warning (message, &gerror, &debug);
        gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
        g_error_free (gerror);
        g_free (debug);

//       g_main_loop_quit (app->loop);
        break;
    }
    case GST_MESSAGE_EOS:
        g_message ("received EOS");
        g_main_loop_quit (app->loop);
        break;
    case GST_MESSAGE_ASYNC_DONE:
        break;
    case GST_MESSAGE_ELEMENT:
    {
        const GstStructure *msgstruct = gst_message_get_structure (message);
        if (msgstruct) {
            const gchar *eventname = gst_structure_get_name (msgstruct);
            if (!strcmp (eventname, "seekable"))
                app->is_seekable = TRUE;
        }
        break;
    }
    case GST_MESSAGE_STATE_CHANGED:
    {
        GstState old_state, new_state;
        GstStateChange transition;
        if (GST_MESSAGE_SRC (message) != GST_OBJECT (app->tsdemux))
            break;

        gst_message_parse_state_changed (message, &old_state, &new_state, NULL);
        transition = (GstStateChange) GST_STATE_TRANSITION (old_state, new_state);

        switch (transition) {
        case GST_STATE_CHANGE_NULL_TO_READY:
            break;
        case GST_STATE_CHANGE_READY_TO_PAUSED:
            break;
        case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
        {

        }
        break;
        case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
            break;
        case GST_STATE_CHANGE_PAUSED_TO_READY:
            break;
        case GST_STATE_CHANGE_READY_TO_NULL:
            break;
        }
        break;
    }
    case GST_MESSAGE_SEGMENT_DONE:
    {
        GST_DEBUG ("GST_MESSAGE_SEGMENT_DONE!!!");
        do_seek (app);
    }
    default:
        break;
    }
    gst_element_get_state (app->pipeline, &current_state, NULL, 0);
    if (app->current_segment == 0 && app->segment_count /*&& app->is_seekable*/
            && current_state == GST_STATE_PLAYING)
        do_seek (app);
    GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(app->pipeline),GST_DEBUG_GRAPH_SHOW_ALL,"bdremux_pipelinegraph_message");
    return TRUE;
}
Beispiel #25
0
// ----------------------------------------------------------------------------
// Retrieve and process a bus message
bool
GStreamerImportFileHandle::ProcessBusMessage(bool & success)
{
   bool cont = true;

   // Default to no errors
   success = true;

   // Get the next message
   GstMessage *msg = gst_bus_timed_pop(mBus, 100 * GST_MSECOND);
   if (!msg)
   {
      // Timed out...not an error
      return cont;
   }

#if defined(__WXDEBUG__)
   gchar *objname = NULL;
   if (msg->src != NULL)
   {
      objname = gst_object_get_name(msg->src);
   }

   wxLogMessage(wxT("GStreamer: Got %s%s%s"),
                wxString::FromUTF8(GST_MESSAGE_TYPE_NAME(msg)).c_str(),
                objname ? wxT(" from ") : wxT(""),
                objname ? wxString::FromUTF8(objname).c_str() : wxT(""));

   if (objname != NULL)
   {
      g_free(objname);
   }
#endif

   // Handle based on message type
   switch (GST_MESSAGE_TYPE(msg))
   {
      // Handle error message from gstreamer
      case GST_MESSAGE_ERROR:
      {
         GError *err = NULL;
         gchar *debug = NULL;

         gst_message_parse_error(msg, &err, &debug);
         if (err)
         {
            wxString m;

            m.Printf(wxT("%s%s%s"),
               wxString::FromUTF8(err->message).c_str(),
               debug ? wxT("\n") : wxT(""),
               debug ? wxString::FromUTF8(debug).c_str() : wxT(""));
#if defined(_DEBUG)
            wxMessageBox(m, wxT("GStreamer Error:"));
#else
            wxLogMessage(wxT("GStreamer Error: %s"), m.c_str());
#endif
            g_error_free(err);
         }

         if (debug)
         {
            g_free(debug);
         }

         success = false;
         cont = false;
      }
      break;

      // Handle warning message from gstreamer
      case GST_MESSAGE_WARNING:
      {
         GError *err = NULL;
         gchar *debug = NULL;

         gst_message_parse_warning(msg, &err, &debug);

         if (err)
         {
            wxLogMessage(wxT("GStreamer Warning: %s%s%s"),
                         wxString::FromUTF8(err->message).c_str(),
                         debug ? wxT("\n") : wxT(""),
                         debug ? wxString::FromUTF8(debug).c_str() : wxT(""));

            g_error_free(err);
         }

         if (debug)
         {
            g_free(debug);
         }
      }
      break;

      // Handle warning message from gstreamer
      case GST_MESSAGE_INFO:
      {
         GError *err = NULL;
         gchar *debug = NULL;

         gst_message_parse_info(msg, &err, &debug);
         if (err)
         {
            wxLogMessage(wxT("GStreamer Info: %s%s%s"),
                         wxString::FromUTF8(err->message).c_str(),
                         debug ? wxT("\n") : wxT(""),
                         debug ? wxString::FromUTF8(debug).c_str() : wxT(""));

            g_error_free(err);
         }

         if (debug)
         {
            g_free(debug);
         }
      }
      break;

      // Handle metadata tags
      case GST_MESSAGE_TAG:
      {
         GstTagList *tags = NULL;

         // Retrieve tag list from message...just ignore failure
         gst_message_parse_tag(msg, &tags);
         if (tags)
         {
            // Go process the list
            OnTag(GST_APP_SINK(GST_MESSAGE_SRC(msg)), tags);

            // Done with list
            gst_tag_list_unref(tags);
         }
      }
      break;

      // Pre-roll is done...will happen for each group
      // (like with chained OGG files)
      case GST_MESSAGE_ASYNC_DONE:
      {
         // If this is the first async-done message, then tell
         // caller to end loop, but leave it active so that
         // gstreamer threads can still queue up.
         //
         // We'll receive multiple async-done messages for chained
         // ogg files, so ignore the message the 2nd and subsequent
         // occurrences.
         if (!mAsyncDone)
         {
            cont = false;
            mAsyncDone = true;
         }

      }
      break;

      // End of the stream (and all sub-streams)
      case GST_MESSAGE_EOS:
      {
         // Terminate loop
         cont = false;
      }
      break;
   }

   // Release the message
   gst_message_unref(msg);

   return cont;
}
Beispiel #26
0
static gboolean
gst_switchui_handle_message (GstBus * bus, GstMessage * message, gpointer data)
{
  GstSwitchUI *switchui = (GstSwitchUI *) data;

  switch (GST_MESSAGE_TYPE (message)) {
    case GST_MESSAGE_EOS:
      gst_switchui_handle_eos (switchui);
      break;
    case GST_MESSAGE_ERROR:
    {
      GError *error = NULL;
      gchar *debug;

      gst_message_parse_error (message, &error, &debug);
      gst_switchui_handle_error (switchui, error, debug);
    }
      break;
    case GST_MESSAGE_WARNING:
    {
      GError *error = NULL;
      gchar *debug;

      gst_message_parse_warning (message, &error, &debug);
      gst_switchui_handle_warning (switchui, error, debug);
    }
      break;
    case GST_MESSAGE_INFO:
    {
      GError *error = NULL;
      gchar *debug;

      gst_message_parse_info (message, &error, &debug);
      gst_switchui_handle_info (switchui, error, debug);
    }
      break;
    case GST_MESSAGE_TAG:
    {
      GstTagList *tag_list;

      gst_message_parse_tag (message, &tag_list);
      if (verbose)
        g_print ("tag\n");
    }
      break;
    case GST_MESSAGE_STATE_CHANGED:
    {
      GstState oldstate, newstate, pending;

      gst_message_parse_state_changed (message, &oldstate, &newstate, &pending);
      if (GST_ELEMENT (message->src) == switchui->pipeline) {
        if (verbose)
          g_print ("state change from %s to %s\n",
              gst_element_state_get_name (oldstate),
              gst_element_state_get_name (newstate));
        switch (GST_STATE_TRANSITION (oldstate, newstate)) {
          case GST_STATE_CHANGE_NULL_TO_READY:
            gst_switchui_handle_null_to_ready (switchui);
            break;
          case GST_STATE_CHANGE_READY_TO_PAUSED:
            gst_switchui_handle_ready_to_paused (switchui);
            break;
          case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
            gst_switchui_handle_paused_to_playing (switchui);
            break;
          case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
            gst_switchui_handle_playing_to_paused (switchui);
            break;
          case GST_STATE_CHANGE_PAUSED_TO_READY:
            gst_switchui_handle_paused_to_ready (switchui);
            break;
          case GST_STATE_CHANGE_READY_TO_NULL:
            gst_switchui_handle_ready_to_null (switchui);
            break;
          default:
            if (verbose)
              g_print ("unknown state change from %s to %s\n",
                  gst_element_state_get_name (oldstate),
                  gst_element_state_get_name (newstate));
        }
      }
    }
      break;
    case GST_MESSAGE_BUFFERING:
    {
      int percent;
      gst_message_parse_buffering (message, &percent);
      //g_print("buffering %d\n", percent);
      if (!switchui->paused_for_buffering && percent < 100) {
        g_print ("pausing for buffing\n");
        switchui->paused_for_buffering = TRUE;
        gst_element_set_state (switchui->pipeline, GST_STATE_PAUSED);
      } else if (switchui->paused_for_buffering && percent == 100) {
        g_print ("unpausing for buffing\n");
        switchui->paused_for_buffering = FALSE;
        gst_element_set_state (switchui->pipeline, GST_STATE_PLAYING);
      }
    }
      break;
    case GST_MESSAGE_STATE_DIRTY:
    case GST_MESSAGE_CLOCK_PROVIDE:
    case GST_MESSAGE_CLOCK_LOST:
    case GST_MESSAGE_NEW_CLOCK:
    case GST_MESSAGE_STRUCTURE_CHANGE:
    case GST_MESSAGE_STREAM_STATUS:
      break;
    case GST_MESSAGE_STEP_DONE:
    case GST_MESSAGE_APPLICATION:
    case GST_MESSAGE_ELEMENT:
    case GST_MESSAGE_SEGMENT_START:
    case GST_MESSAGE_SEGMENT_DONE:
      //case GST_MESSAGE_DURATION:
    case GST_MESSAGE_LATENCY:
    case GST_MESSAGE_ASYNC_START:
    case GST_MESSAGE_ASYNC_DONE:
    case GST_MESSAGE_REQUEST_STATE:
    case GST_MESSAGE_STEP_START:
    case GST_MESSAGE_QOS:
    default:
      if (verbose) {
        g_print ("message: %s\n", GST_MESSAGE_TYPE_NAME (message));
      }
      break;
  }

  return TRUE;
}
Beispiel #27
0
/**
 * gst_bus_timed_pop_filtered:
 * @bus: a #GstBus to pop from
 * @timeout: a timeout in nanoseconds, or GST_CLOCK_TIME_NONE to wait forever
 * @types: message types to take into account, GST_MESSAGE_ANY for any type
 *
 * Get a message from the bus whose type matches the message type mask @types,
 * waiting up to the specified timeout (and discarding any messages that do not
 * match the mask provided).
 *
 * If @timeout is 0, this function behaves like gst_bus_pop_filtered(). If
 * @timeout is #GST_CLOCK_TIME_NONE, this function will block forever until a
 * matching message was posted on the bus.
 *
 * Returns: (transfer full) (nullable): a #GstMessage matching the
 *     filter in @types, or %NULL if no matching message was found on
 *     the bus until the timeout expired. The message is taken from
 *     the bus and needs to be unreffed with gst_message_unref() after
 *     usage.
 *
 * MT safe.
 */
GstMessage *
gst_bus_timed_pop_filtered (GstBus * bus, GstClockTime timeout,
    GstMessageType types)
{
  GstMessage *message;
  GTimeVal now, then;
  gboolean first_round = TRUE;
  GstClockTime elapsed = 0;

  g_return_val_if_fail (GST_IS_BUS (bus), NULL);
  g_return_val_if_fail (types != 0, NULL);
  g_return_val_if_fail (timeout == 0 || bus->priv->poll != NULL, NULL);

  g_mutex_lock (&bus->priv->queue_lock);

  while (TRUE) {
    gint ret;

    GST_LOG_OBJECT (bus, "have %d messages",
        gst_atomic_queue_length (bus->priv->queue));

    while ((message = gst_atomic_queue_pop (bus->priv->queue))) {
      if (bus->priv->poll) {
        while (!gst_poll_read_control (bus->priv->poll)) {
          if (errno == EWOULDBLOCK) {
            /* Retry, this can happen if pushing to the queue has finished,
             * popping here succeeded but writing control did not finish
             * before we got to this line. */
            /* Give other threads the chance to do something */
            g_thread_yield ();
            continue;
          } else {
            /* This is a real error and means that either the bus is in an
             * inconsistent state, or the GstPoll is invalid. GstPoll already
             * prints a critical warning about this, no need to do that again
             * ourselves */
            break;
          }
        }
      }

      GST_DEBUG_OBJECT (bus, "got message %p, %s from %s, type mask is %u",
          message, GST_MESSAGE_TYPE_NAME (message),
          GST_MESSAGE_SRC_NAME (message), (guint) types);
      if ((GST_MESSAGE_TYPE (message) & types) != 0) {
        /* Extra check to ensure extended types don't get matched unless
         * asked for */
        if ((!GST_MESSAGE_TYPE_IS_EXTENDED (message))
            || (types & GST_MESSAGE_EXTENDED)) {
          /* exit the loop, we have a message */
          goto beach;
        }
      }

      GST_DEBUG_OBJECT (bus, "discarding message, does not match mask");
      gst_message_unref (message);
      message = NULL;
    }

    /* no need to wait, exit loop */
    if (timeout == 0)
      break;

    else if (timeout != GST_CLOCK_TIME_NONE) {
      if (first_round) {
        g_get_current_time (&then);
        first_round = FALSE;
      } else {
        g_get_current_time (&now);

        elapsed = GST_TIMEVAL_TO_TIME (now) - GST_TIMEVAL_TO_TIME (then);

        if (elapsed > timeout)
          break;
      }
    }

    /* only here in timeout case */
    g_assert (bus->priv->poll);
    g_mutex_unlock (&bus->priv->queue_lock);
    ret = gst_poll_wait (bus->priv->poll, timeout - elapsed);
    g_mutex_lock (&bus->priv->queue_lock);

    if (ret == 0) {
      GST_INFO_OBJECT (bus, "timed out, breaking loop");
      break;
    } else {
      GST_INFO_OBJECT (bus, "we got woken up, recheck for message");
    }
  }

beach:

  g_mutex_unlock (&bus->priv->queue_lock);

  return message;
}