transcoder: Add state-changed signal

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>
This commit is contained in:
Philippe Normand 2021-02-20 11:36:42 +00:00 committed by GStreamer Marge Bot
parent 12a7bf9f7c
commit a6b5e3c7d5
4 changed files with 110 additions and 1 deletions

View file

@ -25,6 +25,7 @@
#define GST_TRANSCODER_MESSAGE_DATA_TYPE "transcoder-message-type" #define GST_TRANSCODER_MESSAGE_DATA_TYPE "transcoder-message-type"
#define GST_TRANSCODER_MESSAGE_DATA_POSITION "position" #define GST_TRANSCODER_MESSAGE_DATA_POSITION "position"
#define GST_TRANSCODER_MESSAGE_DATA_DURATION "duration" #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_ERROR "error"
#define GST_TRANSCODER_MESSAGE_DATA_WARNING "warning" #define GST_TRANSCODER_MESSAGE_DATA_WARNING "warning"
#define GST_TRANSCODER_MESSAGE_DATA_ISSUE_DETAILS "issue-details" #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_sync_emit (GstTranscoder * transcoder);
GstTranscoderSignalAdapter * gst_transcoder_signal_adapter_new (GstTranscoder * transcoder, GMainContext * context); GstTranscoderSignalAdapter * gst_transcoder_signal_adapter_new (GstTranscoder * transcoder, GMainContext * context);

View file

@ -37,6 +37,7 @@ enum
{ {
SIGNAL_POSITION_UPDATED, SIGNAL_POSITION_UPDATED,
SIGNAL_DURATION_CHANGED, SIGNAL_DURATION_CHANGED,
SIGNAL_STATE_CHANGED,
SIGNAL_DONE, SIGNAL_DONE,
SIGNAL_ERROR, SIGNAL_ERROR,
SIGNAL_WARNING, SIGNAL_WARNING,
@ -94,6 +95,13 @@ gst_transcoder_signal_adapter_emit (GstTranscoderSignalAdapter * self,
g_signal_emit (self, signals[SIGNAL_DURATION_CHANGED], 0, duration); g_signal_emit (self, signals[SIGNAL_DURATION_CHANGED], 0, duration);
break; 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: case GST_TRANSCODER_MESSAGE_DONE:
g_signal_emit (self, signals[SIGNAL_DONE], 0); g_signal_emit (self, signals[SIGNAL_DONE], 0);
break; 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, 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); 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: * GstTranscoderSignalAdapter:transcoder:
* *

View file

@ -90,6 +90,8 @@ struct _GstTranscoder
GstClockTime last_duration; GstClockTime last_duration;
GstTranscoderState app_state;
GstBus *api_bus; GstBus *api_bus;
GstTranscoderSignalAdapter *signal_adapter; GstTranscoderSignalAdapter *signal_adapter;
GstTranscoderSignalAdapter *sync_signal_adapter; GstTranscoderSignalAdapter *sync_signal_adapter;
@ -589,6 +591,20 @@ warning_cb (G_GNUC_UNUSED GstBus * bus, GstMessage * msg, gpointer user_data)
g_free (message); g_free (message);
} }
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 static void
eos_cb (G_GNUC_UNUSED GstBus * bus, G_GNUC_UNUSED GstMessage * msg, eos_cb (G_GNUC_UNUSED GstBus * bus, G_GNUC_UNUSED GstMessage * msg,
gpointer user_data) gpointer user_data)
@ -602,6 +618,7 @@ eos_cb (G_GNUC_UNUSED GstBus * bus, G_GNUC_UNUSED GstMessage * msg,
tick_cb (self); tick_cb (self);
remove_tick_source (self); remove_tick_source (self);
notify_state_changed (self, GST_TRANSCODER_STATE_STOPPED);
api_bus_post_message (self, GST_TRANSCODER_MESSAGE_DONE, NULL, NULL); api_bus_post_message (self, GST_TRANSCODER_MESSAGE_DONE, NULL, NULL);
self->is_eos = TRUE; self->is_eos = TRUE;
} }
@ -654,9 +671,16 @@ state_changed_cb (G_GNUC_UNUSED GstBus * bus, GstMessage * msg,
self->current_state = new_state; 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 if (new_state == GST_STATE_PLAYING
&& pending_state == GST_STATE_VOID_PENDING) { && pending_state == GST_STATE_VOID_PENDING) {
add_tick_source (self); 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->current_state = GST_STATE_NULL;
self->is_eos = FALSE; self->is_eos = FALSE;
self->is_live = FALSE; self->is_live = FALSE;
self->app_state = GST_TRANSCODER_STATE_STOPPED;
GST_TRACE_OBJECT (self, "Starting main loop"); GST_TRACE_OBJECT (self, "Starting main loop");
g_main_loop_run (self->loop); g_main_loop_run (self->loop);
@ -1410,6 +1435,23 @@ gst_transcoder_message_parse_position (GstMessage * msg,
GST_TYPE_CLOCK_TIME, position); GST_TYPE_CLOCK_TIME, position);
} }
/**
* 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: * gst_transcoder_message_parse_error:
* @msg: A #GstMessage * @msg: A #GstMessage
@ -1449,3 +1491,29 @@ gst_transcoder_message_parse_warning (GstMessage * msg, GError * error,
PARSE_MESSAGE_FIELD (msg, GST_TRANSCODER_MESSAGE_DATA_ISSUE_DETAILS, PARSE_MESSAGE_FIELD (msg, GST_TRANSCODER_MESSAGE_DATA_ISSUE_DETAILS,
GST_TYPE_STRUCTURE, 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;
}

View file

@ -28,12 +28,35 @@ GQuark gst_transcoder_error_quark (void);
GST_TRANSCODER_API GST_TRANSCODER_API
const gchar * gst_transcoder_error_get_name (GstTranscoderError error); 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 ************/ /*********** Messages types definitions ************/
/** /**
* GstTranscoderMessage: * GstTranscoderMessage:
* @GST_TRANSCODER_MESSAGE_POSITION_UPDATED: Sink position changed * @GST_TRANSCODER_MESSAGE_POSITION_UPDATED: Sink position changed
* @GST_TRANSCODER_MESSAGE_DURATION_CHANGED: Duration of stream 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_DONE: Transcoding is done
* @GST_TRANSCODER_MESSAGE_ERROR: Message contains an error * @GST_TRANSCODER_MESSAGE_ERROR: Message contains an error
* @GST_TRANSCODER_MESSAGE_WARNING: 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_POSITION_UPDATED,
GST_TRANSCODER_MESSAGE_DURATION_CHANGED, GST_TRANSCODER_MESSAGE_DURATION_CHANGED,
GST_TRANSCODER_MESSAGE_STATE_CHANGED,
GST_TRANSCODER_MESSAGE_DONE, GST_TRANSCODER_MESSAGE_DONE,
GST_TRANSCODER_MESSAGE_ERROR, GST_TRANSCODER_MESSAGE_ERROR,
GST_TRANSCODER_MESSAGE_WARNING, GST_TRANSCODER_MESSAGE_WARNING,
@ -65,6 +89,9 @@ void gst_transcoder_message_parse_position (GstMessage * msg
GST_TRANSCODER_API GST_TRANSCODER_API
void gst_transcoder_message_parse_duration (GstMessage * msg, GstClockTime * duration); 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 GST_TRANSCODER_API
void gst_transcoder_message_parse_error (GstMessage * msg, GError * error, GstStructure ** details); void gst_transcoder_message_parse_error (GstMessage * msg, GError * error, GstStructure ** details);