transcoder: Add state-changed signal
authorPhilippe Normand <philn@igalia.com>
Sat, 20 Feb 2021 11:36:42 +0000 (11:36 +0000)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Wed, 10 Mar 2021 17:13:57 +0000 (17:13 +0000)
Similar to GstPlayer, a new signal for state tracking is now emitted at runtime,
as a commodity for applications which then don't need to monitor the pipeline
GstBus for state changes anymore.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/2028>

gst-libs/gst/transcoder/gsttranscoder-private.h
gst-libs/gst/transcoder/gsttranscoder-signal-adapter.c
gst-libs/gst/transcoder/gsttranscoder.c
gst-libs/gst/transcoder/gsttranscoder.h

index edf8daf..f0acce6 100644 (file)
@@ -25,6 +25,7 @@
 #define GST_TRANSCODER_MESSAGE_DATA_TYPE "transcoder-message-type"
 #define GST_TRANSCODER_MESSAGE_DATA_POSITION "position"
 #define GST_TRANSCODER_MESSAGE_DATA_DURATION "duration"
+#define GST_TRANSCODER_MESSAGE_DATA_STATE "state"
 #define GST_TRANSCODER_MESSAGE_DATA_ERROR "error"
 #define GST_TRANSCODER_MESSAGE_DATA_WARNING "warning"
 #define GST_TRANSCODER_MESSAGE_DATA_ISSUE_DETAILS "issue-details"
@@ -40,4 +41,4 @@ struct _GstTranscoderSignalAdapter
 
 
 GstTranscoderSignalAdapter * gst_transcoder_signal_adapter_new_sync_emit (GstTranscoder * transcoder);
