mirror of
https://github.com/Rafostar/clapper.git
synced 2025-08-29 15:22:11 +02:00
gstclapper: Fix video/audio decoder change detection
The video/audio decoder changed signal was not working correctly in case of multiple streams with multiple decoders in single file. We need to listen to the current-(video/audio) signal, when it changes find corresponding "input-selector", get stream ID from its active pad and then find the decoder in the pipeline that handles this stream ID. Similarly for playbin3, but use stream ID from the "streams-selected" signal.
This commit is contained in:
170
lib/gst/clapper/gstclapper.c
vendored
170
lib/gst/clapper/gstclapper.c
vendored
@@ -253,6 +253,9 @@ static void gst_clapper_audio_info_update (GstClapper * self,
|
||||
static void gst_clapper_subtitle_info_update (GstClapper * self,
|
||||
GstClapperStreamInfo * stream_info);
|
||||
|
||||
static gboolean find_active_decoder_with_stream_id (GstClapper * self,
|
||||
GstElementFactoryListType type, const gchar * stream_id);
|
||||
|
||||
/* For playbin3 */
|
||||
static void gst_clapper_streams_info_create_from_collection (GstClapper * self,
|
||||
GstClapperMediaInfo * media_info, GstStreamCollection * collection);
|
||||
@@ -2050,6 +2053,7 @@ streams_selected_cb (G_GNUC_UNUSED GstBus * bus, GstMessage * msg,
|
||||
{
|
||||
GstClapper *self = GST_CLAPPER (user_data);
|
||||
GstStreamCollection *collection = NULL;
|
||||
gchar *video_sid, *audio_sid;
|
||||
guint i, len;
|
||||
|
||||
gst_message_parse_streams_selected (msg, &collection);
|
||||
@@ -2098,7 +2102,22 @@ streams_selected_cb (G_GNUC_UNUSED GstBus * bus, GstMessage * msg,
|
||||
|
||||
*current_sid = g_strdup (stream_id);
|
||||
}
|
||||
|
||||
video_sid = g_strdup (self->video_sid);
|
||||
audio_sid = g_strdup (self->audio_sid);
|
||||
|
||||
g_mutex_unlock (&self->lock);
|
||||
|
||||
if (video_sid) {
|
||||
find_active_decoder_with_stream_id (self, GST_ELEMENT_FACTORY_TYPE_DECODER
|
||||
| GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO, video_sid);
|
||||
g_free (video_sid);
|
||||
}
|
||||
if (audio_sid) {
|
||||
find_active_decoder_with_stream_id (self, GST_ELEMENT_FACTORY_TYPE_DECODER
|
||||
| GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO, audio_sid);
|
||||
g_free (audio_sid);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -3009,11 +3028,12 @@ decoder_changed_signal_data_free (DecoderChangedSignalData * data)
|
||||
|
||||
static void
|
||||
emit_decoder_changed (GstClapper * self, gchar * decoder_name,
|
||||
gboolean is_video)
|
||||
GstElementFactoryListType type)
|
||||
{
|
||||
GstClapperSignalDispatcherFunc func = NULL;
|
||||
|
||||
if (is_video) {
|
||||
if ((type & GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO) ==
|
||||
GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO) {
|
||||
if (g_signal_handler_find (self, G_SIGNAL_MATCH_ID,
|
||||
signals[SIGNAL_VIDEO_DECODER_CHANGED], 0, NULL, NULL, NULL) != 0 &&
|
||||
g_strcmp0 (self->last_vdecoder, decoder_name) != 0) {
|
||||
@@ -3021,7 +3041,8 @@ emit_decoder_changed (GstClapper * self, gchar * decoder_name,
|
||||
g_free (self->last_vdecoder);
|
||||
self->last_vdecoder = g_strdup (decoder_name);
|
||||
}
|
||||
} else {
|
||||
} else if ((type & GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO) ==
|
||||
GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO) {
|
||||
if (g_signal_handler_find (self, G_SIGNAL_MATCH_ID,
|
||||
signals[SIGNAL_AUDIO_DECODER_CHANGED], 0, NULL, NULL, NULL) != 0 &&
|
||||
g_strcmp0 (self->last_adecoder, decoder_name) != 0) {
|
||||
@@ -3042,6 +3063,137 @@ emit_decoder_changed (GstClapper * self, gchar * decoder_name,
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
iterate_decoder_pads (GstClapper * self, GstElement * element,
|
||||
const gchar * stream_id, GstElementFactoryListType type)
|
||||
{
|
||||
GstIterator *iter;
|
||||
GValue value = { 0, };
|
||||
gboolean found = FALSE;
|
||||
|
||||
iter = gst_element_iterate_src_pads (element);
|
||||
|
||||
while (gst_iterator_next (iter, &value) == GST_ITERATOR_OK) {
|
||||
GstPad *decoder_pad = g_value_get_object (&value);
|
||||
gchar *decoder_stream_id = gst_pad_get_stream_id (decoder_pad);
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Decoder stream: %s", decoder_stream_id);
|
||||
|
||||
/* In case of playbin3, pad may not be active yet */
|
||||
if ((found = (g_strcmp0 (decoder_stream_id, stream_id) == 0
|
||||
|| (!decoder_stream_id && self->use_playbin3)))) {
|
||||
GstElementFactory *factory;
|
||||
gchar *plugin_name;
|
||||
|
||||
factory = gst_element_get_factory (element);
|
||||
plugin_name = gst_object_get_name (GST_OBJECT_CAST (factory));
|
||||
|
||||
if (plugin_name) {
|
||||
GST_DEBUG_OBJECT (self, "Found decoder: %s", plugin_name);
|
||||
emit_decoder_changed (self, plugin_name, type);
|
||||
}
|
||||
|
||||
g_free (plugin_name);
|
||||
}
|
||||
|
||||
g_value_unset (&value);
|
||||
|
||||
if (found)
|
||||
break;
|
||||
}
|
||||
|
||||
gst_iterator_free (iter);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
find_active_decoder_with_stream_id (GstClapper * self, GstElementFactoryListType type,
|
||||
const gchar * stream_id)
|
||||
{
|
||||
GstIterator *iter;
|
||||
GValue value = { 0, };
|
||||
gboolean found = FALSE;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Searching for decoder with stream: %s", stream_id);
|
||||
|
||||
iter = gst_bin_iterate_recurse (GST_BIN (self->playbin));
|
||||
|
||||
while (gst_iterator_next (iter, &value) == GST_ITERATOR_OK) {
|
||||
GstElement *element = g_value_get_object (&value);
|
||||
GstElementFactory *factory = gst_element_get_factory (element);
|
||||
|
||||
if (factory && gst_element_factory_list_is_type (factory, type))
|
||||
found = iterate_decoder_pads (self, element, stream_id, type);
|
||||
|
||||
g_value_unset (&value);
|
||||
|
||||
if (found)
|
||||
break;
|
||||
}
|
||||
|
||||
gst_iterator_free (iter);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
static void
|
||||
update_current_decoder (GstClapper *self, GstElementFactoryListType type)
|
||||
{
|
||||
GstIterator *iter;
|
||||
GValue value = { 0, };
|
||||
|
||||
iter = gst_bin_iterate_all_by_element_factory_name (
|
||||
GST_BIN (self->playbin), "input-selector");
|
||||
|
||||
while (gst_iterator_next (iter, &value) == GST_ITERATOR_OK) {
|
||||
GstElement *element = g_value_get_object (&value);
|
||||
GstPad *active_pad;
|
||||
gboolean found = FALSE;
|
||||
|
||||
g_object_get (G_OBJECT (element), "active-pad", &active_pad, NULL);
|
||||
|
||||
if (active_pad) {
|
||||
gchar *stream_id;
|
||||
|
||||
stream_id = gst_pad_get_stream_id (active_pad);
|
||||
gst_object_unref (active_pad);
|
||||
|
||||
if (stream_id) {
|
||||
found = find_active_decoder_with_stream_id (self, type, stream_id);
|
||||
g_free (stream_id);
|
||||
}
|
||||
}
|
||||
|
||||
g_value_unset (&value);
|
||||
|
||||
if (found)
|
||||
break;
|
||||
}
|
||||
|
||||
gst_iterator_free (iter);
|
||||
}
|
||||
|
||||
static void
|
||||
current_video_notify_cb (G_GNUC_UNUSED GObject * obj, G_GNUC_UNUSED GParamSpec * pspec,
|
||||
GstClapper * self)
|
||||
{
|
||||
GstElementFactoryListType type = GST_ELEMENT_FACTORY_TYPE_DECODER
|
||||
| GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO;
|
||||
|
||||
update_current_decoder (self, type);
|
||||
}
|
||||
|
||||
static void
|
||||
current_audio_notify_cb (G_GNUC_UNUSED GObject * obj, G_GNUC_UNUSED GParamSpec * pspec,
|
||||
GstClapper * self)
|
||||
{
|
||||
GstElementFactoryListType type = GST_ELEMENT_FACTORY_TYPE_DECODER
|
||||
| GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO;
|
||||
|
||||
update_current_decoder (self, type);
|
||||
}
|
||||
|
||||
static void
|
||||
element_setup_cb (GstElement * playbin, GstElement * element, GstClapper * self)
|
||||
{
|
||||
@@ -3054,13 +3206,6 @@ element_setup_cb (GstElement * playbin, GstElement * element, GstClapper * self)
|
||||
if (plugin_name) {
|
||||
GST_INFO_OBJECT (self, "Plugin setup: %s", plugin_name);
|
||||
|
||||
if (gst_element_factory_list_is_type (factory,
|
||||
GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO))
|
||||
emit_decoder_changed (self, plugin_name, TRUE);
|
||||
else if (gst_element_factory_list_is_type (factory,
|
||||
GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO))
|
||||
emit_decoder_changed (self, plugin_name, FALSE);
|
||||
|
||||
/* TODO: Set plugin props */
|
||||
}
|
||||
g_free (plugin_name);
|
||||
@@ -3229,6 +3374,11 @@ gst_clapper_main (gpointer data)
|
||||
G_CALLBACK (audio_tags_changed_cb), self);
|
||||
g_signal_connect (self->playbin, "text-tags-changed",
|
||||
G_CALLBACK (subtitle_tags_changed_cb), self);
|
||||
|
||||
g_signal_connect (self->playbin, "notify::current-video",
|
||||
G_CALLBACK (current_video_notify_cb), self);
|
||||
g_signal_connect (self->playbin, "notify::current-audio",
|
||||
G_CALLBACK (current_audio_notify_cb), self);
|
||||
}
|
||||
|
||||
g_signal_connect (self->playbin, "notify::volume",
|
||||
|
Reference in New Issue
Block a user