-GstTranscoderSignalAdapter * gst_transcoder_signal_adapter_new           (GstTranscoder * transcoder, GMainContext * context);
\ No newline at end of file
+GstTranscoderSignalAdapter * gst_transcoder_signal_adapter_new           (GstTranscoder * transcoder, GMainContext * context);
index 6d54405..cbbec12 100644 (file)
@@ -37,6 +37,7 @@ enum
 {
   SIGNAL_POSITION_UPDATED,
   SIGNAL_DURATION_CHANGED,
+  SIGNAL_STATE_CHANGED,
   SIGNAL_DONE,
   SIGNAL_ERROR,
   SIGNAL_WARNING,
@@ -94,6 +95,13 @@ gst_transcoder_signal_adapter_emit (GstTranscoderSignalAdapter * self,
       g_signal_emit (self, signals[SIGNAL_DURATION_CHANGED], 0, duration);
       break;
     }
+    case GST_TRANSCODER_MESSAGE_STATE_CHANGED:{
+      GstTranscoderState state;
+      gst_structure_get (message_data, GST_TRANSCODER_MESSAGE_DATA_STATE,
+          GST_TYPE_TRANSCODER_STATE, &state, NULL);
+      g_signal_emit (self, signals[SIGNAL_STATE_CHANGED], 0, state);
+      break;
+    }
     case GST_TRANSCODER_MESSAGE_DONE:
       g_signal_emit (self, signals[SIGNAL_DONE], 0);
       break;
@@ -298,6 +306,11 @@ gst_transcoder_signal_adapter_class_init (GstTranscoderSignalAdapterClass *
       G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, 0, NULL,
       NULL, NULL, G_TYPE_NONE, 2, G_TYPE_ERROR, GST_TYPE_STRUCTURE);
 
+  signals[SIGNAL_STATE_CHANGED] =
+      g_signal_new ("state-changed", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, 0, NULL,
+      NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_TRANSCODER_STATE);
+
   /**
    * GstTranscoderSignalAdapter:transcoder:
    *
index 575493a..1b93375 100644 (file)
@@ -90,6 +90,8 @@ struct _GstTranscoder
 
   GstClockTime last_duration;
 
+  GstTranscoderState app_state;
+
   GstBus *api_bus;
   GstTranscoderSignalAdapter *signal_adapter;
   GstTranscoderSignalAdapter *sync_signal_adapter;
@@ -590,6 +592,20 @@ warning_cb (G_GNUC_UNUSED GstBus * bus, GstMessage * msg, gpointer user_data)
 }
 
 static void
+notify_state_changed (GstTranscoder * self, GstTranscoderState new_state)
+{
+  if (new_state == self->app_state)
+    return;
+
+  GST_DEBUG_OBJECT (self, "Notifying new state: %s",
+      gst_transcoder_state_get_name (new_state));
+  self->app_state = new_state;
+  api_bus_post_message (self, GST_TRANSCODER_MESSAGE_STATE_CHANGED,
+      GST_TRANSCODER_MESSAGE_DATA_STATE, GST_TYPE_TRANSCODER_STATE, new_state,
+      NULL);
+}
+
+static void
 eos_cb (G_GNUC_UNUSED GstBus * bus, G_GNUC_UNUSED GstMessage * msg,
     gpointer user_data)
 {
@@ -602,6 +618,7 @@ eos_cb (G_GNUC_UNUSED GstBus * bus, G_GNUC_UNUSED GstMessage * msg,
   tick_cb (self);
   remove_tick_source (self);
 
+  notify_state_changed (self, GST_TRANSCODER_STATE_STOPPED);
   api_bus_post_message (self, GST_TRANSCODER_MESSAGE_DONE, NULL, NULL);
   self->is_eos = TRUE;
 }
@@ -654,9 +671,16 @@ state_changed_cb (G_GNUC_UNUSED GstBus * bus, GstMessage * msg,
 
     self->current_state = new_state;
 
+    if (new_state == GST_STATE_PAUSED
+        && pending_state == GST_STATE_VOID_PENDING) {
+      remove_tick_source (self);
+      notify_state_changed (self, GST_TRANSCODER_STATE_PAUSED);
+    }
+
     if (new_state == GST_STATE_PLAYING
         && pending_state == GST_STATE_VOID_PENDING) {
       add_tick_source (self);
+      notify_state_changed (self, GST_TRANSCODER_STATE_PLAYING);
     }
   }
 }
@@ -797,6 +821,7 @@ gst_transcoder_main (gpointer data)
   self->current_state = GST_STATE_NULL;
   self->is_eos = FALSE;
   self->is_live = FALSE;
+  self->app_state = GST_TRANSCODER_STATE_STOPPED;
 
   GST_TRACE_OBJECT (self, "Starting main loop");
   g_main_loop_run (self->loop);
@@ -1411,6 +1436,23 @@ gst_transcoder_message_parse_position (GstMessage * msg,
 }
 
 /**
+ * gst_transcoder_message_parse_state:
+ * @msg: A #GstMessage
+ * @state: (out): the resulting state
+ *
+ * Parse the given state @msg and extract the corresponding #GstTranscoderState
+ *
+ * Since: 1.20
+ */
+void
+gst_transcoder_message_parse_state (GstMessage * msg,
+    GstTranscoderState * state)
+{
+  PARSE_MESSAGE_FIELD (msg, GST_TRANSCODER_MESSAGE_DATA_STATE,
+      GST_TYPE_TRANSCODER_STATE, state);
+}
+
+/**
  * gst_transcoder_message_parse_error:
  * @msg: A #GstMessage
  * @error: (out): the resulting error
@@ -1449,3 +1491,29 @@ gst_transcoder_message_parse_warning (GstMessage * msg, GError * error,
   PARSE_MESSAGE_FIELD (msg, GST_TRANSCODER_MESSAGE_DATA_ISSUE_DETAILS,
       GST_TYPE_STRUCTURE, details);
 }
+
+/**
+ * gst_transcoder_state_get_name:
+ * @state: a #GstTranscoderState
+ *
+ * Gets a string representing the given state.
+ *
+ * Returns: (transfer none): a string with the name of the state.
+ *
+ * Since: 1.20
+ */
+const gchar *
+gst_transcoder_state_get_name (GstTranscoderState state)
+{
+  switch (state) {
+    case GST_TRANSCODER_STATE_STOPPED:
+      return "stopped";
+    case GST_TRANSCODER_STATE_PAUSED:
+      return "paused";
+    case GST_TRANSCODER_STATE_PLAYING:
+      return "playing";
+  }
+
+  g_assert_not_reached ();
+  return NULL;
+}
index 5f890c6..938db7e 100644 (file)
@@ -28,12 +28,35 @@ GQuark        gst_transcoder_error_quark    (void);
 GST_TRANSCODER_API
 const gchar * gst_transcoder_error_get_name (GstTranscoderError error);
 
+/*********** State definition ************/
+
+/**
+ * GstTranscoderState:
+ * @GST_TRANSCODER_STATE_STOPPED: the transcoder is stopped.
+ * @GST_TRANSCODER_STATE_PAUSED: the transcoder is paused.
+ * @GST_TRANSCODER_STATE_PLAYING: the transcoder is currently transcoding a
+ * stream.
+ *
+ * High level representation of the transcoder pipeline state.
+ *
+ * Since: 1.20
+ */
+typedef enum {
+    GST_TRANSCODER_STATE_STOPPED,
+    GST_TRANSCODER_STATE_PAUSED,
+    GST_TRANSCODER_STATE_PLAYING
+} GstTranscoderState;
+
+GST_TRANSCODER_API
+const gchar * gst_transcoder_state_get_name                (GstTranscoderState state);
+
 /*********** Messages types definitions ************/
 
 /**
  * GstTranscoderMessage:
  * @GST_TRANSCODER_MESSAGE_POSITION_UPDATED: Sink position changed
  * @GST_TRANSCODER_MESSAGE_DURATION_CHANGED: Duration of stream changed
+ * @GST_TRANSCODER_MESSAGE_STATE_CHANGED: Pipeline state changed
  * @GST_TRANSCODER_MESSAGE_DONE: Transcoding is done
  * @GST_TRANSCODER_MESSAGE_ERROR: Message contains an error
  * @GST_TRANSCODER_MESSAGE_WARNING: Message contains an error
@@ -48,6 +71,7 @@ typedef enum
 {
   GST_TRANSCODER_MESSAGE_POSITION_UPDATED,
   GST_TRANSCODER_MESSAGE_DURATION_CHANGED,
+  GST_TRANSCODER_MESSAGE_STATE_CHANGED,
   GST_TRANSCODER_MESSAGE_DONE,
   GST_TRANSCODER_MESSAGE_ERROR,
   GST_TRANSCODER_MESSAGE_WARNING,
@@ -66,6 +90,9 @@ GST_TRANSCODER_API
 void           gst_transcoder_message_parse_duration           (GstMessage * msg, GstClockTime * duration);
 
 GST_TRANSCODER_API
+void           gst_transcoder_message_parse_state              (GstMessage * msg, GstTranscoderState * state);
+
+GST_TRANSCODER_API
 void           gst_transcoder_message_parse_error              (GstMessage * msg, GError * error, GstStructure ** details);
 
 GST_TRANSCODER_API