summaryrefslogtreecommitdiff
path: root/gst-libs
diff options
context:
space:
mode:
authorPhilippe Normand <philn@igalia.com>2020-12-07 10:47:30 +0000
committerPhilippe Normand <philn@igalia.com>2021-03-09 18:03:48 +0000
commit12a7bf9f7c3229b0f911c9c5510c3d833bf194a0 (patch)
treea6faeec70c4a7f2bcb12d80b48d5b90a39521610 /gst-libs
parentf009802771a9a0eec3ce84abee9fd207acfb0213 (diff)
downloadgstreamer-plugins-bad-12a7bf9f7c3229b0f911c9c5510c3d833bf194a0.tar.gz
player: Rewrite as GstPlay wrapper
For the time being the GstPlayer library remains as a wrapper for GstPlay, in order to keep existing applications working and give them time to port to GstPlay. GstPlayer will remain in -bad for a couple cycles and the plan for GstPlay is to move it to -base before 1.20. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/2061>
Diffstat (limited to 'gst-libs')
-rw-r--r--gst-libs/gst/play/gstplay-signal-adapter.c4
-rw-r--r--gst-libs/gst/player/gstplayer-media-info-private.h57
-rw-r--r--gst-libs/gst/player/gstplayer-media-info.c246
-rw-r--r--gst-libs/gst/player/gstplayer-wrapped-video-renderer-private.h49
-rw-r--r--gst-libs/gst/player/gstplayer-wrapped-video-renderer.c114
-rw-r--r--gst-libs/gst/player/gstplayer.c3449
-rw-r--r--gst-libs/gst/player/meson.build7
7 files changed, 497 insertions, 3429 deletions
diff --git a/gst-libs/gst/play/gstplay-signal-adapter.c b/gst-libs/gst/play/gstplay-signal-adapter.c
index 24b7e6bae..cc5f0e0ce 100644
--- a/gst-libs/gst/play/gstplay-signal-adapter.c
+++ b/gst-libs/gst/play/gstplay-signal-adapter.c
@@ -439,12 +439,12 @@ gst_play_signal_adapter_class_init (GstPlaySignalAdapterClass * klass)
signals[SIGNAL_VOLUME_CHANGED] =
g_signal_new ("volume-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, 0, G_TYPE_INVALID);
+ NULL, NULL, G_TYPE_NONE, 1, G_TYPE_DOUBLE);
signals[SIGNAL_MUTE_CHANGED] =
g_signal_new ("mute-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, 0, G_TYPE_INVALID);
+ NULL, NULL, G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
signals[SIGNAL_WARNING] =
g_signal_new ("warning", G_TYPE_FROM_CLASS (klass),
diff --git a/gst-libs/gst/player/gstplayer-media-info-private.h b/gst-libs/gst/player/gstplayer-media-info-private.h
index 70aaea925..1075ef92f 100644
--- a/gst-libs/gst/player/gstplayer-media-info-private.h
+++ b/gst-libs/gst/player/gstplayer-media-info-private.h
@@ -23,16 +23,14 @@
#ifndef __GST_PLAYER_MEDIA_INFO_PRIVATE_H__
#define __GST_PLAYER_MEDIA_INFO_PRIVATE_H__
+#include <gst/play/gstplay-media-info.h>
+
struct _GstPlayerStreamInfo
{
GObject parent;
- gchar *codec;
-
- GstCaps *caps;
gint stream_index;
- GstTagList *tags;
- gchar *stream_id;
+ GstPlayStreamInfo *info;
};
struct _GstPlayerStreamInfoClass
@@ -42,9 +40,9 @@ struct _GstPlayerStreamInfoClass
struct _GstPlayerSubtitleInfo
{
- GstPlayerStreamInfo parent;
+ GstPlayerStreamInfo parent;
- gchar *language;
+ GstPlaySubtitleInfo *info;
};
struct _GstPlayerSubtitleInfoClass
@@ -54,15 +52,9 @@ struct _GstPlayerSubtitleInfoClass
struct _GstPlayerAudioInfo
{
- GstPlayerStreamInfo parent;
-
- gint channels;
- gint sample_rate;
-
- guint bitrate;
- guint max_bitrate;
+ GstPlayerStreamInfo parent;
- gchar *language;
+ GstPlayAudioInfo *info;
};
struct _GstPlayerAudioInfoClass
@@ -72,17 +64,9 @@ struct _GstPlayerAudioInfoClass
struct _GstPlayerVideoInfo
{
- GstPlayerStreamInfo parent;
+ GstPlayerStreamInfo parent;
- gint width;
- gint height;
- gint framerate_num;
- gint framerate_denom;
- gint par_num;
- gint par_denom;
-
- guint bitrate;
- guint max_bitrate;
+ GstPlayVideoInfo *info;
};
struct _GstPlayerVideoInfoClass
@@ -94,19 +78,11 @@ struct _GstPlayerMediaInfo
{
GObject parent;
- gchar *uri;
- gchar *title;
- gchar *container;
- gboolean seekable, is_live;
- GstTagList *tags;
- GstSample *image_sample;
-
GList *stream_list;
GList *audio_stream_list;
GList *video_stream_list;
GList *subtitle_stream_list;
-
- GstClockTime duration;
+ GstPlayMediaInfo *info;
};
struct _GstPlayerMediaInfoClass
@@ -115,12 +91,23 @@ struct _GstPlayerMediaInfoClass
};
G_GNUC_INTERNAL GstPlayerMediaInfo* gst_player_media_info_new
- (const gchar *uri);
+ (void);
G_GNUC_INTERNAL GstPlayerMediaInfo* gst_player_media_info_copy
(GstPlayerMediaInfo *ref);
G_GNUC_INTERNAL GstPlayerStreamInfo* gst_player_stream_info_new
(gint stream_index, GType type);
+G_GNUC_INTERNAL GstPlayerStreamInfo* gst_player_stream_info_wrapped
+ (GstPlayStreamInfo * info);
G_GNUC_INTERNAL GstPlayerStreamInfo* gst_player_stream_info_copy
(GstPlayerStreamInfo *ref);
+G_GNUC_INTERNAL GstPlayerMediaInfo* gst_player_media_info_wrapped
+ (GstPlayMediaInfo *info);
+G_GNUC_INTERNAL GstPlayerAudioInfo* gst_player_audio_info_wrapped
+ (GstPlayAudioInfo *info);
+G_GNUC_INTERNAL GstPlayerVideoInfo* gst_player_video_info_wrapped
+ (GstPlayVideoInfo *info);
+G_GNUC_INTERNAL GstPlayerSubtitleInfo* gst_player_subtitle_info_wrapped
+ (GstPlaySubtitleInfo *info);
+
#endif /* __GST_PLAYER_MEDIA_INFO_PRIVATE_H__ */
diff --git a/gst-libs/gst/player/gstplayer-media-info.c b/gst-libs/gst/player/gstplayer-media-info.c
index 6c9a4a887..c805ebea0 100644
--- a/gst-libs/gst/player/gstplayer-media-info.c
+++ b/gst-libs/gst/player/gstplayer-media-info.c
@@ -47,14 +47,7 @@ gst_player_stream_info_finalize (GObject * object)
{
GstPlayerStreamInfo *sinfo = GST_PLAYER_STREAM_INFO (object);
- g_free (sinfo->codec);
- g_free (sinfo->stream_id);
-
- if (sinfo->caps)
- gst_caps_unref (sinfo->caps);
-
- if (sinfo->tags)
- gst_tag_list_unref (sinfo->tags);
+ g_clear_object (&sinfo->info);
G_OBJECT_CLASS (gst_player_stream_info_parent_class)->finalize (object);
}
@@ -97,12 +90,7 @@ gst_player_stream_info_get_stream_type (const GstPlayerStreamInfo * info)
{
g_return_val_if_fail (GST_IS_PLAYER_STREAM_INFO (info), NULL);
- if (GST_IS_PLAYER_VIDEO_INFO (info))
- return "video";
- else if (GST_IS_PLAYER_AUDIO_INFO (info))
- return "audio";
- else
- return "subtitle";
+ return gst_play_stream_info_get_stream_type (info->info);
}
/**
@@ -116,7 +104,7 @@ gst_player_stream_info_get_tags (const GstPlayerStreamInfo * info)
{
g_return_val_if_fail (GST_IS_PLAYER_STREAM_INFO (info), NULL);
- return info->tags;
+ return gst_play_stream_info_get_tags (info->info);
}
/**
@@ -132,7 +120,7 @@ gst_player_stream_info_get_codec (const GstPlayerStreamInfo * info)
{
g_return_val_if_fail (GST_IS_PLAYER_STREAM_INFO (info), NULL);
- return info->codec;
+ return gst_play_stream_info_get_codec (info->info);
}
/**
@@ -146,7 +134,7 @@ gst_player_stream_info_get_caps (const GstPlayerStreamInfo * info)
{
g_return_val_if_fail (GST_IS_PLAYER_STREAM_INFO (info), NULL);
- return info->caps;
+ return gst_play_stream_info_get_caps (info->info);
}
/* Video information */
@@ -154,14 +142,9 @@ G_DEFINE_TYPE (GstPlayerVideoInfo, gst_player_video_info,
GST_TYPE_PLAYER_STREAM_INFO);
static void
-gst_player_video_info_init (GstPlayerVideoInfo * info)
+gst_player_video_info_init (G_GNUC_UNUSED GstPlayerVideoInfo * info)
{
- info->width = -1;
- info->height = -1;
- info->framerate_num = 0;
- info->framerate_denom = 1;
- info->par_num = 1;
- info->par_denom = 1;
+
}
static void
@@ -181,7 +164,7 @@ gst_player_video_info_get_width (const GstPlayerVideoInfo * info)
{
g_return_val_if_fail (GST_IS_PLAYER_VIDEO_INFO (info), -1);
- return info->width;
+ return gst_play_video_info_get_width (info->info);
}
/**
@@ -195,7 +178,7 @@ gst_player_video_info_get_height (const GstPlayerVideoInfo * info)
{
g_return_val_if_fail (GST_IS_PLAYER_VIDEO_INFO (info), -1);
- return info->height;
+ return gst_play_video_info_get_height (info->info);
}
/**
@@ -211,8 +194,7 @@ gst_player_video_info_get_framerate (const GstPlayerVideoInfo * info,
{
g_return_if_fail (GST_IS_PLAYER_VIDEO_INFO (info));
- *fps_n = info->framerate_num;
- *fps_d = info->framerate_denom;
+ gst_play_video_info_get_framerate (info->info, fps_n, fps_d);
}
/**
@@ -230,8 +212,7 @@ gst_player_video_info_get_pixel_aspect_ratio (const GstPlayerVideoInfo * info,
{
g_return_if_fail (GST_IS_PLAYER_VIDEO_INFO (info));
- *par_n = info->par_num;
- *par_d = info->par_denom;
+ gst_play_video_info_get_pixel_aspect_ratio (info->info, par_n, par_d);
}
/**
@@ -245,7 +226,7 @@ gst_player_video_info_get_bitrate (const GstPlayerVideoInfo * info)
{
g_return_val_if_fail (GST_IS_PLAYER_VIDEO_INFO (info), -1);
- return info->bitrate;
+ return gst_play_video_info_get_bitrate (info->info);
}
/**
@@ -259,7 +240,7 @@ gst_player_video_info_get_max_bitrate (const GstPlayerVideoInfo * info)
{
g_return_val_if_fail (GST_IS_PLAYER_VIDEO_INFO (info), -1);
- return info->max_bitrate;
+ return gst_play_video_info_get_max_bitrate (info->info);
}
/* Audio information */
@@ -267,12 +248,9 @@ G_DEFINE_TYPE (GstPlayerAudioInfo, gst_player_audio_info,
GST_TYPE_PLAYER_STREAM_INFO);
static void
-gst_player_audio_info_init (GstPlayerAudioInfo * info)
+gst_player_audio_info_init (G_GNUC_UNUSED GstPlayerAudioInfo * info)
{
- info->channels = 0;
- info->sample_rate = 0;
- info->bitrate = -1;
- info->max_bitrate = -1;
+
}
static void
@@ -280,7 +258,7 @@ gst_player_audio_info_finalize (GObject * object)
{
GstPlayerAudioInfo *info = GST_PLAYER_AUDIO_INFO (object);
- g_free (info->language);
+ g_clear_object (&info->info);
G_OBJECT_CLASS (gst_player_audio_info_parent_class)->finalize (object);
}
@@ -304,7 +282,7 @@ gst_player_audio_info_get_language (const GstPlayerAudioInfo * info)
{
g_return_val_if_fail (GST_IS_PLAYER_AUDIO_INFO (info), NULL);
- return info->language;
+ return gst_play_audio_info_get_language (info->info);
}
/**
@@ -318,7 +296,7 @@ gst_player_audio_info_get_channels (const GstPlayerAudioInfo * info)
{
g_return_val_if_fail (GST_IS_PLAYER_AUDIO_INFO (info), 0);
- return info->channels;
+ return gst_play_audio_info_get_channels (info->info);
}
/**
@@ -332,7 +310,7 @@ gst_player_audio_info_get_sample_rate (const GstPlayerAudioInfo * info)
{
g_return_val_if_fail (GST_IS_PLAYER_AUDIO_INFO (info), 0);
- return info->sample_rate;
+ return gst_play_audio_info_get_sample_rate (info->info);
}
/**
@@ -346,7 +324,7 @@ gst_player_audio_info_get_bitrate (const GstPlayerAudioInfo * info)
{
g_return_val_if_fail (GST_IS_PLAYER_AUDIO_INFO (info), -1);
- return info->bitrate;
+ return gst_play_audio_info_get_bitrate (info->info);
}
/**
@@ -360,7 +338,7 @@ gst_player_audio_info_get_max_bitrate (const GstPlayerAudioInfo * info)
{
g_return_val_if_fail (GST_IS_PLAYER_AUDIO_INFO (info), -1);
- return info->max_bitrate;
+ return gst_play_audio_info_get_max_bitrate (info->info);
}
/* Subtitle information */
@@ -378,7 +356,7 @@ gst_player_subtitle_info_finalize (GObject * object)
{
GstPlayerSubtitleInfo *info = GST_PLAYER_SUBTITLE_INFO (object);
- g_free (info->language);
+ g_clear_object (&info->info);
G_OBJECT_CLASS (gst_player_subtitle_info_parent_class)->finalize (object);
}
@@ -402,18 +380,16 @@ gst_player_subtitle_info_get_language (const GstPlayerSubtitleInfo * info)
{
g_return_val_if_fail (GST_IS_PLAYER_SUBTITLE_INFO (info), NULL);
- return info->language;
+ return gst_play_subtitle_info_get_language (info->info);
}
/* Global media information */
G_DEFINE_TYPE (GstPlayerMediaInfo, gst_player_media_info, G_TYPE_OBJECT);
static void
-gst_player_media_info_init (GstPlayerMediaInfo * info)
+gst_player_media_info_init (G_GNUC_UNUSED GstPlayerMediaInfo * info)
{
- info->duration = -1;
- info->is_live = FALSE;
- info->seekable = FALSE;
+
}
static void
@@ -421,18 +397,6 @@ gst_player_media_info_finalize (GObject * object)
{
GstPlayerMediaInfo *info = GST_PLAYER_MEDIA_INFO (object);
- g_free (info->uri);
-
- if (info->tags)
- gst_tag_list_unref (info->tags);
-
- g_free (info->title);
-
- g_free (info->container);
-
- if (info->image_sample)
- gst_sample_unref (info->image_sample);
-
if (info->audio_stream_list)
g_list_free (info->audio_stream_list);
@@ -444,6 +408,7 @@ gst_player_media_info_finalize (GObject * object)
if (info->stream_list)
g_list_free_full (info->stream_list, g_object_unref);
+ g_clear_object (&info->info);
G_OBJECT_CLASS (gst_player_media_info_parent_class)->finalize (object);
}
@@ -480,15 +445,7 @@ gst_player_video_info_copy (GstPlayerVideoInfo * ref)
GstPlayerVideoInfo *ret;
ret = gst_player_video_info_new ();
-
- ret->width = ref->width;
- ret->height = ref->height;
- ret->framerate_num = ref->framerate_num;
- ret->framerate_denom = ref->framerate_denom;
- ret->par_num = ref->par_num;
- ret->par_denom = ref->par_denom;
- ret->bitrate = ref->bitrate;
- ret->max_bitrate = ref->max_bitrate;
+ ret->info = g_object_ref (ref->info);
return (GstPlayerStreamInfo *) ret;
}
@@ -499,14 +456,7 @@ gst_player_audio_info_copy (GstPlayerAudioInfo * ref)
GstPlayerAudioInfo *ret;
ret = gst_player_audio_info_new ();
-
- ret->sample_rate = ref->sample_rate;
- ret->channels = ref->channels;
- ret->bitrate = ref->bitrate;
- ret->max_bitrate = ref->max_bitrate;
-
- if (ref->language)
- ret->language = g_strdup (ref->language);
+ ret->info = g_object_ref (ref->info);
return (GstPlayerStreamInfo *) ret;
}
@@ -517,8 +467,7 @@ gst_player_subtitle_info_copy (GstPlayerSubtitleInfo * ref)
GstPlayerSubtitleInfo *ret;
ret = gst_player_subtitle_info_new ();
- if (ref->language)
- ret->language = g_strdup (ref->language);
+ ret->info = g_object_ref (ref->info);
return (GstPlayerStreamInfo *) ret;
}
@@ -539,14 +488,6 @@ gst_player_stream_info_copy (GstPlayerStreamInfo * ref)
info = gst_player_subtitle_info_copy ((GstPlayerSubtitleInfo *) ref);
info->stream_index = ref->stream_index;
- if (ref->tags)
- info->tags = gst_tag_list_ref (ref->tags);
- if (ref->caps)
- info->caps = gst_caps_copy (ref->caps);
- if (ref->codec)
- info->codec = g_strdup (ref->codec);
- if (ref->stream_id)
- info->stream_id = g_strdup (ref->stream_id);
return info;
}
@@ -560,20 +501,9 @@ gst_player_media_info_copy (GstPlayerMediaInfo * ref)
if (!ref)
return NULL;
- info = gst_player_media_info_new (ref->uri);
- info->duration = ref->duration;
- info->seekable = ref->seekable;
- info->is_live = ref->is_live;
- if (ref->tags)
- info->tags = gst_tag_list_ref (ref->tags);
- if (ref->title)
- info->title = g_strdup (ref->title);
- if (ref->container)
- info->container = g_strdup (ref->container);
- if (ref->image_sample)
- info->image_sample = gst_sample_ref (ref->image_sample);
-
- for (l = ref->stream_list; l != NULL; l = l->next) {
+ info = gst_player_media_info_new ();
+
+ for (l = gst_player_media_info_get_stream_list (ref); l != NULL; l = l->next) {
GstPlayerStreamInfo *s;
s = gst_player_stream_info_copy ((GstPlayerStreamInfo *) l->data);
@@ -588,6 +518,8 @@ gst_player_media_info_copy (GstPlayerMediaInfo * ref)
g_list_append (info->subtitle_stream_list, s);
}
+ info->info = g_object_ref (ref->info);
+
return info;
}
@@ -608,17 +540,99 @@ gst_player_stream_info_new (gint stream_index, GType type)
return info;
}
+GstPlayerStreamInfo *
+gst_player_stream_info_wrapped (GstPlayStreamInfo * info)
+{
+ GstPlayerStreamInfo *ret;
+ GType type;
+
+ if (GST_IS_PLAY_AUDIO_INFO (info)) {
+ type = GST_TYPE_PLAYER_AUDIO_INFO;
+ } else if (GST_IS_PLAY_VIDEO_INFO (info)) {
+ type = GST_TYPE_PLAYER_VIDEO_INFO;
+ } else {
+ type = GST_TYPE_PLAYER_SUBTITLE_INFO;
+ }
+
+ ret =
+ gst_player_stream_info_new (gst_play_stream_info_get_index (info), type);
+ ret->info = g_object_ref (info);
+ return ret;
+}
+
GstPlayerMediaInfo *
-gst_player_media_info_new (const gchar * uri)
+gst_player_media_info_new (void)
{
- GstPlayerMediaInfo *info;
+ return g_object_new (GST_TYPE_PLAYER_MEDIA_INFO, NULL);
+}
- g_return_val_if_fail (uri != NULL, NULL);
+GstPlayerMediaInfo *
+gst_player_media_info_wrapped (GstPlayMediaInfo * info)
+{
+ GstPlayerMediaInfo *ret;
+ GList *l;
- info = g_object_new (GST_TYPE_PLAYER_MEDIA_INFO, NULL);
- info->uri = g_strdup (uri);
+ ret = gst_player_media_info_new ();
+ ret->info = g_object_ref (info);
- return info;
+ for (l = gst_play_media_info_get_stream_list (info); l != NULL; l = l->next) {
+ GstPlayerStreamInfo *s;
+
+ s = gst_player_stream_info_wrapped ((GstPlayStreamInfo *) l->data);
+ ret->stream_list = g_list_append (ret->stream_list, s);
+
+ if (GST_IS_PLAYER_AUDIO_INFO (s)) {
+ GstPlayerAudioInfo *i = GST_PLAYER_AUDIO_INFO (s);
+ i->info = g_object_ref (GST_PLAY_AUDIO_INFO (l->data));
+ ret->audio_stream_list = g_list_append (ret->audio_stream_list, i);
+ } else if (GST_IS_PLAYER_VIDEO_INFO (s)) {
+ GstPlayerVideoInfo *i = GST_PLAYER_VIDEO_INFO (s);
+ i->info = g_object_ref (GST_PLAY_VIDEO_INFO (l->data));
+ ret->video_stream_list = g_list_append (ret->video_stream_list, i);
+ } else {
+ GstPlayerSubtitleInfo *i = GST_PLAYER_SUBTITLE_INFO (s);
+ i->info = g_object_ref (GST_PLAY_SUBTITLE_INFO (l->data));
+ ret->subtitle_stream_list = g_list_append (ret->subtitle_stream_list, i);
+ }
+ }
+
+ return ret;
+}
+
+GstPlayerAudioInfo *
+gst_player_audio_info_wrapped (GstPlayAudioInfo * info)
+{
+ GstPlayerStreamInfo *s;
+ GstPlayerAudioInfo *i;
+
+ s = gst_player_stream_info_wrapped ((GstPlayStreamInfo *) info);
+ i = GST_PLAYER_AUDIO_INFO (s);
+ i->info = g_object_ref (info);
+ return i;
+}
+
+GstPlayerVideoInfo *
+gst_player_video_info_wrapped (GstPlayVideoInfo * info)
+{
+ GstPlayerStreamInfo *s;
+ GstPlayerVideoInfo *i;
+
+ s = gst_player_stream_info_wrapped ((GstPlayStreamInfo *) info);
+ i = GST_PLAYER_VIDEO_INFO (s);
+ i->info = g_object_ref (info);
+ return i;
+}
+
+GstPlayerSubtitleInfo *
+gst_player_subtitle_info_wrapped (GstPlaySubtitleInfo * info)
+{
+ GstPlayerStreamInfo *s;
+ GstPlayerSubtitleInfo *i;
+
+ s = gst_player_stream_info_wrapped ((GstPlayStreamInfo *) info);
+ i = GST_PLAYER_SUBTITLE_INFO (s);
+ i->info = g_object_ref (info);
+ return i;
}
/**
@@ -632,7 +646,7 @@ gst_player_media_info_get_uri (const GstPlayerMediaInfo * info)
{
g_return_val_if_fail (GST_IS_PLAYER_MEDIA_INFO (info), NULL);
- return info->uri;
+ return gst_play_media_info_get_uri (info->info);
}
/**
@@ -646,7 +660,7 @@ gst_player_media_info_is_seekable (const GstPlayerMediaInfo * info)
{
g_return_val_if_fail (GST_IS_PLAYER_MEDIA_INFO (info), FALSE);
- return info->seekable;
+ return gst_play_media_info_is_seekable (info->info);
}
/**
@@ -660,7 +674,7 @@ gst_player_media_info_is_live (const GstPlayerMediaInfo * info)
{
g_return_val_if_fail (GST_IS_PLAYER_MEDIA_INFO (info), FALSE);
- return info->is_live;
+ return gst_play_media_info_is_live (info->info);
}
/**
@@ -734,7 +748,7 @@ gst_player_media_info_get_duration (const GstPlayerMediaInfo * info)
{
g_return_val_if_fail (GST_IS_PLAYER_MEDIA_INFO (info), -1);
- return info->duration;
+ return gst_play_media_info_get_duration (info->info);
}
/**
@@ -748,7 +762,7 @@ gst_player_media_info_get_tags (const GstPlayerMediaInfo * info)
{
g_return_val_if_fail (GST_IS_PLAYER_MEDIA_INFO (info), NULL);
- return info->tags;
+ return gst_play_media_info_get_tags (info->info);
}
/**
@@ -762,7 +776,7 @@ gst_player_media_info_get_title (const GstPlayerMediaInfo * info)
{
g_return_val_if_fail (GST_IS_PLAYER_MEDIA_INFO (info), NULL);
- return info->title;
+ return gst_play_media_info_get_title (info->info);
}
/**
@@ -776,7 +790,7 @@ gst_player_media_info_get_container_format (const GstPlayerMediaInfo * info)
{
g_return_val_if_fail (GST_IS_PLAYER_MEDIA_INFO (info), NULL);
- return info->container;
+ return gst_play_media_info_get_container_format (info->info);
}
/**
@@ -793,7 +807,7 @@ gst_player_media_info_get_image_sample (const GstPlayerMediaInfo * info)
{
g_return_val_if_fail (GST_IS_PLAYER_MEDIA_INFO (info), NULL);
- return info->image_sample;
+ return gst_play_media_info_get_image_sample (info->info);
}
/**
diff --git a/gst-libs/gst/player/gstplayer-wrapped-video-renderer-private.h b/gst-libs/gst/player/gstplayer-wrapped-video-renderer-private.h
new file mode 100644
index 000000000..99fd155bc
--- /dev/null
+++ b/gst-libs/gst/player/gstplayer-wrapped-video-renderer-private.h
@@ -0,0 +1,49 @@
+/* GStreamer
+ *
+ * Copyright (C) 2020 Philippe Normand <philn@igalia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GST_PLAYER_WRAPPED_VIDEO_RENDERER_H__
+#define __GST_PLAYER_WRAPPED_VIDEO_RENDERER_H__
+
+#include <gst/player/gstplayer-types.h>
+#include <gst/player/gstplayer-video-renderer.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GstPlayerWrappedVideoRenderer
+ GstPlayerWrappedVideoRenderer;
+typedef struct _GstPlayerWrappedVideoRendererClass
+ GstPlayerWrappedVideoRendererClass;
+
+#define GST_TYPE_PLAYER_WRAPPED_VIDEO_RENDERER (gst_player_wrapped_video_renderer_get_type ())
+#define GST_IS_PLAYER_WRAPPED_VIDEO_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PLAYER_WRAPPED_VIDEO_RENDERER))
+#define GST_IS_PLAYER_WRAPPED_VIDEO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PLAYER_WRAPPED_VIDEO_RENDERER))
+#define GST_PLAYER_WRAPPED_VIDEO_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_PLAYER_WRAPPED_VIDEO_RENDERER, GstPlayerWrappedVideoRendererClass))
+#define GST_PLAYER_WRAPPED_VIDEO_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PLAYER_WRAPPED_VIDEO_RENDERER, GstPlayerWrappedVideoRenderer))
+#define GST_PLAYER_WRAPPED_VIDEO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_PLAYER_WRAPPED_VIDEO_RENDERER, GstPlayerWrappedVideoRendererClass))
+#define GST_PLAYER_WRAPPED_VIDEO_RENDERER_CAST(obj) ((GstPlayerWrappedVideoRenderer*)(obj))
+
+GType gst_player_wrapped_video_renderer_get_type (void);
+
+GstPlayerVideoRenderer * gst_player_wrapped_video_renderer_new (GstPlayerVideoRenderer * renderer, GstPlayer * player);
+
+
+G_END_DECLS
+
+#endif /* __GST_PLAYER_WRAPPED_VIDEO_RENDERER_H__ */
diff --git a/gst-libs/gst/player/gstplayer-wrapped-video-renderer.c b/gst-libs/gst/player/gstplayer-wrapped-video-renderer.c
new file mode 100644
index 000000000..a54f1df97
--- /dev/null
+++ b/gst-libs/gst/player/gstplayer-wrapped-video-renderer.c
@@ -0,0 +1,114 @@
+/* GStreamer
+ *
+ * Copyright (C) 2020 Philippe Normand <philn@igalia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/play/gstplay-video-renderer.h>
+
+#include "gstplayer-wrapped-video-renderer-private.h"
+#include "gstplayer.h"
+#include "gstplayer-video-renderer-private.h"
+
+/*
+ * This object is an internal wrapper created by the GstPlayer, implementing the
+ * new GstPlayVideoRenderer interface and acting as a bridge from the legacy
+ * GstPlayerVideoRenderer interface.
+ */
+
+struct _GstPlayerWrappedVideoRenderer
+{
+ GObject parent;
+
+ GstPlayerVideoRenderer *renderer;
+ GstPlayer *player;
+};
+
+struct _GstPlayerWrappedVideoRendererClass
+{
+ GObjectClass parent_class;
+};
+
+static void
+ gst_player_wrapped_video_renderer_interface_init
+ (GstPlayVideoRendererInterface * iface);
+
+G_DEFINE_TYPE_WITH_CODE (GstPlayerWrappedVideoRenderer,
+ gst_player_wrapped_video_renderer, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (GST_TYPE_PLAY_VIDEO_RENDERER,
+ gst_player_wrapped_video_renderer_interface_init));
+
+static void
+gst_player_wrapped_video_renderer_finalize (GObject * object)
+{
+ GstPlayerWrappedVideoRenderer *self =
+ GST_PLAYER_WRAPPED_VIDEO_RENDERER (object);
+
+ g_clear_object (&self->renderer);
+
+ G_OBJECT_CLASS
+ (gst_player_wrapped_video_renderer_parent_class)->finalize (object);
+}
+
+static void
+gst_player_wrapped_video_renderer_class_init (GstPlayerWrappedVideoRendererClass
+ * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = gst_player_wrapped_video_renderer_finalize;
+}
+
+static void
+gst_player_wrapped_video_renderer_init (GstPlayerWrappedVideoRenderer * self)
+{
+}
+
+static GstElement *
+gst_player_wrapped_video_renderer_create_video_sink (GstPlayVideoRenderer *
+ iface, GstPlay * player)
+{
+ GstPlayerWrappedVideoRenderer *self =
+ GST_PLAYER_WRAPPED_VIDEO_RENDERER (iface);
+
+ return gst_player_video_renderer_create_video_sink (self->renderer,
+ self->player);
+}
+
+static void
+gst_player_wrapped_video_renderer_interface_init (GstPlayVideoRendererInterface
+ * iface)
+{
+ iface->create_video_sink =
+ gst_player_wrapped_video_renderer_create_video_sink;
+}
+
+GstPlayerVideoRenderer *
+gst_player_wrapped_video_renderer_new (GstPlayerVideoRenderer * renderer,
+ GstPlayer * player)
+{
+ GstPlayerWrappedVideoRenderer *self =
+ g_object_new (GST_TYPE_PLAYER_WRAPPED_VIDEO_RENDERER,
+ NULL);
+ self->renderer = g_object_ref (renderer);
+ self->player = player;
+ return (GstPlayerVideoRenderer *) self;
+}
diff --git a/gst-libs/gst/player/gstplayer.c b/gst-libs/gst/player/gstplayer.c
index 07b7ae2ba..a1eea9f58 100644
--- a/gst-libs/gst/player/gstplayer.c
+++ b/gst-libs/gst/player/gstplayer.c
@@ -26,6 +26,8 @@
* @symbols:
* - GstPlayer
*
+ * Starting from GStreamer 1.20, application developers are strongly advised to migrate to #GstPlay.
+ * #GstPlayer will be deprecated in 1.20 and most likely removed by 1.24.
*/
/* TODO:
@@ -49,8 +51,10 @@
#include "gstplayer-signal-dispatcher-private.h"
#include "gstplayer-video-renderer-private.h"
#include "gstplayer-media-info-private.h"
+#include "gstplayer-wrapped-video-renderer-private.h"
#include <gst/gst.h>
+#include <gst/play/play.h>
#include <gst/video/video.h>
#include <gst/video/colorbalance.h>
#include <gst/tag/tag.h>
@@ -144,67 +148,15 @@ enum
SIGNAL_LAST
};
-enum
-{
- GST_PLAY_FLAG_VIDEO = (1 << 0),
- GST_PLAY_FLAG_AUDIO = (1 << 1),
- GST_PLAY_FLAG_SUBTITLE = (1 << 2),
- GST_PLAY_FLAG_VIS = (1 << 3)
-};
-
struct _GstPlayer
{
GstObject parent;
- GstPlayerVideoRenderer *video_renderer;
- GstPlayerSignalDispatcher *signal_dispatcher;
+ GstPlay *play;
+ GstPlaySignalAdapter *signal_adapter;
- gchar *uri;
- gchar *redirect_uri;
- gchar *suburi;
-
- GThread *thread;
- GMutex lock;
- GCond cond;
- GMainContext *context;
- GMainLoop *loop;
-
- GstElement *playbin;
- GstBus *bus;
- GstState target_state, current_state;
- gboolean is_live, is_eos;
- GSource *tick_source, *ready_timeout_source;
- GstClockTime cached_duration;
-
- gdouble rate;
-
- GstPlayerState app_state;
- gint buffering;
-
- GstTagList *global_tags;
- GstPlayerMediaInfo *media_info;
-
- GstElement *current_vis_element;
-
- GstStructure *config;
-
- /* Protected by lock */
- gboolean seek_pending; /* Only set from main context */
- GstClockTime last_seek_time; /* Only set from main context */
- GSource *seek_source;
- GstClockTime seek_position;
- /* If TRUE, all signals are inhibited except the
- * state-changed:GST_PLAYER_STATE_STOPPED/PAUSED. This ensures that no signal
- * is emitted after gst_player_stop/pause() has been called by the user. */
- gboolean inhibit_sigs;
-
- /* For playbin3 */
- gboolean use_playbin3;
- GstStreamCollection *collection;
- gchar *video_sid;
- gchar *audio_sid;
- gchar *subtitle_sid;
- gulong stream_notify_id;
+ /* legacy */
+ GstPlayerSignalDispatcher *signal_dispatcher;
};
struct _GstPlayerClass
@@ -218,92 +170,16 @@ G_DEFINE_TYPE (GstPlayer, gst_player, GST_TYPE_OBJECT);
static guint signals[SIGNAL_LAST] = { 0, };
static GParamSpec *param_specs[PROP_LAST] = { NULL, };
-static void gst_player_dispose (GObject * object);
static void gst_player_finalize (GObject * object);
static void gst_player_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_player_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
-static void gst_player_constructed (GObject * object);
-
-static gpointer gst_player_main (gpointer data);
-
-static void gst_player_seek_internal_locked (GstPlayer * self);
-static void gst_player_stop_internal (GstPlayer * self, gboolean transient);
-static gboolean gst_player_pause_internal (gpointer user_data);
-static gboolean gst_player_play_internal (gpointer user_data);
-static gboolean gst_player_seek_internal (gpointer user_data);
-static void gst_player_set_rate_internal (GstPlayer * self);
-static void change_state (GstPlayer * self, GstPlayerState state);
-
-static GstPlayerMediaInfo *gst_player_media_info_create (GstPlayer * self);
-
-static void gst_player_streams_info_create (GstPlayer * self,
- GstPlayerMediaInfo * media_info, const gchar * prop, GType type);
-static void gst_player_stream_info_update (GstPlayer * self,
- GstPlayerStreamInfo * s);
-static void gst_player_stream_info_update_tags_and_caps (GstPlayer * self,
- GstPlayerStreamInfo * s);
-static GstPlayerStreamInfo *gst_player_stream_info_find (GstPlayerMediaInfo *
- media_info, GType type, gint stream_index);
-static GstPlayerStreamInfo *gst_player_stream_info_get_current (GstPlayer *
- self, const gchar * prop, GType type);
-
-static void gst_player_video_info_update (GstPlayer * self,
- GstPlayerStreamInfo * stream_info);
-static void gst_player_audio_info_update (GstPlayer * self,
- GstPlayerStreamInfo * stream_info);
-static void gst_player_subtitle_info_update (GstPlayer * self,
- GstPlayerStreamInfo * stream_info);
-
-/* For playbin3 */
-static void gst_player_streams_info_create_from_collection (GstPlayer * self,
- GstPlayerMediaInfo * media_info, GstStreamCollection * collection);
-static void gst_player_stream_info_update_from_stream (GstPlayer * self,
- GstPlayerStreamInfo * s, GstStream * stream);
-static GstPlayerStreamInfo *gst_player_stream_info_find_from_stream_id
- (GstPlayerMediaInfo * media_info, const gchar * stream_id);
-static GstPlayerStreamInfo *gst_player_stream_info_get_current_from_stream_id
- (GstPlayer * self, const gchar * stream_id, GType type);
-static void stream_notify_cb (GstStreamCollection * collection,
- GstStream * stream, GParamSpec * pspec, GstPlayer * self);
-
-static void emit_media_info_updated_signal (GstPlayer * self);
-
-static void *get_title (GstTagList * tags);
-static void *get_container_format (GstTagList * tags);
-static void *get_from_tags (GstPlayer * self, GstPlayerMediaInfo * media_info,
- void *(*func) (GstTagList *));
-static void *get_cover_sample (GstTagList * tags);
-
-static void remove_seek_source (GstPlayer * self);
static void
-gst_player_init (GstPlayer * self)
+gst_player_init (G_GNUC_UNUSED GstPlayer * self)
{
- GST_TRACE_OBJECT (self, "Initializing");
-
- self = gst_player_get_instance_private (self);
- g_mutex_init (&self->lock);
- g_cond_init (&self->cond);
-
- self->context = g_main_context_new ();
- self->loop = g_main_loop_new (self->context, FALSE);
-
- /* *INDENT-OFF* */
- self->config = gst_structure_new_id (QUARK_CONFIG,
- CONFIG_QUARK (POSITION_INTERVAL_UPDATE), G_TYPE_UINT, DEFAULT_POSITION_UPDATE_INTERVAL_MS,
- CONFIG_QUARK (ACCURATE_SEEK), G_TYPE_BOOLEAN, FALSE,
- NULL);
- /* *INDENT-ON* */
-
- self->seek_pending = FALSE;
- self->seek_position = GST_CLOCK_TIME_NONE;
- self->last_seek_time = GST_CLOCK_TIME_NONE;
- self->inhibit_sigs = FALSE;
-
- GST_TRACE_OBJECT (self, "Initialized");
}
static void
@@ -330,15 +206,13 @@ gst_player_class_init (GstPlayerClass * klass)
gobject_class->set_property = gst_player_set_property;
gobject_class->get_property = gst_player_get_property;
- gobject_class->dispose = gst_player_dispose;
gobject_class->finalize = gst_player_finalize;
- gobject_class->constructed = gst_player_constructed;
param_specs[PROP_VIDEO_RENDERER] =
g_param_spec_object ("video-renderer",
"Video Renderer", "Video renderer to use for rendering videos",
GST_TYPE_PLAYER_VIDEO_RENDERER,
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
param_specs[PROP_SIGNAL_DISPATCHER] =
g_param_spec_object ("signal-dispatcher",
@@ -495,260 +369,33 @@ gst_player_class_init (GstPlayerClass * klass)
}
static void
-gst_player_dispose (GObject * object)
-{
- GstPlayer *self = GST_PLAYER (object);
-
- GST_TRACE_OBJECT (self, "Stopping main thread");
-
- if (self->loop) {
- g_main_loop_quit (self->loop);
-
- if (self->thread != g_thread_self ())
- g_thread_join (self->thread);
- else
- g_thread_unref (self->thread);
- self->thread = NULL;
-
- g_main_loop_unref (self->loop);
- self->loop = NULL;
-
- g_main_context_unref (self->context);
- self->context = NULL;
- }
-
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static void
gst_player_finalize (GObject * object)
{
GstPlayer *self = GST_PLAYER (object);
GST_TRACE_OBJECT (self, "Finalizing");
- g_free (self->uri);
- g_free (self->redirect_uri);
- g_free (self->suburi);
- g_free (self->video_sid);
- g_free (self->audio_sid);
- g_free (self->subtitle_sid);
- if (self->global_tags)
- gst_tag_list_unref (self->global_tags);
- if (self->video_renderer)
- g_object_unref (self->video_renderer);
if (self->signal_dispatcher)
g_object_unref (self->signal_dispatcher);
- if (self->current_vis_element)
- gst_object_unref (self->current_vis_element);
- if (self->config)
- gst_structure_free (self->config);
- if (self->collection)
- gst_object_unref (self->collection);
- g_mutex_clear (&self->lock);
- g_cond_clear (&self->cond);
+ if (self->play)
+ gst_object_unref (self->play);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
-gst_player_constructed (GObject * object)
-{
- GstPlayer *self = GST_PLAYER (object);
-
- GST_TRACE_OBJECT (self, "Constructed");
-
- g_mutex_lock (&self->lock);
- self->thread = g_thread_new ("GstPlayer", gst_player_main, self);
- while (!self->loop || !g_main_loop_is_running (self->loop))
- g_cond_wait (&self->cond, &self->lock);
- g_mutex_unlock (&self->lock);
-
- G_OBJECT_CLASS (parent_class)->constructed (object);
-}
-
-typedef struct
-{
- GstPlayer *player;
- gchar *uri;
-} UriLoadedSignalData;
-
-static void
-uri_loaded_dispatch (gpointer user_data)
-{
- UriLoadedSignalData *data = user_data;
-
- g_signal_emit (data->player, signals[SIGNAL_URI_LOADED], 0, data->uri);
-}
-
-static void
-uri_loaded_signal_data_free (UriLoadedSignalData * data)
-{
- g_object_unref (data->player);
- g_free (data->uri);
- g_free (data);
-}
-
-static gboolean
-gst_player_set_uri_internal (gpointer user_data)
-{
- GstPlayer *self = user_data;
-
- gst_player_stop_internal (self, FALSE);
-
- g_mutex_lock (&self->lock);
-
- GST_DEBUG_OBJECT (self, "Changing URI to '%s'", GST_STR_NULL (self->uri));
-
- g_object_set (self->playbin, "uri", self->uri, NULL);
-
- if (g_signal_handler_find (self, G_SIGNAL_MATCH_ID,
- signals[SIGNAL_URI_LOADED], 0, NULL, NULL, NULL) != 0) {
- UriLoadedSignalData *data = g_new (UriLoadedSignalData, 1);
-
- data->player = g_object_ref (self);
- data->uri = g_strdup (self->uri);
- gst_player_signal_dispatcher_dispatch (self->signal_dispatcher, self,
- uri_loaded_dispatch, data,
- (GDestroyNotify) uri_loaded_signal_data_free);
- }
-
- g_object_set (self->playbin, "suburi", NULL, NULL);
-
- g_mutex_unlock (&self->lock);
-
- return G_SOURCE_REMOVE;
-}
-
-static gboolean
-gst_player_set_suburi_internal (gpointer user_data)
-{
- GstPlayer *self = user_data;
- GstClockTime position;
- GstState target_state;
-
- /* save the state and position */
- target_state = self->target_state;
- position = gst_player_get_position (self);
-
- gst_player_stop_internal (self, TRUE);
- g_mutex_lock (&self->lock);
-
- GST_DEBUG_OBJECT (self, "Changing SUBURI to '%s'",
- GST_STR_NULL (self->suburi));
-
- g_object_set (self->playbin, "suburi", self->suburi, NULL);
-
- g_mutex_unlock (&self->lock);
-
- /* restore state and position */
- if (position != GST_CLOCK_TIME_NONE)
- gst_player_seek (self, position);
- if (target_state == GST_STATE_PAUSED)
- gst_player_pause_internal (self);
- else if (target_state == GST_STATE_PLAYING)
- gst_player_play_internal (self);
-
- return G_SOURCE_REMOVE;
-}
-
-static void
-gst_player_set_rate_internal (GstPlayer * self)
-{
- self->seek_position = gst_player_get_position (self);
-
- /* If there is no seek being dispatch to the main context currently do that,
- * otherwise we just updated the rate so that it will be taken by
- * the seek handler from the main context instead of the old one.
- */
- if (!self->seek_source) {
- /* If no seek is pending then create new seek source */
- if (!self->seek_pending) {
- self->seek_source = g_idle_source_new ();
- g_source_set_callback (self->seek_source,
- (GSourceFunc) gst_player_seek_internal, self, NULL);
- g_source_attach (self->seek_source, self->context);
- }
- }
-}
-
-static void
gst_player_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstPlayer *self = GST_PLAYER (object);
switch (prop_id) {
- case PROP_VIDEO_RENDERER:
- self->video_renderer = g_value_dup_object (value);
- break;
case PROP_SIGNAL_DISPATCHER:
self->signal_dispatcher = g_value_dup_object (value);
break;
- case PROP_URI:{
- g_mutex_lock (&self->lock);
- g_free (self->uri);
- g_free (self->redirect_uri);
- self->redirect_uri = NULL;
-
- g_free (self->suburi);
- self->suburi = NULL;
-
- self->uri = g_value_dup_string (value);
- GST_DEBUG_OBJECT (self, "Set uri=%s", self->uri);
- g_mutex_unlock (&self->lock);
-
- g_main_context_invoke_full (self->context, G_PRIORITY_DEFAULT,
- gst_player_set_uri_internal, self, NULL);
- break;
- }
- case PROP_SUBURI:{
- g_mutex_lock (&self->lock);
- g_free (self->suburi);
-
- self->suburi = g_value_dup_string (value);
- GST_DEBUG_OBJECT (self, "Set suburi=%s", self->suburi);
- g_mutex_unlock (&self->lock);
-
- g_main_context_invoke_full (self->context, G_PRIORITY_DEFAULT,
- gst_player_set_suburi_internal, self, NULL);
- break;
- }
- case PROP_VOLUME:
- GST_DEBUG_OBJECT (self, "Set volume=%lf", g_value_get_double (value));
- g_object_set_property (G_OBJECT (self->playbin), "volume", value);
- break;
- case PROP_RATE:
- g_mutex_lock (&self->lock);
- self->rate = g_value_get_double (value);
- GST_DEBUG_OBJECT (self, "Set rate=%lf", g_value_get_double (value));
- gst_player_set_rate_internal (self);
- g_mutex_unlock (&self->lock);
- break;
- case PROP_MUTE:
- GST_DEBUG_OBJECT (self, "Set mute=%d", g_value_get_boolean (value));
- g_object_set_property (G_OBJECT (self->playbin), "mute", value);
- break;
- case PROP_VIDEO_MULTIVIEW_MODE:
- GST_DEBUG_OBJECT (self, "Set multiview mode=%u",
- g_value_get_enum (value));
- g_object_set_property (G_OBJECT (self->playbin), "video-multiview-mode",
- value);
- break;
- case PROP_VIDEO_MULTIVIEW_FLAGS:
- GST_DEBUG_OBJECT (self, "Set multiview flags=%x",
- g_value_get_flags (value));
- g_object_set_property (G_OBJECT (self->playbin), "video-multiview-flags",
- value);
- break;
- case PROP_AUDIO_VIDEO_OFFSET:
- g_object_set_property (G_OBJECT (self->playbin), "av-offset", value);
- break;
- case PROP_SUBTITLE_VIDEO_OFFSET:
- g_object_set_property (G_OBJECT (self->playbin), "text-offset", value);
- break;
default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ g_object_set_property (G_OBJECT (self->play),
+ g_param_spec_get_name (pspec), value);
break;
}
}
@@ -760,2274 +407,141 @@ gst_player_get_property (GObject * object, guint prop_id,
GstPlayer *self = GST_PLAYER (object);
switch (prop_id) {
- case PROP_URI:
- g_mutex_lock (&self->lock);
- g_value_set_string (value, self->uri);
- g_mutex_unlock (&self->lock);
- break;
- case PROP_SUBURI:
- g_mutex_lock (&self->lock);
- g_value_set_string (value, self->suburi);
- g_mutex_unlock (&self->lock);
- GST_DEBUG_OBJECT (self, "Returning suburi=%s",
- g_value_get_string (value));
- break;
- case PROP_POSITION:{
- gint64 position = GST_CLOCK_TIME_NONE;
-
- gst_element_query_position (self->playbin, GST_FORMAT_TIME, &position);
- g_value_set_uint64 (value, position);
- GST_TRACE_OBJECT (self, "Returning position=%" GST_TIME_FORMAT,
- GST_TIME_ARGS (g_value_get_uint64 (value)));
- break;
- }
- case PROP_DURATION:{
- g_value_set_uint64 (value, self->cached_duration);
- GST_TRACE_OBJECT (self, "Returning duration=%" GST_TIME_FORMAT,
- GST_TIME_ARGS (g_value_get_uint64 (value)));
- break;
- }
- case PROP_MEDIA_INFO:{
- GstPlayerMediaInfo *media_info = gst_player_get_media_info (self);
- g_value_take_object (value, media_info);
- break;
- }
- case PROP_CURRENT_AUDIO_TRACK:{
- GstPlayerAudioInfo *audio_info =
- gst_player_get_current_audio_track (self);
- g_value_take_object (value, audio_info);
- break;
- }
- case PROP_CURRENT_VIDEO_TRACK:{
- GstPlayerVideoInfo *video_info =
- gst_player_get_current_video_track (self);
- g_value_take_object (value, video_info);
- break;
- }
- case PROP_CURRENT_SUBTITLE_TRACK:{
- GstPlayerSubtitleInfo *subtitle_info =
- gst_player_get_current_subtitle_track (self);
- g_value_take_object (value, subtitle_info);
- break;
- }
- case PROP_VOLUME:
- g_object_get_property (G_OBJECT (self->playbin), "volume", value);
- GST_TRACE_OBJECT (self, "Returning volume=%lf",
- g_value_get_double (value));
- break;
- case PROP_RATE:
- g_mutex_lock (&self->lock);
- g_value_set_double (value, self->rate);
- g_mutex_unlock (&self->lock);
+ case PROP_MEDIA_INFO:
+ g_value_take_object (value, gst_player_get_media_info (self));
break;
- case PROP_MUTE:
- g_object_get_property (G_OBJECT (self->playbin), "mute", value);
- GST_TRACE_OBJECT (self, "Returning mute=%d", g_value_get_boolean (value));
+ case PROP_CURRENT_AUDIO_TRACK:
+ g_value_take_object (value, gst_player_get_current_audio_track (self));
break;
- case PROP_PIPELINE:
- g_value_set_object (value, self->playbin);
+ case PROP_CURRENT_VIDEO_TRACK:
+ g_value_take_object (value, gst_player_get_current_video_track (self));
break;
- case PROP_VIDEO_MULTIVIEW_MODE:{
- g_object_get_property (G_OBJECT (self->playbin), "video-multiview-mode",
- value);
- GST_TRACE_OBJECT (self, "Return multiview mode=%d",
- g_value_get_enum (value));
- break;
- }
- case PROP_VIDEO_MULTIVIEW_FLAGS:{
- g_object_get_property (G_OBJECT (self->playbin), "video-multiview-flags",
- value);
- GST_TRACE_OBJECT (self, "Return multiview flags=%x",
- g_value_get_flags (value));
- break;
- }
- case PROP_AUDIO_VIDEO_OFFSET:
- g_object_get_property (G_OBJECT (self->playbin), "av-offset", value);
- break;
- case PROP_SUBTITLE_VIDEO_OFFSET:
- g_object_get_property (G_OBJECT (self->playbin), "text-offset", value);
+ case PROP_CURRENT_SUBTITLE_TRACK:
+ g_value_take_object (value, gst_player_get_current_subtitle_track (self));
break;
default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ g_object_get_property (G_OBJECT (self->play),
+ g_param_spec_get_name (pspec), value);
break;
}
}
-static gboolean
-main_loop_running_cb (gpointer user_data)
-{
- GstPlayer *self = GST_PLAYER (user_data);
-
- GST_TRACE_OBJECT (self, "Main loop running now");
-
- g_mutex_lock (&self->lock);
- g_cond_signal (&self->cond);
- g_mutex_unlock (&self->lock);
-
- return G_SOURCE_REMOVE;
-}
-
-typedef struct
-{
- GstPlayer *player;
- GstPlayerState state;
-} StateChangedSignalData;
-
-static void
-state_changed_dispatch (gpointer user_data)
-{
- StateChangedSignalData *data = user_data;
-
- if (data->player->inhibit_sigs && data->state != GST_PLAYER_STATE_STOPPED
- && data->state != GST_PLAYER_STATE_PAUSED)
- return;
-
- g_signal_emit (data->player, signals[SIGNAL_STATE_CHANGED], 0, data->state);
-}
-
-static void
-state_changed_signal_data_free (StateChangedSignalData * data)
-{
- g_object_unref (data->player);
- g_free (data);
-}
-
-static void
-change_state (GstPlayer * self, GstPlayerState state)
-{
- if (state == self->app_state)
- return;
-
- GST_DEBUG_OBJECT (self, "Changing app state from %s to %s",
- gst_player_state_get_name (self->app_state),
- gst_player_state_get_name (state));
- self->app_state = state;
-
- if (g_signal_handler_find (self, G_SIGNAL_MATCH_ID,
- signals[SIGNAL_STATE_CHANGED], 0, NULL, NULL, NULL) != 0) {
- StateChangedSignalData *data = g_new (StateChangedSignalData, 1);
-
- data->player = g_object_ref (self);
- data->state = state;
- gst_player_signal_dispatcher_dispatch (self->signal_dispatcher, self,
- state_changed_dispatch, data,
- (GDestroyNotify) state_changed_signal_data_free);
- }
-}
-
-typedef struct
-{
- GstPlayer *player;
- GstClockTime position;
-} PositionUpdatedSignalData;
-
-static void
-position_updated_dispatch (gpointer user_data)
-{
- PositionUpdatedSignalData *data = user_data;
-
- if (data->player->inhibit_sigs)
- return;
-
- if (data->player->target_state >= GST_STATE_PAUSED) {
- g_signal_emit (data->player, signals[SIGNAL_POSITION_UPDATED], 0,
- data->position);
- g_object_notify_by_pspec (G_OBJECT (data->player),
- param_specs[PROP_POSITION]);
- }
-}
-
-static void
-position_updated_signal_data_free (PositionUpdatedSignalData * data)
-{
- g_object_unref (data->player);
- g_free (data);
-}
-
-static gboolean
-tick_cb (gpointer user_data)
-{
- GstPlayer *self = GST_PLAYER (user_data);
- gint64 position;
-
- if (self->target_state >= GST_STATE_PAUSED
- && gst_element_query_position (self->playbin, GST_FORMAT_TIME,
- &position)) {
- GST_LOG_OBJECT (self, "Position %" GST_TIME_FORMAT,
- GST_TIME_ARGS (position));
-
- if (g_signal_handler_find (self, G_SIGNAL_MATCH_ID,
- signals[SIGNAL_POSITION_UPDATED], 0, NULL, NULL, NULL) != 0) {
- PositionUpdatedSignalData *data = g_new (PositionUpdatedSignalData, 1);
-
- data->player = g_object_ref (self);
- data->position = position;
- gst_player_signal_dispatcher_dispatch (self->signal_dispatcher, self,
- position_updated_dispatch, data,
- (GDestroyNotify) position_updated_signal_data_free);
- }
- }
-
- return G_SOURCE_CONTINUE;
-}
-
-static void
-add_tick_source (GstPlayer * self)
-{
- guint position_update_interval_ms;
-
- if (self->tick_source)
- return;
-
- position_update_interval_ms =
- gst_player_config_get_position_update_interval (self->config);
- if (!position_update_interval_ms)
- return;
-
- self->tick_source = g_timeout_source_new (position_update_interval_ms);
- g_source_set_callback (self->tick_source, (GSourceFunc) tick_cb, self, NULL);
- g_source_attach (self->tick_source, self->context);
-}
-
-static void
-remove_tick_source (GstPlayer * self)
-{
- if (!self->tick_source)
- return;
-
- g_source_destroy (self->tick_source);
- g_source_unref (self->tick_source);
- self->tick_source = NULL;
-}
-
-static gboolean
-ready_timeout_cb (gpointer user_data)
-{
- GstPlayer *self = user_data;
-
- if (self->target_state <= GST_STATE_READY) {
- GST_DEBUG_OBJECT (self, "Setting pipeline to NULL state");
- self->target_state = GST_STATE_NULL;
- self->current_state = GST_STATE_NULL;
- gst_element_set_state (self->playbin, GST_STATE_NULL);
- }
-
- return G_SOURCE_REMOVE;
-}
-
-static void
-add_ready_timeout_source (GstPlayer * self)
-{
- if (self->ready_timeout_source)
- return;
-
- self->ready_timeout_source = g_timeout_source_new_seconds (60);
- g_source_set_callback (self->ready_timeout_source,
- (GSourceFunc) ready_timeout_cb, self, NULL);
- g_source_attach (self->ready_timeout_source, self->context);
-}
-
-static void
-remove_ready_timeout_source (GstPlayer * self)
-{
- if (!self->ready_timeout_source)
- return;
-
- g_source_destroy (self->ready_timeout_source);
- g_source_unref (self->ready_timeout_source);
- self->ready_timeout_source = NULL;
-}
-
-typedef struct
-{
- GstPlayer *player;
- GError *err;
-} ErrorSignalData;
-
-static void
-error_dispatch (gpointer user_data)
-{
- ErrorSignalData *data = user_data;
-
- if (data->player->inhibit_sigs)
- return;
-
- g_signal_emit (data->player, signals[SIGNAL_ERROR], 0, data->err);
-}
-
-static void
-free_error_signal_data (ErrorSignalData * data)
-{
- g_object_unref (data->player);
- g_clear_error (&data->err);
- g_free (data);
-}
-
-static void
-emit_error (GstPlayer * self, GError * err)
-{
- GST_ERROR_OBJECT (self, "Error: %s (%s, %d)", err->message,
- g_quark_to_string (err->domain), err->code);
-
- if (g_signal_handler_find (self, G_SIGNAL_MATCH_ID,
- signals[SIGNAL_ERROR], 0, NULL, NULL, NULL) != 0) {
- ErrorSignalData *data = g_new (ErrorSignalData, 1);
-
- data->player = g_object_ref (self);
- data->err = g_error_copy (err);
- gst_player_signal_dispatcher_dispatch (self->signal_dispatcher, self,
- error_dispatch, data, (GDestroyNotify) free_error_signal_data);
- }
-
- g_error_free (err);
-
- remove_tick_source (self);
- remove_ready_timeout_source (self);
-
- self->target_state = GST_STATE_NULL;
- self->current_state = GST_STATE_NULL;
- self->is_live = FALSE;
- self->is_eos = FALSE;
- gst_element_set_state (self->playbin, GST_STATE_NULL);
- change_state (self, GST_PLAYER_STATE_STOPPED);
- self->buffering = 100;
-
- g_mutex_lock (&self->lock);
- if (self->media_info) {
- g_object_unref (self->media_info);
- self->media_info = NULL;
- }
-
- if (self->global_tags) {
- gst_tag_list_unref (self->global_tags);
- self->global_tags = NULL;
- }
-
- self->seek_pending = FALSE;
- remove_seek_source (self);
- self->seek_position = GST_CLOCK_TIME_NONE;
- self->last_seek_time = GST_CLOCK_TIME_NONE;
- g_mutex_unlock (&self->lock);
-}
-
-static void
-dump_dot_file (GstPlayer * self, const gchar * name)
-{
- gchar *full_name;
-
- full_name = g_strdup_printf ("gst-player.%p.%s", self, name);
-
- GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (self->playbin),
- GST_DEBUG_GRAPH_SHOW_ALL, full_name);
-
- g_free (full_name);
-}
-
-typedef struct
-{
- GstPlayer *player;
- GError *err;
-} WarningSignalData;
-
-static void
-warning_dispatch (gpointer user_data)
-{
- WarningSignalData *data = user_data;
-
- if (data->player->inhibit_sigs)
- return;
-
- g_signal_emit (data->player, signals[SIGNAL_WARNING], 0, data->err);
-}
-
-static void
-free_warning_signal_data (WarningSignalData * data)
-{
- g_object_unref (data->player);
- g_clear_error (&data->err);
- g_free (data);
-}
-
-static void
-emit_warning (GstPlayer * self, GError * err)
-{
- GST_ERROR_OBJECT (self, "Warning: %s (%s, %d)", err->message,
- g_quark_to_string (err->domain), err->code);
-
- if (g_signal_handler_find (self, G_SIGNAL_MATCH_ID,
- signals[SIGNAL_WARNING], 0, NULL, NULL, NULL) != 0) {
- WarningSignalData *data = g_new (WarningSignalData, 1);
-
- data->player = g_object_ref (self);
- data->err = g_error_copy (err);
- gst_player_signal_dispatcher_dispatch (self->signal_dispatcher, self,
- warning_dispatch, data, (GDestroyNotify) free_warning_signal_data);
- }
-
- g_error_free (err);
-}
-
-static void
-error_cb (G_GNUC_UNUSED GstBus * bus, GstMessage * msg, gpointer user_data)
-{
- GstPlayer *self = GST_PLAYER (user_data);
- GError *err, *player_err;
- gchar *name, *debug, *message, *full_message;
-
- dump_dot_file (self, "error");
-
- gst_message_parse_error (msg, &err, &debug);
-
- name = gst_object_get_path_string (msg->src);
- message = gst_error_get_message (err->domain, err->code);
-
- if (debug)
- full_message =
- g_strdup_printf ("Error from element %s: %s\n%s\n%s", name, message,
- err->message, debug);
- else
- full_message =
- g_strdup_printf ("Error from element %s: %s\n%s", name, message,
- err->message);
-
- GST_ERROR_OBJECT (self, "ERROR: from element %s: %s", name, err->message);
- if (debug != NULL)
- GST_ERROR_OBJECT (self, "Additional debug info: %s", debug);
-
- player_err =
- g_error_new_literal (GST_PLAYER_ERROR, GST_PLAYER_ERROR_FAILED,
- full_message);
- emit_error (self, player_err);
-
- g_clear_error (&err);
- g_free (debug);
- g_free (name);
- g_free (full_message);
- g_free (message);
-}
-
-static void
-warning_cb (G_GNUC_UNUSED GstBus * bus, GstMessage * msg, gpointer user_data)
-{
- GstPlayer *self = GST_PLAYER (user_data);
- GError *err, *player_err;
- gchar *name, *debug, *message, *full_message;
-
- dump_dot_file (self, "warning");
-
- gst_message_parse_warning (msg, &err, &debug);
-
- name = gst_object_get_path_string (msg->src);
- message = gst_error_get_message (err->domain, err->code);
-
- if (debug)
- full_message =
- g_strdup_printf ("Warning from element %s: %s\n%s\n%s", name, message,
- err->message, debug);
- else
- full_message =
- g_strdup_printf ("Warning from element %s: %s\n%s", name, message,
- err->message);
-
- GST_WARNING_OBJECT (self, "WARNING: from element %s: %s", name, err->message);
- if (debug != NULL)
- GST_WARNING_OBJECT (self, "Additional debug info: %s", debug);
-
- player_err =
- g_error_new_literal (GST_PLAYER_ERROR, GST_PLAYER_ERROR_FAILED,
- full_message);
- emit_warning (self, player_err);
-
- g_clear_error (&err);
- g_free (debug);
- g_free (name);
- g_free (full_message);
- g_free (message);
-}
-
-static void
-eos_dispatch (gpointer user_data)
-{
- GstPlayer *player = user_data;
-
- if (player->inhibit_sigs)
- return;
-
- g_signal_emit (player, signals[SIGNAL_END_OF_STREAM], 0);
-}
-
-static void
-eos_cb (G_GNUC_UNUSED GstBus * bus, G_GNUC_UNUSED GstMessage * msg,
- gpointer user_data)
-{
- GstPlayer *self = GST_PLAYER (user_data);
-
- GST_DEBUG_OBJECT (self, "End of stream");
-
- tick_cb (self);
- remove_tick_source (self);
-
- if (g_signal_handler_find (self, G_SIGNAL_MATCH_ID,
- signals[SIGNAL_END_OF_STREAM], 0, NULL, NULL, NULL) != 0) {
- gst_player_signal_dispatcher_dispatch (self->signal_dispatcher, self,
- eos_dispatch, g_object_ref (self), (GDestroyNotify) g_object_unref);
- }
- change_state (self, GST_PLAYER_STATE_STOPPED);
- self->buffering = 100;
- self->is_eos = TRUE;
-}
-
-typedef struct
-{
- GstPlayer *player;
- gint percent;
-} BufferingSignalData;
-
-static void
-buffering_dispatch (gpointer user_data)
-{
- BufferingSignalData *data = user_data;
-
- if (data->player->inhibit_sigs)
- return;
-
- if (data->player->target_state >= GST_STATE_PAUSED) {
- g_signal_emit (data->player, signals[SIGNAL_BUFFERING], 0, data->percent);
- }
-}
-
-static void
-buffering_signal_data_free (BufferingSignalData * data)
-{
- g_object_unref (data->player);
- g_free (data);
-}
-
-static void
-buffering_cb (G_GNUC_UNUSED GstBus * bus, GstMessage * msg, gpointer user_data)
-{
- GstPlayer *self = GST_PLAYER (user_data);
- gint percent;
-
- if (self->target_state < GST_STATE_PAUSED)
- return;
- if (self->is_live)
- return;
-
- gst_message_parse_buffering (msg, &percent);
- GST_LOG_OBJECT (self, "Buffering %d%%", percent);
-
- if (percent < 100 && self->target_state >= GST_STATE_PAUSED) {
- GstStateChangeReturn state_ret;
-
- GST_DEBUG_OBJECT (self, "Waiting for buffering to finish");
- state_ret = gst_element_set_state (self->playbin, GST_STATE_PAUSED);
-
- if (state_ret == GST_STATE_CHANGE_FAILURE) {
- emit_error (self, g_error_new (GST_PLAYER_ERROR, GST_PLAYER_ERROR_FAILED,
- "Failed to handle buffering"));
- return;
- }
-
- change_state (self, GST_PLAYER_STATE_BUFFERING);
- }
-
- if (self->buffering != percent) {
- if (g_signal_handler_find (self, G_SIGNAL_MATCH_ID,
- signals[SIGNAL_BUFFERING], 0, NULL, NULL, NULL) != 0) {
- BufferingSignalData *data = g_new (BufferingSignalData, 1);
-
- data->player = g_object_ref (self);
- data->percent = percent;
- gst_player_signal_dispatcher_dispatch (self->signal_dispatcher, self,
- buffering_dispatch, data,
- (GDestroyNotify) buffering_signal_data_free);
- }
-
- self->buffering = percent;
- }
-
-
- g_mutex_lock (&self->lock);
- if (percent == 100 && (self->seek_position != GST_CLOCK_TIME_NONE ||
- self->seek_pending)) {
- g_mutex_unlock (&self->lock);
-
- GST_DEBUG_OBJECT (self, "Buffering finished - seek pending");
- } else if (percent == 100 && self->target_state >= GST_STATE_PLAYING
- && self->current_state >= GST_STATE_PAUSED) {
- GstStateChangeReturn state_ret;
-
- g_mutex_unlock (&self->lock);
-
- GST_DEBUG_OBJECT (self, "Buffering finished - going to PLAYING");
- state_ret = gst_element_set_state (self->playbin, GST_STATE_PLAYING);
- /* Application state change is happening when the state change happened */
- if (state_ret == GST_STATE_CHANGE_FAILURE)
- emit_error (self, g_error_new (GST_PLAYER_ERROR, GST_PLAYER_ERROR_FAILED,
- "Failed to handle buffering"));
- } else if (percent == 100 && self->target_state >= GST_STATE_PAUSED) {
- g_mutex_unlock (&self->lock);
-
- GST_DEBUG_OBJECT (self, "Buffering finished - staying PAUSED");
- change_state (self, GST_PLAYER_STATE_PAUSED);
- } else {
- g_mutex_unlock (&self->lock);
- }
-}
-
-static void
-clock_lost_cb (G_GNUC_UNUSED GstBus * bus, G_GNUC_UNUSED GstMessage * msg,
- gpointer user_data)
-{
- GstPlayer *self = GST_PLAYER (user_data);
- GstStateChangeReturn state_ret;
-
- GST_DEBUG_OBJECT (self, "Clock lost");
- if (self->target_state >= GST_STATE_PLAYING) {
- state_ret = gst_element_set_state (self->playbin, GST_STATE_PAUSED);
- if (state_ret != GST_STATE_CHANGE_FAILURE)
- state_ret = gst_element_set_state (self->playbin, GST_STATE_PLAYING);
-
- if (state_ret == GST_STATE_CHANGE_FAILURE)
- emit_error (self, g_error_new (GST_PLAYER_ERROR, GST_PLAYER_ERROR_FAILED,
- "Failed to handle clock loss"));
- }
-}
-
-typedef struct
-{
- GstPlayer *player;
- gint width, height;
-} VideoDimensionsChangedSignalData;
-
-static void
-video_dimensions_changed_dispatch (gpointer user_data)
-{
- VideoDimensionsChangedSignalData *data = user_data;
-
- if (data->player->inhibit_sigs)
- return;
-
- if (data->player->target_state >= GST_STATE_PAUSED) {
- g_signal_emit (data->player, signals[SIGNAL_VIDEO_DIMENSIONS_CHANGED], 0,
- data->width, data->height);
- }
-}
-
-static void
-video_dimensions_changed_signal_data_free (VideoDimensionsChangedSignalData *
- data)
-{
- g_object_unref (data->player);
- g_free (data);
-}
-
-static void
-check_video_dimensions_changed (GstPlayer * self)
-{
- GstElement *video_sink;
- GstPad *video_sink_pad;
- GstCaps *caps;
- GstVideoInfo info;
- gint width = 0, height = 0;
-
- g_object_get (self->playbin, "video-sink", &video_sink, NULL);
- if (!video_sink)
- goto out;
-
- video_sink_pad = gst_element_get_static_pad (video_sink, "sink");
- if (!video_sink_pad) {
- gst_object_unref (video_sink);
- goto out;
- }
-
- caps = gst_pad_get_current_caps (video_sink_pad);
-
- if (caps) {
- if (gst_video_info_from_caps (&info, caps)) {
- info.width = info.width * info.par_n / info.par_d;
-
- GST_DEBUG_OBJECT (self, "Video dimensions changed: %dx%d", info.width,
- info.height);
- width = info.width;
- height = info.height;
- }
-
- gst_caps_unref (caps);
- }
- gst_object_unref (video_sink_pad);
- gst_object_unref (video_sink);
-
-out:
- if (g_signal_handler_find (self, G_SIGNAL_MATCH_ID,
- signals[SIGNAL_VIDEO_DIMENSIONS_CHANGED], 0, NULL, NULL, NULL) != 0) {
- VideoDimensionsChangedSignalData *data =
- g_new (VideoDimensionsChangedSignalData, 1);
-
- data->player = g_object_ref (self);
- data->width = width;
- data->height = height;
- gst_player_signal_dispatcher_dispatch (self->signal_dispatcher, self,
- video_dimensions_changed_dispatch, data,
- (GDestroyNotify) video_dimensions_changed_signal_data_free);
- }
-}
-
-static void
-notify_caps_cb (G_GNUC_UNUSED GObject * object,
- G_GNUC_UNUSED GParamSpec * pspec, gpointer user_data)
-{
- GstPlayer *self = GST_PLAYER (user_data);
-
- check_video_dimensions_changed (self);
-}
-
-typedef struct
-{
- GstPlayer *player;
- GstClockTime duration;
-} DurationChangedSignalData;
-
-static void
-duration_changed_dispatch (gpointer user_data)
-{
- DurationChangedSignalData *data = user_data;
-
- if (data->player->inhibit_sigs)
- return;
-
- if (data->player->target_state >= GST_STATE_PAUSED) {
- g_signal_emit (data->player, signals[SIGNAL_DURATION_CHANGED], 0,
- data->duration);
- g_object_notify_by_pspec (G_OBJECT (data->player),
- param_specs[PROP_DURATION]);
- }
-}
-
-static void
-duration_changed_signal_data_free (DurationChangedSignalData * data)
-{
- g_object_unref (data->player);
- g_free (data);
-}
-
-static void
-emit_duration_changed (GstPlayer * self, GstClockTime duration)
-{
- gboolean updated = FALSE;
-
- if (self->cached_duration == duration)
- return;
-
- GST_DEBUG_OBJECT (self, "Duration changed %" GST_TIME_FORMAT,
- GST_TIME_ARGS (duration));
-
- self->cached_duration = duration;
- g_mutex_lock (&self->lock);
- if (self->media_info) {
- self->media_info->duration = duration;
- updated = TRUE;
- }
- g_mutex_unlock (&self->lock);
- if (updated) {
- emit_media_info_updated_signal (self);
- }
-
- if (g_signal_handler_find (self, G_SIGNAL_MATCH_ID,
- signals[SIGNAL_DURATION_CHANGED], 0, NULL, NULL, NULL) != 0) {
- DurationChangedSignalData *data = g_new (DurationChangedSignalData, 1);
-
- data->player = g_object_ref (self);
- data->duration = duration;
- gst_player_signal_dispatcher_dispatch (self->signal_dispatcher, self,
- duration_changed_dispatch, data,
- (GDestroyNotify) duration_changed_signal_data_free);
- }
-}
-
-typedef struct
-{
- GstPlayer *player;
- GstClockTime position;
-} SeekDoneSignalData;
-
-static void
-seek_done_dispatch (gpointer user_data)
-{
- SeekDoneSignalData *data = user_data;
-
- if (data->player->inhibit_sigs)
- return;
-
- g_signal_emit (data->player, signals[SIGNAL_SEEK_DONE], 0, data->position);
-}
-
-static void
-seek_done_signal_data_free (SeekDoneSignalData * data)
-{
- g_object_unref (data->player);
- g_free (data);
-}
-
-static void
-emit_seek_done (GstPlayer * self)
-{
- if (g_signal_handler_find (self, G_SIGNAL_MATCH_ID,
- signals[SIGNAL_SEEK_DONE], 0, NULL, NULL, NULL) != 0) {
- SeekDoneSignalData *data = g_new (SeekDoneSignalData, 1);
-
- data->player = g_object_ref (self);
- data->position = gst_player_get_position (self);
- gst_player_signal_dispatcher_dispatch (self->signal_dispatcher, self,
- seek_done_dispatch, data, (GDestroyNotify) seek_done_signal_data_free);
- }
-}
-
-static void
-state_changed_cb (G_GNUC_UNUSED GstBus * bus, GstMessage * msg,
- gpointer user_data)
-{
- GstPlayer *self = GST_PLAYER (user_data);
- GstState old_state, new_state, pending_state;
-
- gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state);
-
- if (GST_MESSAGE_SRC (msg) == GST_OBJECT (self->playbin)) {
- gchar *transition_name;
-
- GST_DEBUG_OBJECT (self, "Changed state old: %s new: %s pending: %s",
- gst_element_state_get_name (old_state),
- gst_element_state_get_name (new_state),
- gst_element_state_get_name (pending_state));
-
- transition_name = g_strdup_printf ("%s_%s",
- gst_element_state_get_name (old_state),
- gst_element_state_get_name (new_state));
- dump_dot_file (self, transition_name);
- g_free (transition_name);
-
- self->current_state = new_state;
-
- if (old_state == GST_STATE_READY && new_state == GST_STATE_PAUSED
- && pending_state == GST_STATE_VOID_PENDING) {
- GstElement *video_sink;
- GstPad *video_sink_pad;
- gint64 duration = -1;
-
- GST_DEBUG_OBJECT (self, "Initial PAUSED - pre-rolled");
-
- g_mutex_lock (&self->lock);
- if (self->media_info)
- g_object_unref (self->media_info);
- self->media_info = gst_player_media_info_create (self);
- g_mutex_unlock (&self->lock);
- emit_media_info_updated_signal (self);
-
- g_object_get (self->playbin, "video-sink", &video_sink, NULL);
-
- if (video_sink) {
- video_sink_pad = gst_element_get_static_pad (video_sink, "sink");
-
- if (video_sink_pad) {
- g_signal_connect (video_sink_pad, "notify::caps",
- (GCallback) notify_caps_cb, self);
- gst_object_unref (video_sink_pad);
- }
- gst_object_unref (video_sink);
- }
-
- check_video_dimensions_changed (self);
- if (gst_element_query_duration (self->playbin, GST_FORMAT_TIME,
- &duration)) {
- emit_duration_changed (self, duration);
- } else {
- self->cached_duration = GST_CLOCK_TIME_NONE;
- }
- }
-
- if (new_state == GST_STATE_PAUSED
- && pending_state == GST_STATE_VOID_PENDING) {
- remove_tick_source (self);
-
- g_mutex_lock (&self->lock);
- if (self->seek_pending) {
- self->seek_pending = FALSE;
-
- if (!self->media_info->seekable) {
- GST_DEBUG_OBJECT (self, "Media is not seekable");
- remove_seek_source (self);
- self->seek_position = GST_CLOCK_TIME_NONE;
- self->last_seek_time = GST_CLOCK_TIME_NONE;
- } else if (self->seek_source) {
- GST_DEBUG_OBJECT (self, "Seek finished but new seek is pending");
- gst_player_seek_internal_locked (self);
- } else {
- GST_DEBUG_OBJECT (self, "Seek finished");
- emit_seek_done (self);
- }
- }
-
- if (self->seek_position != GST_CLOCK_TIME_NONE) {
- GST_DEBUG_OBJECT (self, "Seeking now that we reached PAUSED state");
- gst_player_seek_internal_locked (self);
- g_mutex_unlock (&self->lock);
- } else if (!self->seek_pending) {
- g_mutex_unlock (&self->lock);
-
- tick_cb (self);
-
- if (self->target_state >= GST_STATE_PLAYING && self->buffering == 100) {
- GstStateChangeReturn state_ret;
-
- state_ret = gst_element_set_state (self->playbin, GST_STATE_PLAYING);
- if (state_ret == GST_STATE_CHANGE_FAILURE)
- emit_error (self, g_error_new (GST_PLAYER_ERROR,
- GST_PLAYER_ERROR_FAILED, "Failed to play"));
- } else if (self->buffering == 100) {
- change_state (self, GST_PLAYER_STATE_PAUSED);
- }
- } else {
- g_mutex_unlock (&self->lock);
- }
- } else if (new_state == GST_STATE_PLAYING
- && pending_state == GST_STATE_VOID_PENDING) {
-
- /* If no seek is currently pending, add the tick source. This can happen
- * if we seeked already but the state-change message was still queued up */
- if (!self->seek_pending) {
- add_tick_source (self);
- change_state (self, GST_PLAYER_STATE_PLAYING);
- }
- } else if (new_state == GST_STATE_READY && old_state > GST_STATE_READY) {
- change_state (self, GST_PLAYER_STATE_STOPPED);
- } else {
- /* Otherwise we neither reached PLAYING nor PAUSED, so must
- * wait for something to happen... i.e. are BUFFERING now */
- change_state (self, GST_PLAYER_STATE_BUFFERING);
- }
- }
-}
-
-static void
-duration_changed_cb (G_GNUC_UNUSED GstBus * bus, G_GNUC_UNUSED GstMessage * msg,
- gpointer user_data)
-{
- GstPlayer *self = GST_PLAYER (user_data);
- gint64 duration = GST_CLOCK_TIME_NONE;
-
- if (gst_element_query_duration (self->playbin, GST_FORMAT_TIME, &duration)) {
- emit_duration_changed (self, duration);
- }
-}
-
-static void
-latency_cb (G_GNUC_UNUSED GstBus * bus, G_GNUC_UNUSED GstMessage * msg,
- gpointer user_data)
-{
- GstPlayer *self = GST_PLAYER (user_data);
-
- GST_DEBUG_OBJECT (self, "Latency changed");
-
- gst_bin_recalculate_latency (GST_BIN (self->playbin));
-}
-
-static void
-request_state_cb (G_GNUC_UNUSED GstBus * bus, GstMessage * msg,
- gpointer user_data)
-{
- GstPlayer *self = GST_PLAYER (user_data);
- GstState state;
- GstStateChangeReturn state_ret;
-
- gst_message_parse_request_state (msg, &state);
-
- GST_DEBUG_OBJECT (self, "State %s requested",
- gst_element_state_get_name (state));
-
- self->target_state = state;
- state_ret = gst_element_set_state (self->playbin, state);
- if (state_ret == GST_STATE_CHANGE_FAILURE)
- emit_error (self, g_error_new (GST_PLAYER_ERROR, GST_PLAYER_ERROR_FAILED,
- "Failed to change to requested state %s",
- gst_element_state_get_name (state)));
-}
-
-static void
-media_info_update (GstPlayer * self, GstPlayerMediaInfo * info)
-{
- g_free (info->title);
- info->title = get_from_tags (self, info, get_title);
-
- g_free (info->container);
- info->container = get_from_tags (self, info, get_container_format);
-
- if (info->image_sample)
- gst_sample_unref (info->image_sample);
- info->image_sample = get_from_tags (self, info, get_cover_sample);
-
- GST_DEBUG_OBJECT (self, "title: %s, container: %s "
- "image_sample: %p", info->title, info->container, info->image_sample);
-}
-
-static void
-tags_cb (G_GNUC_UNUSED GstBus * bus, GstMessage * msg, gpointer user_data)
-{
- GstPlayer *self = GST_PLAYER (user_data);
- GstTagList *tags = NULL;
-
- gst_message_parse_tag (msg, &tags);
-
- GST_DEBUG_OBJECT (self, "received %s tags",
- gst_tag_list_get_scope (tags) ==
- GST_TAG_SCOPE_GLOBAL ? "global" : "stream");
-
- if (gst_tag_list_get_scope (tags) == GST_TAG_SCOPE_GLOBAL) {
- g_mutex_lock (&self->lock);
- if (self->media_info) {
- if (self->media_info->tags)
- gst_tag_list_unref (self->media_info->tags);
- self->media_info->tags = gst_tag_list_ref (tags);
- media_info_update (self, self->media_info);
- g_mutex_unlock (&self->lock);
- emit_media_info_updated_signal (self);
- } else {
- if (self->global_tags)
- gst_tag_list_unref (self->global_tags);
- self->global_tags = gst_tag_list_ref (tags);
- g_mutex_unlock (&self->lock);
- }
- }
-
- gst_tag_list_unref (tags);
-}
-
-static void
-element_cb (G_GNUC_UNUSED GstBus * bus, GstMessage * msg, gpointer user_data)
-{
- GstPlayer *self = GST_PLAYER (user_data);
- const GstStructure *s;
-
- s = gst_message_get_structure (msg);
- if (gst_structure_has_name (s, "redirect")) {
- const gchar *new_location;
-
- new_location = gst_structure_get_string (s, "new-location");
- if (!new_location) {
- const GValue *locations_list, *location_val;
- guint i, size;
-
- locations_list = gst_structure_get_value (s, "locations");
- size = gst_value_list_get_size (locations_list);
- for (i = 0; i < size; ++i) {
- const GstStructure *location_s;
-
- location_val = gst_value_list_get_value (locations_list, i);
- if (!GST_VALUE_HOLDS_STRUCTURE (location_val))
- continue;
-
- location_s = (const GstStructure *) g_value_get_boxed (location_val);
- if (!gst_structure_has_name (location_s, "redirect"))
- continue;
-
- new_location = gst_structure_get_string (location_s, "new-location");
- if (new_location)
- break;
- }
- }
-
- if (new_location) {
- GstState target_state;
-
- GST_DEBUG_OBJECT (self, "Redirect to '%s'", new_location);
-
- /* Remember target state and restore after setting the URI */
- target_state = self->target_state;
-
- gst_player_stop_internal (self, TRUE);
-
- g_mutex_lock (&self->lock);
- g_free (self->redirect_uri);
- self->redirect_uri = g_strdup (new_location);
- g_object_set (self->playbin, "uri", self->redirect_uri, NULL);
- g_mutex_unlock (&self->lock);
-
- if (target_state == GST_STATE_PAUSED)
- gst_player_pause_internal (self);
- else if (target_state == GST_STATE_PLAYING)
- gst_player_play_internal (self);
- }
- }
-}
-
-/* Must be called with lock */
-static gboolean
-update_stream_collection (GstPlayer * self, GstStreamCollection * collection)
-{
- if (self->collection && self->collection == collection)
- return FALSE;
-
- if (self->collection && self->stream_notify_id)
- g_signal_handler_disconnect (self->collection, self->stream_notify_id);
-
- gst_object_replace ((GstObject **) & self->collection,
- (GstObject *) collection);
- if (self->media_info) {
- gst_object_unref (self->media_info);
- self->media_info = gst_player_media_info_create (self);
- }
-
- self->stream_notify_id =
- g_signal_connect (self->collection, "stream-notify",
- G_CALLBACK (stream_notify_cb), self);
-
- return TRUE;
-}
-
-static void
-stream_collection_cb (G_GNUC_UNUSED GstBus * bus, GstMessage * msg,
- gpointer user_data)
-{
- GstPlayer *self = GST_PLAYER (user_data);
- GstStreamCollection *collection = NULL;
- gboolean updated = FALSE;
-
- gst_message_parse_stream_collection (msg, &collection);
-
- if (!collection)
- return;
-
- g_mutex_lock (&self->lock);
- updated = update_stream_collection (self, collection);
- gst_object_unref (collection);
- g_mutex_unlock (&self->lock);
-
- if (self->media_info && updated)
- emit_media_info_updated_signal (self);
-}
-
-static void
-streams_selected_cb (G_GNUC_UNUSED GstBus * bus, GstMessage * msg,
- gpointer user_data)
-{
- GstPlayer *self = GST_PLAYER (user_data);
- GstStreamCollection *collection = NULL;
- gboolean updated = FALSE;
- guint i, len;
-
- gst_message_parse_streams_selected (msg, &collection);
-
- if (!collection)
- return;
-
- g_mutex_lock (&self->lock);
- updated = update_stream_collection (self, collection);
- gst_object_unref (collection);
-
- g_free (self->video_sid);
- g_free (self->audio_sid);
- g_free (self->subtitle_sid);
- self->video_sid = NULL;
- self->audio_sid = NULL;
- self->subtitle_sid = NULL;
-
- len = gst_message_streams_selected_get_size (msg);
- for (i = 0; i < len; i++) {
- GstStream *stream;
- GstStreamType stream_type;
- const gchar *stream_id;
- gchar **current_sid;
- stream = gst_message_streams_selected_get_stream (msg, i);
- stream_type = gst_stream_get_stream_type (stream);
- stream_id = gst_stream_get_stream_id (stream);
- if (stream_type & GST_STREAM_TYPE_AUDIO)
- current_sid = &self->audio_sid;
- else if (stream_type & GST_STREAM_TYPE_VIDEO)
- current_sid = &self->video_sid;
- else if (stream_type & GST_STREAM_TYPE_TEXT)
- current_sid = &self->subtitle_sid;
- else {
- GST_WARNING_OBJECT (self,
- "Unknown stream-id %s with type 0x%x", stream_id, stream_type);
- continue;
- }
-
- if (G_UNLIKELY (*current_sid)) {
- GST_FIXME_OBJECT (self,
- "Multiple streams are selected for type %s, choose the first one",
- gst_stream_type_get_name (stream_type));
- continue;
- }
-
- *current_sid = g_strdup (stream_id);
- }
- g_mutex_unlock (&self->lock);
-
- if (self->media_info && updated)
- emit_media_info_updated_signal (self);
-}
-
-static void
-player_set_flag (GstPlayer * self, gint pos)
-{
- gint flags;
-
- g_object_get (self->playbin, "flags", &flags, NULL);
- flags |= pos;
- g_object_set (self->playbin, "flags", flags, NULL);
-
- GST_DEBUG_OBJECT (self, "setting flags=%#x", flags);
-}
-
-static void
-player_clear_flag (GstPlayer * self, gint pos)
-{
- gint flags;
-
- g_object_get (self->playbin, "flags", &flags, NULL);
- flags &= ~pos;
- g_object_set (self->playbin, "flags", flags, NULL);
-
- GST_DEBUG_OBJECT (self, "setting flags=%#x", flags);
-}
-
-typedef struct
-{
- GstPlayer *player;
- GstPlayerMediaInfo *info;
-} MediaInfoUpdatedSignalData;
-
-static void
-media_info_updated_dispatch (gpointer user_data)
-{
- MediaInfoUpdatedSignalData *data = user_data;
-
- if (data->player->inhibit_sigs)
- return;
-
- if (data->player->target_state >= GST_STATE_PAUSED) {
- g_signal_emit (data->player, signals[SIGNAL_MEDIA_INFO_UPDATED], 0,
- data->info);
- }
-}
-
-static void
-free_media_info_updated_signal_data (MediaInfoUpdatedSignalData * data)
-{
- g_object_unref (data->player);
- g_object_unref (data->info);
- g_free (data);
-}
-
-/*
- * emit_media_info_updated_signal:
- *
- * create a new copy of self->media_info object and emits the newly created
- * copy to user application. The newly created media_info will be unref'ed
- * as part of signal finalize method.
- */
-static void
-emit_media_info_updated_signal (GstPlayer * self)
-{
- MediaInfoUpdatedSignalData *data = g_new (MediaInfoUpdatedSignalData, 1);
- data->player = g_object_ref (self);
- g_mutex_lock (&self->lock);
- data->info = gst_player_media_info_copy (self->media_info);
- g_mutex_unlock (&self->lock);
-
- gst_player_signal_dispatcher_dispatch (self->signal_dispatcher, self,
- media_info_updated_dispatch, data,
- (GDestroyNotify) free_media_info_updated_signal_data);
-}
-
-static GstCaps *
-get_caps (GstPlayer * self, gint stream_index, GType type)
-{
- GstPad *pad = NULL;
- GstCaps *caps = NULL;
-
- if (type == GST_TYPE_PLAYER_VIDEO_INFO)
- g_signal_emit_by_name (G_OBJECT (self->playbin),
- "get-video-pad", stream_index, &pad);
- else if (type == GST_TYPE_PLAYER_AUDIO_INFO)
- g_signal_emit_by_name (G_OBJECT (self->playbin),
- "get-audio-pad", stream_index, &pad);
- else
- g_signal_emit_by_name (G_OBJECT (self->playbin),
- "get-text-pad", stream_index, &pad);
-
- if (pad) {
- caps = gst_pad_get_current_caps (pad);
- gst_object_unref (pad);
- }
-
- return caps;
-}
-
-static void
-gst_player_subtitle_info_update (GstPlayer * self,
- GstPlayerStreamInfo * stream_info)
-{
- GstPlayerSubtitleInfo *info = (GstPlayerSubtitleInfo *) stream_info;
-
- if (stream_info->tags) {
-
- /* free the old language info */
- g_free (info->language);
- info->language = NULL;
-
- /* First try to get the language full name from tag, if name is not
- * available then try language code. If we find the language code
- * then use gstreamer api to translate code to full name.
- */
- gst_tag_list_get_string (stream_info->tags, GST_TAG_LANGUAGE_NAME,
- &info->language);
- if (!info->language) {
- gchar *lang_code = NULL;
-
- gst_tag_list_get_string (stream_info->tags, GST_TAG_LANGUAGE_CODE,
- &lang_code);
- if (lang_code) {
- info->language = g_strdup (gst_tag_get_language_name (lang_code));
- g_free (lang_code);
- }
- }
-
- /* If we are still failed to find language name then check if external
- * subtitle is loaded and compare the stream index between current sub
- * stream index with our stream index and if matches then declare it as
- * external subtitle and use the filename.
- */
- if (!info->language) {
- gint text_index = -1;
- gchar *suburi = NULL;
-
- g_object_get (G_OBJECT (self->playbin), "current-suburi", &suburi, NULL);
- if (suburi) {
- if (self->use_playbin3) {
- if (g_str_equal (self->subtitle_sid, stream_info->stream_id))
- info->language = g_path_get_basename (suburi);
- } else {
- g_object_get (G_OBJECT (self->playbin), "current-text", &text_index,
- NULL);
- if (text_index == gst_player_stream_info_get_index (stream_info))
- info->language = g_path_get_basename (suburi);
- }
- g_free (suburi);
- }
- }
-
- } else {
- g_free (info->language);
- info->language = NULL;
- }
-
- GST_DEBUG_OBJECT (self, "language=%s", info->language);
-}
-
-static void
-gst_player_video_info_update (GstPlayer * self,
- GstPlayerStreamInfo * stream_info)
-{
- GstPlayerVideoInfo *info = (GstPlayerVideoInfo *) stream_info;
-
- if (stream_info->caps) {
- GstStructure *s;
-
- s = gst_caps_get_structure (stream_info->caps, 0);
- if (s) {
- gint width, height;
- gint fps_n, fps_d;
- gint par_n, par_d;
-
- if (gst_structure_get_int (s, "width", &width))
- info->width = width;
- else
- info->width = -1;
-
- if (gst_structure_get_int (s, "height", &height))
- info->height = height;
- else
- info->height = -1;
-
- if (gst_structure_get_fraction (s, "framerate", &fps_n, &fps_d)) {
- info->framerate_num = fps_n;
- info->framerate_denom = fps_d;
- } else {
- info->framerate_num = 0;
- info->framerate_denom = 1;
- }
-
-
- if (gst_structure_get_fraction (s, "pixel-aspect-ratio", &par_n, &par_d)) {
- info->par_num = par_n;
- info->par_denom = par_d;
- } else {
- info->par_num = 1;
- info->par_denom = 1;
- }
- }
- } else {
- info->width = info->height = -1;
- info->par_num = info->par_denom = 1;
- info->framerate_num = 0;
- info->framerate_denom = 1;
- }
-
- if (stream_info->tags) {
- guint bitrate, max_bitrate;
-
- if (gst_tag_list_get_uint (stream_info->tags, GST_TAG_BITRATE, &bitrate))
- info->bitrate = bitrate;
- else
- info->bitrate = -1;
-
- if (gst_tag_list_get_uint (stream_info->tags, GST_TAG_MAXIMUM_BITRATE,
- &max_bitrate) || gst_tag_list_get_uint (stream_info->tags,
- GST_TAG_NOMINAL_BITRATE, &max_bitrate))
- info->max_bitrate = max_bitrate;
- else
- info->max_bitrate = -1;
- } else {
- info->bitrate = info->max_bitrate = -1;
- }
-
- GST_DEBUG_OBJECT (self, "width=%d height=%d fps=%.2f par=%d:%d "
- "bitrate=%d max_bitrate=%d", info->width, info->height,
- (gdouble) info->framerate_num / info->framerate_denom,
- info->par_num, info->par_denom, info->bitrate, info->max_bitrate);
-}
-
-static void
-gst_player_audio_info_update (GstPlayer * self,
- GstPlayerStreamInfo * stream_info)
-{
- GstPlayerAudioInfo *info = (GstPlayerAudioInfo *) stream_info;
-
- if (stream_info->caps) {
- GstStructure *s;
-
- s = gst_caps_get_structure (stream_info->caps, 0);
- if (s) {
- gint rate, channels;
-
- if (gst_structure_get_int (s, "rate", &rate))
- info->sample_rate = rate;
- else
- info->sample_rate = -1;
-
- if (gst_structure_get_int (s, "channels", &channels))
- info->channels = channels;
- else
- info->channels = 0;
- }
- } else {
- info->sample_rate = -1;
- info->channels = 0;
- }
-
- if (stream_info->tags) {
- guint bitrate, max_bitrate;
-
- if (gst_tag_list_get_uint (stream_info->tags, GST_TAG_BITRATE, &bitrate))
- info->bitrate = bitrate;
- else
- info->bitrate = -1;
-
- if (gst_tag_list_get_uint (stream_info->tags, GST_TAG_MAXIMUM_BITRATE,
- &max_bitrate) || gst_tag_list_get_uint (stream_info->tags,
- GST_TAG_NOMINAL_BITRATE, &max_bitrate))
- info->max_bitrate = max_bitrate;
- else
- info->max_bitrate = -1;
-
- /* if we have old language the free it */
- g_free (info->language);
- info->language = NULL;
-
- /* First try to get the language full name from tag, if name is not
- * available then try language code. If we find the language code
- * then use gstreamer api to translate code to full name.
- */
- gst_tag_list_get_string (stream_info->tags, GST_TAG_LANGUAGE_NAME,
- &info->language);
- if (!info->language) {
- gchar *lang_code = NULL;
-
- gst_tag_list_get_string (stream_info->tags, GST_TAG_LANGUAGE_CODE,
- &lang_code);
- if (lang_code) {
- info->language = g_strdup (gst_tag_get_language_name (lang_code));
- g_free (lang_code);
- }
- }
- } else {
- g_free (info->language);
- info->language = NULL;
- info->max_bitrate = info->bitrate = -1;
- }
-
- GST_DEBUG_OBJECT (self, "language=%s rate=%d channels=%d bitrate=%d "
- "max_bitrate=%d", info->language, info->sample_rate, info->channels,
- info->bitrate, info->max_bitrate);
-}
-
-static GstPlayerStreamInfo *
-gst_player_stream_info_find (GstPlayerMediaInfo * media_info,
- GType type, gint stream_index)
+static gpointer
+gst_player_init_once (G_GNUC_UNUSED gpointer user_data)
{
- GList *list, *l;
- GstPlayerStreamInfo *info = NULL;
-
- if (!media_info)
- return NULL;
-
- list = gst_player_media_info_get_stream_list (media_info);
- for (l = list; l != NULL; l = l->next) {
- info = (GstPlayerStreamInfo *) l->data;
- if ((G_OBJECT_TYPE (info) == type) && (info->stream_index == stream_index)) {
- return info;
- }
- }
-
- return NULL;
-}
+ gst_init (NULL, NULL);
-static GstPlayerStreamInfo *
-gst_player_stream_info_find_from_stream_id (GstPlayerMediaInfo * media_info,
- const gchar * stream_id)
-{
- GList *list, *l;
- GstPlayerStreamInfo *info = NULL;
-
- if (!media_info)
- return NULL;
-
- list = gst_player_media_info_get_stream_list (media_info);
- for (l = list; l != NULL; l = l->next) {
- info = (GstPlayerStreamInfo *) l->data;
- if (g_str_equal (info->stream_id, stream_id)) {
- return info;
- }
- }
+ GST_DEBUG_CATEGORY_INIT (gst_player_debug, "gst-player", 0, "GstPlayer");
+ gst_player_error_quark ();
return NULL;
}
-static gboolean
-is_track_enabled (GstPlayer * self, gint pos)
-{
- gint flags;
-
- g_object_get (G_OBJECT (self->playbin), "flags", &flags, NULL);
-
- if ((flags & pos))
- return TRUE;
-
- return FALSE;
-}
-
-static GstPlayerStreamInfo *
-gst_player_stream_info_get_current (GstPlayer * self, const gchar * prop,
- GType type)
-{
- gint current;
- GstPlayerStreamInfo *info;
-
- if (!self->media_info)
- return NULL;
-
- g_object_get (G_OBJECT (self->playbin), prop, &current, NULL);
- g_mutex_lock (&self->lock);
- info = gst_player_stream_info_find (self->media_info, type, current);
- if (info)
- info = gst_player_stream_info_copy (info);
- g_mutex_unlock (&self->lock);
-
- return info;
-}
-
-static GstPlayerStreamInfo *
-gst_player_stream_info_get_current_from_stream_id (GstPlayer * self,
- const gchar * stream_id, GType type)
-{
- GstPlayerStreamInfo *info;
-
- if (!self->media_info || !stream_id)
- return NULL;
-
- g_mutex_lock (&self->lock);
- info =
- gst_player_stream_info_find_from_stream_id (self->media_info, stream_id);
- if (info && G_OBJECT_TYPE (info) == type)
- info = gst_player_stream_info_copy (info);
- else
- info = NULL;
- g_mutex_unlock (&self->lock);
-
- return info;
-}
-
static void
-stream_notify_cb (GstStreamCollection * collection, GstStream * stream,
- GParamSpec * pspec, GstPlayer * self)
-{
- GstPlayerStreamInfo *info;
- const gchar *stream_id;
- gboolean emit_signal = FALSE;
-
- if (!self->media_info)
- return;
-
- if (G_PARAM_SPEC_VALUE_TYPE (pspec) != GST_TYPE_CAPS &&
- G_PARAM_SPEC_VALUE_TYPE (pspec) != GST_TYPE_TAG_LIST)
- return;
-
- stream_id = gst_stream_get_stream_id (stream);
- g_mutex_lock (&self->lock);
- info =
- gst_player_stream_info_find_from_stream_id (self->media_info, stream_id);
- if (info) {
- gst_player_stream_info_update_from_stream (self, info, stream);
- emit_signal = TRUE;
- }
- g_mutex_unlock (&self->lock);
-
- if (emit_signal)
- emit_media_info_updated_signal (self);
-}
-
-static void
-gst_player_stream_info_update (GstPlayer * self, GstPlayerStreamInfo * s)
-{
- if (GST_IS_PLAYER_VIDEO_INFO (s))
- gst_player_video_info_update (self, s);
- else if (GST_IS_PLAYER_AUDIO_INFO (s))
- gst_player_audio_info_update (self, s);
- else
- gst_player_subtitle_info_update (self, s);
-}
-
-static gchar *
-stream_info_get_codec (GstPlayerStreamInfo * s)
+uri_loaded_cb (GstPlaySignalAdapter * adapter, const gchar * uri,
+ GstPlayer * self)
{
- const gchar *type;
- GstTagList *tags;
- gchar *codec = NULL;
-
- if (GST_IS_PLAYER_VIDEO_INFO (s))
- type = GST_TAG_VIDEO_CODEC;
- else if (GST_IS_PLAYER_AUDIO_INFO (s))
- type = GST_TAG_AUDIO_CODEC;
- else
- type = GST_TAG_SUBTITLE_CODEC;
-
- tags = gst_player_stream_info_get_tags (s);
- if (tags) {
- gst_tag_list_get_string (tags, type, &codec);
- if (!codec)
- gst_tag_list_get_string (tags, GST_TAG_CODEC, &codec);
- }
-
- if (!codec) {
- GstCaps *caps;
- caps = gst_player_stream_info_get_caps (s);
- if (caps) {
- codec = gst_pb_utils_get_codec_description (caps);
- }
- }
-
- return codec;
+ g_signal_emit (self, signals[SIGNAL_URI_LOADED], 0, uri);
}
static void
-gst_player_stream_info_update_tags_and_caps (GstPlayer * self,
- GstPlayerStreamInfo * s)
+position_updated_cb (GstPlaySignalAdapter * adapter, GstClockTime position,
+ GstPlayer * self)
{
- GstTagList *tags;
- gint stream_index;
-
- stream_index = gst_player_stream_info_get_index (s);
-
- if (GST_IS_PLAYER_VIDEO_INFO (s))
- g_signal_emit_by_name (self->playbin, "get-video-tags",
- stream_index, &tags);
- else if (GST_IS_PLAYER_AUDIO_INFO (s))
- g_signal_emit_by_name (self->playbin, "get-audio-tags",
- stream_index, &tags);
- else
- g_signal_emit_by_name (self->playbin, "get-text-tags", stream_index, &tags);
-
- if (s->tags)
- gst_tag_list_unref (s->tags);
- s->tags = tags;
-
- if (s->caps)
- gst_caps_unref (s->caps);
- s->caps = get_caps (self, stream_index, G_OBJECT_TYPE (s));
-
- g_free (s->codec);
- s->codec = stream_info_get_codec (s);
-
- GST_DEBUG_OBJECT (self, "%s index: %d tags: %p caps: %p",
- gst_player_stream_info_get_stream_type (s), stream_index,
- s->tags, s->caps);
-
- gst_player_stream_info_update (self, s);
+ g_signal_emit (self, signals[SIGNAL_POSITION_UPDATED], 0, position);
}
static void
-gst_player_streams_info_create (GstPlayer * self,
- GstPlayerMediaInfo * media_info, const gchar * prop, GType type)
-{
- gint i;
- gint total = -1;
- GstPlayerStreamInfo *s;
-
- if (!media_info)
- return;
-
- g_object_get (G_OBJECT (self->playbin), prop, &total, NULL);
-
- GST_DEBUG_OBJECT (self, "%s: %d", prop, total);
-
- for (i = 0; i < total; i++) {
- /* check if stream already exist in the list */
- s = gst_player_stream_info_find (media_info, type, i);
-
- if (!s) {
- /* create a new stream info instance */
- s = gst_player_stream_info_new (i, type);
-
- /* add the object in stream list */
- media_info->stream_list = g_list_append (media_info->stream_list, s);
-
- /* based on type, add the object in its corresponding stream_ list */
- if (GST_IS_PLAYER_AUDIO_INFO (s))
- media_info->audio_stream_list = g_list_append
- (media_info->audio_stream_list, s);
- else if (GST_IS_PLAYER_VIDEO_INFO (s))
- media_info->video_stream_list = g_list_append
- (media_info->video_stream_list, s);
- else
- media_info->subtitle_stream_list = g_list_append
- (media_info->subtitle_stream_list, s);
-
- GST_DEBUG_OBJECT (self, "create %s stream stream_index: %d",
- gst_player_stream_info_get_stream_type (s), i);
- }
-
- gst_player_stream_info_update_tags_and_caps (self, s);
- }
-}
-
-static void
-gst_player_stream_info_update_from_stream (GstPlayer * self,
- GstPlayerStreamInfo * s, GstStream * stream)
+duration_changed_cb (GstPlaySignalAdapter * adapter, GstClockTime duraton,
+ GstPlayer * self)
{
- if (s->tags)
- gst_tag_list_unref (s->tags);
- s->tags = gst_stream_get_tags (stream);
-
- if (s->caps)
- gst_caps_unref (s->caps);
- s->caps = gst_stream_get_caps (stream);
-
- g_free (s->codec);
- s->codec = stream_info_get_codec (s);
-
- GST_DEBUG_OBJECT (self, "%s index: %d tags: %p caps: %p",
- gst_player_stream_info_get_stream_type (s), s->stream_index,
- s->tags, s->caps);
-
- gst_player_stream_info_update (self, s);
+ g_signal_emit (self, signals[SIGNAL_DURATION_CHANGED], 0, duraton);
}
static void
-gst_player_streams_info_create_from_collection (GstPlayer * self,
- GstPlayerMediaInfo * media_info, GstStreamCollection * collection)
+state_changed_cb (GstPlaySignalAdapter * adapter, GstPlayState state,
+ GstPlayer * self)
{
- guint i;
- guint total;
- GstPlayerStreamInfo *s;
- guint n_audio = 0;
- guint n_video = 0;
- guint n_text = 0;
-
- if (!media_info || !collection)
- return;
-
- total = gst_stream_collection_get_size (collection);
-
- for (i = 0; i < total; i++) {
- GstStream *stream = gst_stream_collection_get_stream (collection, i);
- GstStreamType stream_type = gst_stream_get_stream_type (stream);
- const gchar *stream_id = gst_stream_get_stream_id (stream);
-
- if (stream_type & GST_STREAM_TYPE_AUDIO) {
- s = gst_player_stream_info_new (n_audio, GST_TYPE_PLAYER_AUDIO_INFO);
- n_audio++;
- } else if (stream_type & GST_STREAM_TYPE_VIDEO) {
- s = gst_player_stream_info_new (n_video, GST_TYPE_PLAYER_VIDEO_INFO);
- n_video++;
- } else if (stream_type & GST_STREAM_TYPE_TEXT) {
- s = gst_player_stream_info_new (n_text, GST_TYPE_PLAYER_SUBTITLE_INFO);
- n_text++;
- } else {
- GST_DEBUG_OBJECT (self, "Unknown type stream %d", i);
- continue;
- }
-
- s->stream_id = g_strdup (stream_id);
-
- /* add the object in stream list */
- media_info->stream_list = g_list_append (media_info->stream_list, s);
-
- /* based on type, add the object in its corresponding stream_ list */
- if (GST_IS_PLAYER_AUDIO_INFO (s))
- media_info->audio_stream_list = g_list_append
- (media_info->audio_stream_list, s);
- else if (GST_IS_PLAYER_VIDEO_INFO (s))
- media_info->video_stream_list = g_list_append
- (media_info->video_stream_list, s);
- else
- media_info->subtitle_stream_list = g_list_append
- (media_info->subtitle_stream_list, s);
-
- GST_DEBUG_OBJECT (self, "create %s stream stream_index: %d",
- gst_player_stream_info_get_stream_type (s), s->stream_index);
-
- gst_player_stream_info_update_from_stream (self, s, stream);
+ GstPlayerState s = GST_PLAYER_STATE_BUFFERING;
+ switch (state) {
+ case GST_PLAY_STATE_BUFFERING:
+ s = GST_PLAYER_STATE_BUFFERING;
+ break;
+ case GST_PLAY_STATE_PAUSED:
+ s = GST_PLAYER_STATE_PAUSED;
+ break;
+ case GST_PLAY_STATE_PLAYING:
+ s = GST_PLAYER_STATE_PLAYING;
+ break;
+ case GST_PLAY_STATE_STOPPED:
+ s = GST_PLAYER_STATE_STOPPED;
+ break;
}
+ g_signal_emit (self, signals[SIGNAL_STATE_CHANGED], 0, s);
}
static void
-video_changed_cb (G_GNUC_UNUSED GObject * object, gpointer user_data)
-{
- GstPlayer *self = GST_PLAYER (user_data);
-
- g_mutex_lock (&self->lock);
- gst_player_streams_info_create (self, self->media_info,
- "n-video", GST_TYPE_PLAYER_VIDEO_INFO);
- g_mutex_unlock (&self->lock);
-}
-
-static void
-audio_changed_cb (G_GNUC_UNUSED GObject * object, gpointer user_data)
+buffering_cb (GstPlaySignalAdapter * adapter, gint buffering_percent,
+ GstPlayer * self)
{
- GstPlayer *self = GST_PLAYER (user_data);
-
- g_mutex_lock (&self->lock);
- gst_player_streams_info_create (self, self->media_info,
- "n-audio", GST_TYPE_PLAYER_AUDIO_INFO);
- g_mutex_unlock (&self->lock);
+ g_signal_emit (self, signals[SIGNAL_BUFFERING], 0, buffering_percent);
}
static void
-subtitle_changed_cb (G_GNUC_UNUSED GObject * object, gpointer user_data)
-{
- GstPlayer *self = GST_PLAYER (user_data);
-
- g_mutex_lock (&self->lock);
- gst_player_streams_info_create (self, self->media_info,
- "n-text", GST_TYPE_PLAYER_SUBTITLE_INFO);
- g_mutex_unlock (&self->lock);
-}
-
-static void *
-get_title (GstTagList * tags)
-{
- gchar *title = NULL;
-
- gst_tag_list_get_string (tags, GST_TAG_TITLE, &title);
- if (!title)
- gst_tag_list_get_string (tags, GST_TAG_TITLE_SORTNAME, &title);
-
- return title;
-}
-
-static void *
-get_container_format (GstTagList * tags)
-{
- gchar *container = NULL;
-
- gst_tag_list_get_string (tags, GST_TAG_CONTAINER_FORMAT, &container);
-
- /* TODO: If container is not available then maybe consider
- * parsing caps or file extension to guess the container format.
- */
-
- return container;
-}
-
-static void *
-get_from_tags (GstPlayer * self, GstPlayerMediaInfo * media_info,
- void *(*func) (GstTagList *))
-{
- GList *l;
- void *ret = NULL;
-
- if (media_info->tags) {
- ret = func (media_info->tags);
- if (ret)
- return ret;
- }
-
- /* if global tag does not exit then try video and audio streams */
- GST_DEBUG_OBJECT (self, "trying video tags");
- for (l = gst_player_media_info_get_video_streams (media_info); l != NULL;
- l = l->next) {
- GstTagList *tags;
-
- tags = gst_player_stream_info_get_tags ((GstPlayerStreamInfo *) l->data);
- if (tags)
- ret = func (tags);
-
- if (ret)
- return ret;
- }
-
- GST_DEBUG_OBJECT (self, "trying audio tags");
- for (l = gst_player_media_info_get_audio_streams (media_info); l != NULL;
- l = l->next) {
- GstTagList *tags;
-
- tags = gst_player_stream_info_get_tags ((GstPlayerStreamInfo *) l->data);
- if (tags)
- ret = func (tags);
-
- if (ret)
- return ret;
- }
-
- GST_DEBUG_OBJECT (self, "failed to get the information from tags");
- return NULL;
-}
-
-static void *
-get_cover_sample (GstTagList * tags)
-{
- GstSample *cover_sample = NULL;
-
- gst_tag_list_get_sample (tags, GST_TAG_IMAGE, &cover_sample);
- if (!cover_sample)
- gst_tag_list_get_sample (tags, GST_TAG_PREVIEW_IMAGE, &cover_sample);
-
- return cover_sample;
-}
-
-static GstPlayerMediaInfo *
-gst_player_media_info_create (GstPlayer * self)
+end_of_stream_cb (GstPlaySignalAdapter * adapter, GstPlayer * self)
{
- GstPlayerMediaInfo *media_info;
- GstQuery *query;
-
- GST_DEBUG_OBJECT (self, "begin");
- media_info = gst_player_media_info_new (self->uri);
- media_info->duration = gst_player_get_duration (self);
- media_info->tags = self->global_tags;
- media_info->is_live = self->is_live;
- self->global_tags = NULL;
-
- query = gst_query_new_seeking (GST_FORMAT_TIME);
- if (gst_element_query (self->playbin, query))
- gst_query_parse_seeking (query, NULL, &media_info->seekable, NULL, NULL);
- gst_query_unref (query);
-
- if (self->use_playbin3 && self->collection) {
- gst_player_streams_info_create_from_collection (self, media_info,
- self->collection);
- } else {
- /* create audio/video/sub streams */
- gst_player_streams_info_create (self, media_info, "n-video",
- GST_TYPE_PLAYER_VIDEO_INFO);
- gst_player_streams_info_create (self, media_info, "n-audio",
- GST_TYPE_PLAYER_AUDIO_INFO);
- gst_player_streams_info_create (self, media_info, "n-text",
- GST_TYPE_PLAYER_SUBTITLE_INFO);
- }
-
- media_info->title = get_from_tags (self, media_info, get_title);
- media_info->container =
- get_from_tags (self, media_info, get_container_format);
- media_info->image_sample = get_from_tags (self, media_info, get_cover_sample);
-
- GST_DEBUG_OBJECT (self, "uri: %s title: %s duration: %" GST_TIME_FORMAT
- " seekable: %s live: %s container: %s image_sample %p",
- media_info->uri, media_info->title, GST_TIME_ARGS (media_info->duration),
- media_info->seekable ? "yes" : "no", media_info->is_live ? "yes" : "no",
- media_info->container, media_info->image_sample);
-
- GST_DEBUG_OBJECT (self, "end");
- return media_info;
+ g_signal_emit (self, signals[SIGNAL_END_OF_STREAM], 0, NULL);
}
static void
-tags_changed_cb (GstPlayer * self, gint stream_index, GType type)
+error_cb (GstPlaySignalAdapter * adapter, GError * error,
+ GstStructure * details, GstPlayer * self)
{
- GstPlayerStreamInfo *s;
-
- if (!self->media_info)
- return;
-
- /* update the stream information */
- g_mutex_lock (&self->lock);
- s = gst_player_stream_info_find (self->media_info, type, stream_index);
- gst_player_stream_info_update_tags_and_caps (self, s);
- g_mutex_unlock (&self->lock);
-
- emit_media_info_updated_signal (self);
+ g_signal_emit (self, signals[SIGNAL_ERROR], 0, error);
}
static void
-video_tags_changed_cb (G_GNUC_UNUSED GstElement * playbin, gint stream_index,
- gpointer user_data)
+dimensions_changed_cb (GstPlaySignalAdapter * adapter, guint width,
+ guint height, GstPlayer * self)
{
- tags_changed_cb (GST_PLAYER (user_data), stream_index,
- GST_TYPE_PLAYER_VIDEO_INFO);
+ g_signal_emit (self, signals[SIGNAL_VIDEO_DIMENSIONS_CHANGED], 0, width,
+ height);
}
static void
-audio_tags_changed_cb (G_GNUC_UNUSED GstElement * playbin, gint stream_index,
- gpointer user_data)
+media_info_cb (GstPlaySignalAdapter * adapter, GstPlayMediaInfo * info,
+ GstPlayer * self)
{
- tags_changed_cb (GST_PLAYER (user_data), stream_index,
- GST_TYPE_PLAYER_AUDIO_INFO);
+ GstPlayerMediaInfo *i = gst_player_media_info_wrapped (info);
+ g_signal_emit (self, signals[SIGNAL_MEDIA_INFO_UPDATED], 0, i);
+ g_object_unref (i);
}
static void
-subtitle_tags_changed_cb (G_GNUC_UNUSED GstElement * playbin, gint stream_index,
- gpointer user_data)
+volume_cb (GstPlaySignalAdapter * adapter, gdouble volume, GstPlayer * self)
{
- tags_changed_cb (GST_PLAYER (user_data), stream_index,
- GST_TYPE_PLAYER_SUBTITLE_INFO);
+ g_signal_emit (self, signals[SIGNAL_VOLUME_CHANGED], 0, NULL);
}
-static void
-volume_changed_dispatch (gpointer user_data)
-{
- GstPlayer *player = user_data;
-
- if (player->inhibit_sigs)
- return;
-
- g_signal_emit (player, signals[SIGNAL_VOLUME_CHANGED], 0);
- g_object_notify_by_pspec (G_OBJECT (player), param_specs[PROP_VOLUME]);
-}
static void
-volume_notify_cb (G_GNUC_UNUSED GObject * obj, G_GNUC_UNUSED GParamSpec * pspec,
- GstPlayer * self)
+mute_cb (GstPlaySignalAdapter * adapter, gboolean muted, GstPlayer * self)
{
- if (g_signal_handler_find (self, G_SIGNAL_MATCH_ID,
- signals[SIGNAL_VOLUME_CHANGED], 0, NULL, NULL, NULL) != 0) {
- gst_player_signal_dispatcher_dispatch (self->signal_dispatcher, self,
- volume_changed_dispatch, g_object_ref (self),
- (GDestroyNotify) g_object_unref);
- }
+ g_signal_emit (self, signals[SIGNAL_MUTE_CHANGED], 0, NULL);
}
static void
-mute_changed_dispatch (gpointer user_data)
+warning_cb (GstPlaySignalAdapter * adapter, GError * warning,
+ GstStructure * details, GstPlayer * self)
{
- GstPlayer *player = user_data;
-
- if (player->inhibit_sigs)
- return;
-
- g_signal_emit (player, signals[SIGNAL_MUTE_CHANGED], 0);
- g_object_notify_by_pspec (G_OBJECT (player), param_specs[PROP_MUTE]);
+ g_signal_emit (self, signals[SIGNAL_WARNING], 0, warning);
}
static void
-mute_notify_cb (G_GNUC_UNUSED GObject * obj, G_GNUC_UNUSED GParamSpec * pspec,
+seek_done_cb (GstPlaySignalAdapter * adapter, GstClockTime time,
GstPlayer * self)
{
- if (g_signal_handler_find (self, G_SIGNAL_MATCH_ID,
- signals[SIGNAL_MUTE_CHANGED], 0, NULL, NULL, NULL) != 0) {
- gst_player_signal_dispatcher_dispatch (self->signal_dispatcher, self,
- mute_changed_dispatch, g_object_ref (self),
- (GDestroyNotify) g_object_unref);
- }
-}
-
-static void
-source_setup_cb (GstElement * playbin, GstElement * source, GstPlayer * self)
-{
- gchar *user_agent;
-
- user_agent = gst_player_config_get_user_agent (self->config);
- if (user_agent) {
- GParamSpec *prop;
-
- prop = g_object_class_find_property (G_OBJECT_GET_CLASS (source),
- "user-agent");
- if (prop && prop->value_type == G_TYPE_STRING) {
- GST_INFO_OBJECT (self, "Setting source user-agent: %s", user_agent);
- g_object_set (source, "user-agent", user_agent, NULL);
- }
-
- g_free (user_agent);
- }
-}
-
-static gpointer
-gst_player_main (gpointer data)
-{
- GstPlayer *self = GST_PLAYER (data);
- GstBus *bus;
- GSource *source;
- GstElement *scaletempo;
- const gchar *env;
-
- GST_TRACE_OBJECT (self, "Starting main thread");
-
- g_main_context_push_thread_default (self->context);
-
- source = g_idle_source_new ();
- g_source_set_callback (source, (GSourceFunc) main_loop_running_cb, self,
- NULL);
- g_source_attach (source, self->context);
- g_source_unref (source);
-
- env = g_getenv ("GST_PLAYER_USE_PLAYBIN3");
- if (env && g_str_has_prefix (env, "1"))
- self->use_playbin3 = TRUE;
-
- if (self->use_playbin3) {
- GST_DEBUG_OBJECT (self, "playbin3 enabled");
- self->playbin = gst_element_factory_make ("playbin3", "playbin3");
- } else {
- self->playbin = gst_element_factory_make ("playbin", "playbin");
- }
-
- if (!self->playbin) {
- g_error ("GstPlayer: 'playbin' element not found, please check your setup");
- g_assert_not_reached ();
- }
-
- gst_object_ref_sink (self->playbin);
-
- if (self->video_renderer) {
- GstElement *video_sink =
- gst_player_video_renderer_create_video_sink (self->video_renderer,
- self);
-
- if (video_sink)
- g_object_set (self->playbin, "video-sink", video_sink, NULL);
- }
-
- scaletempo = gst_element_factory_make ("scaletempo", NULL);
- if (scaletempo) {
- g_object_set (self->playbin, "audio-filter", scaletempo, NULL);
- } else {
- g_warning ("GstPlayer: scaletempo element not available. Audio pitch "
- "will not be preserved during trick modes");
- }
-
- self->bus = bus = gst_element_get_bus (self->playbin);
- gst_bus_add_signal_watch (bus);
-
- g_signal_connect (G_OBJECT (bus), "message::error", G_CALLBACK (error_cb),
- self);
- g_signal_connect (G_OBJECT (bus), "message::warning", G_CALLBACK (warning_cb),
- self);
- g_signal_connect (G_OBJECT (bus), "message::eos", G_CALLBACK (eos_cb), self);
- g_signal_connect (G_OBJECT (bus), "message::state-changed",
- G_CALLBACK (state_changed_cb), self);
- g_signal_connect (G_OBJECT (bus), "message::buffering",
- G_CALLBACK (buffering_cb), self);
- g_signal_connect (G_OBJECT (bus), "message::clock-lost",
- G_CALLBACK (clock_lost_cb), self);
- g_signal_connect (G_OBJECT (bus), "message::duration-changed",
- G_CALLBACK (duration_changed_cb), self);
- g_signal_connect (G_OBJECT (bus), "message::latency",
- G_CALLBACK (latency_cb), self);
- g_signal_connect (G_OBJECT (bus), "message::request-state",
- G_CALLBACK (request_state_cb), self);
- g_signal_connect (G_OBJECT (bus), "message::element",
- G_CALLBACK (element_cb), self);
- g_signal_connect (G_OBJECT (bus), "message::tag", G_CALLBACK (tags_cb), self);
-
- if (self->use_playbin3) {
- g_signal_connect (G_OBJECT (bus), "message::stream-collection",
- G_CALLBACK (stream_collection_cb), self);
- g_signal_connect (G_OBJECT (bus), "message::streams-selected",
- G_CALLBACK (streams_selected_cb), self);
- } else {
- g_signal_connect (self->playbin, "video-changed",
- G_CALLBACK (video_changed_cb), self);
- g_signal_connect (self->playbin, "audio-changed",
- G_CALLBACK (audio_changed_cb), self);
- g_signal_connect (self->playbin, "text-changed",
- G_CALLBACK (subtitle_changed_cb), self);
-
- g_signal_connect (self->playbin, "video-tags-changed",
- G_CALLBACK (video_tags_changed_cb), self);
- g_signal_connect (self->playbin, "audio-tags-changed",
- 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::volume",
- G_CALLBACK (volume_notify_cb), self);
- g_signal_connect (self->playbin, "notify::mute",
- G_CALLBACK (mute_notify_cb), self);
- g_signal_connect (self->playbin, "source-setup",
- G_CALLBACK (source_setup_cb), self);
-
- self->target_state = GST_STATE_NULL;
- self->current_state = GST_STATE_NULL;
- change_state (self, GST_PLAYER_STATE_STOPPED);
- self->buffering = 100;
- self->is_eos = FALSE;
- self->is_live = FALSE;
- self->rate = 1.0;
-
- GST_TRACE_OBJECT (self, "Starting main loop");
- g_main_loop_run (self->loop);
- GST_TRACE_OBJECT (self, "Stopped main loop");
-
- gst_bus_remove_signal_watch (bus);
- gst_object_unref (bus);
-
- remove_tick_source (self);
- remove_ready_timeout_source (self);
-
- g_mutex_lock (&self->lock);
- if (self->media_info) {
- g_object_unref (self->media_info);
- self->media_info = NULL;
- }
-
- remove_seek_source (self);
- g_mutex_unlock (&self->lock);
-
- g_main_context_pop_thread_default (self->context);
-
- self->target_state = GST_STATE_NULL;
- self->current_state = GST_STATE_NULL;
- if (self->playbin) {
- gst_element_set_state (self->playbin, GST_STATE_NULL);
- gst_object_unref (self->playbin);
- self->playbin = NULL;
- }
-
- GST_TRACE_OBJECT (self, "Stopped main thread");
-
- return NULL;
-}
-
-static gpointer
-gst_player_init_once (G_GNUC_UNUSED gpointer user_data)
-{
- gst_init (NULL, NULL);
-
- GST_DEBUG_CATEGORY_INIT (gst_player_debug, "gst-player", 0, "GstPlayer");
- gst_player_error_quark ();
-
- return NULL;
+ g_signal_emit (self, signals[SIGNAL_SEEK_DONE], 0, time);
}
/**
@@ -3051,76 +565,64 @@ gst_player_new (GstPlayerVideoRenderer * video_renderer,
{
static GOnce once = G_ONCE_INIT;
GstPlayer *self;
+ GstPlayerVideoRenderer *renderer = NULL;
g_once (&once, gst_player_init_once, NULL);
self =
- g_object_new (GST_TYPE_PLAYER, "video-renderer", video_renderer,
- "signal-dispatcher", signal_dispatcher, NULL);
- gst_object_ref_sink (self);
-
- if (video_renderer)
- g_object_unref (video_renderer);
- if (signal_dispatcher)
- g_object_unref (signal_dispatcher);
-
- return self;
-}
-
-static gboolean
-gst_player_play_internal (gpointer user_data)
-{
- GstPlayer *self = GST_PLAYER (user_data);
- GstStateChangeReturn state_ret;
-
- GST_DEBUG_OBJECT (self, "Play");
+ g_object_new (GST_TYPE_PLAYER, "signal-dispatcher", signal_dispatcher,
+ NULL);
- g_mutex_lock (&self->lock);
- if (!self->uri) {
- g_mutex_unlock (&self->lock);
- return G_SOURCE_REMOVE;
+ if (video_renderer != NULL) {
+ renderer = gst_player_wrapped_video_renderer_new (video_renderer, self);
}
- g_mutex_unlock (&self->lock);
+ self->play = gst_play_new (GST_PLAY_VIDEO_RENDERER (renderer));
- remove_ready_timeout_source (self);
- self->target_state = GST_STATE_PLAYING;
+ if (signal_dispatcher != NULL) {
+ GMainContext *context = NULL;
- if (self->current_state < GST_STATE_PAUSED)
- change_state (self, GST_PLAYER_STATE_BUFFERING);
-
- if (self->current_state >= GST_STATE_PAUSED && !self->is_eos
- && self->buffering >= 100 && !(self->seek_position != GST_CLOCK_TIME_NONE
- || self->seek_pending)) {
- state_ret = gst_element_set_state (self->playbin, GST_STATE_PLAYING);
+ g_object_get (signal_dispatcher, "application-context", &context, NULL);
+ self->signal_adapter =
+ gst_play_signal_adapter_new_with_main_context (self->play, context);
+ g_main_context_unref (context);
} else {
- state_ret = gst_element_set_state (self->playbin, GST_STATE_PAUSED);
+ self->signal_adapter = gst_play_signal_adapter_new (self->play);
}
- if (state_ret == GST_STATE_CHANGE_FAILURE) {
- emit_error (self, g_error_new (GST_PLAYER_ERROR, GST_PLAYER_ERROR_FAILED,
- "Failed to play"));
- return G_SOURCE_REMOVE;
- } else if (state_ret == GST_STATE_CHANGE_NO_PREROLL) {
- self->is_live = TRUE;
- GST_DEBUG_OBJECT (self, "Pipeline is live");
- }
+ gst_object_ref_sink (self);
- if (self->is_eos) {
- gboolean ret;
-
- GST_DEBUG_OBJECT (self, "Was EOS, seeking to beginning");
- self->is_eos = FALSE;
- ret =
- gst_element_seek_simple (self->playbin, GST_FORMAT_TIME,
- GST_SEEK_FLAG_FLUSH, 0);
- if (!ret) {
- GST_ERROR_OBJECT (self, "Seek to beginning failed");
- gst_player_stop_internal (self, TRUE);
- gst_player_play_internal (self);
- }
- }
+ g_signal_connect (self->signal_adapter, "uri-loaded",
+ G_CALLBACK (uri_loaded_cb), self);
+ g_signal_connect (self->signal_adapter, "position-updated",
+ G_CALLBACK (position_updated_cb), self);
+ g_signal_connect (self->signal_adapter, "duration-changed",
+ G_CALLBACK (duration_changed_cb), self);
+ g_signal_connect (self->signal_adapter, "state-changed",
+ G_CALLBACK (state_changed_cb), self);
+ g_signal_connect (self->signal_adapter, "buffering",
+ G_CALLBACK (buffering_cb), self);
+ g_signal_connect (self->signal_adapter, "end-of-stream",
+ G_CALLBACK (end_of_stream_cb), self);
+ g_signal_connect (self->signal_adapter, "error", G_CALLBACK (error_cb), self);
+ g_signal_connect (self->signal_adapter, "video-dimensions-changed",
+ G_CALLBACK (dimensions_changed_cb), self);
+ g_signal_connect (self->signal_adapter, "media-info-updated",
+ G_CALLBACK (media_info_cb), self);
+ g_signal_connect (self->signal_adapter, "volume-changed",
+ G_CALLBACK (volume_cb), self);
+ g_signal_connect (self->signal_adapter, "mute-changed", G_CALLBACK (mute_cb),
+ self);
+ g_signal_connect (self->signal_adapter, "warning", G_CALLBACK (warning_cb),
+ self);
+ g_signal_connect (self->signal_adapter, "seek-done",
+ G_CALLBACK (seek_done_cb), self);
- return G_SOURCE_REMOVE;
+ if (video_renderer)
+ g_object_unref (video_renderer);
+ if (signal_dispatcher)
+ g_object_unref (signal_dispatcher);
+
+ return self;
}
/**
@@ -3134,64 +636,7 @@ gst_player_play (GstPlayer * self)
{
g_return_if_fail (GST_IS_PLAYER (self));
- g_mutex_lock (&self->lock);
- self->inhibit_sigs = FALSE;
- g_mutex_unlock (&self->lock);
-
- g_main_context_invoke_full (self->context, G_PRIORITY_DEFAULT,
- gst_player_play_internal, self, NULL);
-}
-
-static gboolean
-gst_player_pause_internal (gpointer user_data)
-{
- GstPlayer *self = GST_PLAYER (user_data);
- GstStateChangeReturn state_ret;
-
- GST_DEBUG_OBJECT (self, "Pause");
-
- g_mutex_lock (&self->lock);
- if (!self->uri) {
- g_mutex_unlock (&self->lock);
- return G_SOURCE_REMOVE;
- }
- g_mutex_unlock (&self->lock);
-
- tick_cb (self);
- remove_tick_source (self);
- remove_ready_timeout_source (self);
-
- self->target_state = GST_STATE_PAUSED;
-
- if (self->current_state < GST_STATE_PAUSED)
- change_state (self, GST_PLAYER_STATE_BUFFERING);
-
- state_ret = gst_element_set_state (self->playbin, GST_STATE_PAUSED);
- if (state_ret == GST_STATE_CHANGE_FAILURE) {
- emit_error (self, g_error_new (GST_PLAYER_ERROR, GST_PLAYER_ERROR_FAILED,
- "Failed to pause"));
- return G_SOURCE_REMOVE;
- } else if (state_ret == GST_STATE_CHANGE_NO_PREROLL) {
- self->is_live = TRUE;
- GST_DEBUG_OBJECT (self, "Pipeline is live");
- }
-
- if (self->is_eos) {
- gboolean ret;
-
- GST_DEBUG_OBJECT (self, "Was EOS, seeking to beginning");
- self->is_eos = FALSE;
- ret =
- gst_element_seek_simple (self->playbin, GST_FORMAT_TIME,
- GST_SEEK_FLAG_FLUSH, 0);
- if (!ret) {
- GST_ERROR_OBJECT (self, "Seek to beginning failed");
- gst_player_stop_internal (self, TRUE);
- gst_player_pause_internal (self);
- }
- }
-
- return G_SOURCE_REMOVE;
+ gst_play_play (self->play);
}
/**
@@ -3205,83 +650,9 @@ gst_player_pause (GstPlayer * self)
{
g_return_if_fail (GST_IS_PLAYER (self));
- g_mutex_lock (&self->lock);
- self->inhibit_sigs = FALSE;
- g_mutex_unlock (&self->lock);
-
- g_main_context_invoke_full (self->context, G_PRIORITY_DEFAULT,
- gst_player_pause_internal, self, NULL);
-}
-
-static void
-gst_player_stop_internal (GstPlayer * self, gboolean transient)
-{
- /* directly return if we're already stopped */
- if (self->current_state <= GST_STATE_READY &&
- self->target_state <= GST_STATE_READY)
- return;
-
- GST_DEBUG_OBJECT (self, "Stop (transient %d)", transient);
-
- tick_cb (self);
- remove_tick_source (self);
-
- add_ready_timeout_source (self);
-
- self->target_state = GST_STATE_NULL;
- self->current_state = GST_STATE_READY;
- self->is_live = FALSE;
- self->is_eos = FALSE;
- gst_bus_set_flushing (self->bus, TRUE);
- gst_element_set_state (self->playbin, GST_STATE_READY);
- gst_bus_set_flushing (self->bus, FALSE);
- change_state (self, transient
- && self->app_state !=
- GST_PLAYER_STATE_STOPPED ? GST_PLAYER_STATE_BUFFERING :
- GST_PLAYER_STATE_STOPPED);
- self->buffering = 100;
- self->cached_duration = GST_CLOCK_TIME_NONE;
- g_mutex_lock (&self->lock);
- if (self->media_info) {
- g_object_unref (self->media_info);
- self->media_info = NULL;
- }
- if (self->global_tags) {
- gst_tag_list_unref (self->global_tags);
- self->global_tags = NULL;
- }
- self->seek_pending = FALSE;
- remove_seek_source (self);
- self->seek_position = GST_CLOCK_TIME_NONE;
- self->last_seek_time = GST_CLOCK_TIME_NONE;
- self->rate = 1.0;
- if (self->collection) {
- if (self->stream_notify_id)
- g_signal_handler_disconnect (self->collection, self->stream_notify_id);
- self->stream_notify_id = 0;
- gst_object_unref (self->collection);
- self->collection = NULL;
- }
- g_free (self->video_sid);
- g_free (self->audio_sid);
- g_free (self->subtitle_sid);
- self->video_sid = NULL;
- self->audio_sid = NULL;
- self->subtitle_sid = NULL;
- g_mutex_unlock (&self->lock);
+ gst_play_pause (self->play);
}
-static gboolean
-gst_player_stop_internal_dispatch (gpointer user_data)
-{
- GstPlayer *self = GST_PLAYER (user_data);
-
- gst_player_stop_internal (self, FALSE);
-
- return G_SOURCE_REMOVE;
-}
-
-
/**
* gst_player_stop:
* @player: #GstPlayer instance
@@ -3294,97 +665,7 @@ gst_player_stop (GstPlayer * self)
{
g_return_if_fail (GST_IS_PLAYER (self));
- g_mutex_lock (&self->lock);
- self->inhibit_sigs = TRUE;
- g_mutex_unlock (&self->lock);
-
- g_main_context_invoke_full (self->context, G_PRIORITY_DEFAULT,
- gst_player_stop_internal_dispatch, self, NULL);
-}
-
-/* Must be called with lock from main context, releases lock! */
-static void
-gst_player_seek_internal_locked (GstPlayer * self)
-{
- gboolean ret;
- GstClockTime position;
- gdouble rate;
- GstStateChangeReturn state_ret;
- GstEvent *s_event;
- GstSeekFlags flags = 0;
- gboolean accurate = FALSE;
-
- remove_seek_source (self);
-
- /* Only seek in PAUSED */
- if (self->current_state < GST_STATE_PAUSED) {
- return;
- } else if (self->current_state != GST_STATE_PAUSED) {
- g_mutex_unlock (&self->lock);
- state_ret = gst_element_set_state (self->playbin, GST_STATE_PAUSED);
- if (state_ret == GST_STATE_CHANGE_FAILURE) {
- emit_error (self, g_error_new (GST_PLAYER_ERROR, GST_PLAYER_ERROR_FAILED,
- "Failed to seek"));
- g_mutex_lock (&self->lock);
- return;
- }
- g_mutex_lock (&self->lock);
- return;
- }
-
- self->last_seek_time = gst_util_get_timestamp ();
- position = self->seek_position;
- self->seek_position = GST_CLOCK_TIME_NONE;
- self->seek_pending = TRUE;
- rate = self->rate;
- g_mutex_unlock (&self->lock);
-
- remove_tick_source (self);
- self->is_eos = FALSE;
-
- flags |= GST_SEEK_FLAG_FLUSH;
-
- accurate = gst_player_config_get_seek_accurate (self->config);
-
- if (accurate) {
- flags |= GST_SEEK_FLAG_ACCURATE;
- } else {
- flags &= ~GST_SEEK_FLAG_ACCURATE;
- }
-
- if (rate != 1.0) {
- flags |= GST_SEEK_FLAG_TRICKMODE;
- }
-
- if (rate >= 0.0) {
- s_event = gst_event_new_seek (rate, GST_FORMAT_TIME, flags,
- GST_SEEK_TYPE_SET, position, GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE);
- } else {
- s_event = gst_event_new_seek (rate, GST_FORMAT_TIME, flags,
- GST_SEEK_TYPE_SET, G_GINT64_CONSTANT (0), GST_SEEK_TYPE_SET, position);
- }
-
- GST_DEBUG_OBJECT (self, "Seek with rate %.2lf to %" GST_TIME_FORMAT,
- rate, GST_TIME_ARGS (position));
-
- ret = gst_element_send_event (self->playbin, s_event);
- if (!ret)
- emit_error (self, g_error_new (GST_PLAYER_ERROR, GST_PLAYER_ERROR_FAILED,
- "Failed to seek to %" GST_TIME_FORMAT, GST_TIME_ARGS (position)));
-
- g_mutex_lock (&self->lock);
-}
-
-static gboolean
-gst_player_seek_internal (gpointer user_data)
-{
- GstPlayer *self = GST_PLAYER (user_data);
-
- g_mutex_lock (&self->lock);
- gst_player_seek_internal_locked (self);
- g_mutex_unlock (&self->lock);
-
- return G_SOURCE_REMOVE;
+ gst_play_stop (self->play);
}
/**
@@ -3435,58 +716,7 @@ gst_player_seek (GstPlayer * self, GstClockTime position)
g_return_if_fail (GST_IS_PLAYER (self));
g_return_if_fail (GST_CLOCK_TIME_IS_VALID (position));
- g_mutex_lock (&self->lock);
- if (self->media_info && !self->media_info->seekable) {
- GST_DEBUG_OBJECT (self, "Media is not seekable");
- g_mutex_unlock (&self->lock);
- return;
- }
-
- self->seek_position = position;
-
- /* If there is no seek being dispatch to the main context currently do that,
- * otherwise we just updated the seek position so that it will be taken by
- * the seek handler from the main context instead of the old one.
- */
- if (!self->seek_source) {
- GstClockTime now = gst_util_get_timestamp ();
-
- /* If no seek is pending or it was started more than 250 mseconds ago seek
- * immediately, otherwise wait until the 250 mseconds have passed */
- if (!self->seek_pending || (now - self->last_seek_time > 250 * GST_MSECOND)) {
- self->seek_source = g_idle_source_new ();
- g_source_set_callback (self->seek_source,
- (GSourceFunc) gst_player_seek_internal, self, NULL);
- GST_TRACE_OBJECT (self, "Dispatching seek to position %" GST_TIME_FORMAT,
- GST_TIME_ARGS (position));
- g_source_attach (self->seek_source, self->context);
- } else {
- guint delay = 250000 - (now - self->last_seek_time) / 1000;
-
- /* Note that last_seek_time must be set to something at this point and
- * it must be smaller than 250 mseconds */
- self->seek_source = g_timeout_source_new (delay);
- g_source_set_callback (self->seek_source,
- (GSourceFunc) gst_player_seek_internal, self, NULL);
-
- GST_TRACE_OBJECT (self,
- "Delaying seek to position %" GST_TIME_FORMAT " by %u us",
- GST_TIME_ARGS (position), delay);
- g_source_attach (self->seek_source, self->context);
- }
- }
- g_mutex_unlock (&self->lock);
-}
-
-static void
-remove_seek_source (GstPlayer * self)
-{
- if (!self->seek_source)
- return;
-
- g_source_destroy (self->seek_source);
- g_source_unref (self->seek_source);
- self->seek_source = NULL;
+ gst_play_seek (self->play, position);
}
/**
@@ -3704,18 +934,15 @@ gst_player_get_pipeline (GstPlayer * self)
GstPlayerMediaInfo *
gst_player_get_media_info (GstPlayer * self)
{
- GstPlayerMediaInfo *info;
+ GstPlayMediaInfo *info;
+ GstPlayerMediaInfo *ret;
g_return_val_if_fail (GST_IS_PLAYER (self), NULL);
- if (!self->media_info)
- return NULL;
-
- g_mutex_lock (&self->lock);
- info = gst_player_media_info_copy (self->media_info);
- g_mutex_unlock (&self->lock);
-
- return info;
+ info = gst_play_get_media_info (self->play);
+ ret = gst_player_media_info_wrapped (info);
+ g_object_unref (info);
+ return ret;
}
/**
@@ -3731,23 +958,17 @@ gst_player_get_media_info (GstPlayer * self)
GstPlayerAudioInfo *
gst_player_get_current_audio_track (GstPlayer * self)
{
- GstPlayerAudioInfo *info;
+ GstPlayAudioInfo *info;
+ GstPlayerAudioInfo *ret = NULL;
g_return_val_if_fail (GST_IS_PLAYER (self), NULL);
- if (!is_track_enabled (self, GST_PLAY_FLAG_AUDIO))
- return NULL;
-
- if (self->use_playbin3) {
- info = (GstPlayerAudioInfo *)
- gst_player_stream_info_get_current_from_stream_id (self,
- self->audio_sid, GST_TYPE_PLAYER_AUDIO_INFO);
- } else {
- info = (GstPlayerAudioInfo *) gst_player_stream_info_get_current (self,
- "current-audio", GST_TYPE_PLAYER_AUDIO_INFO);
+ info = gst_play_get_current_audio_track (self->play);
+ if (info != NULL) {
+ ret = gst_player_audio_info_wrapped (info);
+ g_object_unref (info);
}
-
- return info;
+ return ret;
}
/**
@@ -3763,23 +984,17 @@ gst_player_get_current_audio_track (GstPlayer * self)
GstPlayerVideoInfo *
gst_player_get_current_video_track (GstPlayer * self)
{
- GstPlayerVideoInfo *info;
+ GstPlayVideoInfo *info;
+ GstPlayerVideoInfo *ret = NULL;
g_return_val_if_fail (GST_IS_PLAYER (self), NULL);
- if (!is_track_enabled (self, GST_PLAY_FLAG_VIDEO))
- return NULL;
-
- if (self->use_playbin3) {
- info = (GstPlayerVideoInfo *)
- gst_player_stream_info_get_current_from_stream_id (self,
- self->video_sid, GST_TYPE_PLAYER_VIDEO_INFO);
- } else {
- info = (GstPlayerVideoInfo *) gst_player_stream_info_get_current (self,
- "current-video", GST_TYPE_PLAYER_VIDEO_INFO);
+ info = gst_play_get_current_video_track (self->play);
+ if (info != NULL) {
+ ret = gst_player_video_info_wrapped (info);
+ g_object_unref (info);
}
-
- return info;
+ return ret;
}
/**
@@ -3795,49 +1010,16 @@ gst_player_get_current_video_track (GstPlayer * self)
GstPlayerSubtitleInfo *
gst_player_get_current_subtitle_track (GstPlayer * self)
{
- GstPlayerSubtitleInfo *info;
+ GstPlaySubtitleInfo *info;
+ GstPlayerSubtitleInfo *ret = NULL;
g_return_val_if_fail (GST_IS_PLAYER (self), NULL);
- if (!is_track_enabled (self, GST_PLAY_FLAG_SUBTITLE))
- return NULL;
-
- if (self->use_playbin3) {
- info = (GstPlayerSubtitleInfo *)
- gst_player_stream_info_get_current_from_stream_id (self,
- self->subtitle_sid, GST_TYPE_PLAYER_SUBTITLE_INFO);
- } else {
- info = (GstPlayerSubtitleInfo *) gst_player_stream_info_get_current (self,
- "current-text", GST_TYPE_PLAYER_SUBTITLE_INFO);
- }
-
- return info;
-}
-
-/* Must be called with lock */
-static gboolean
-gst_player_select_streams (GstPlayer * self)
-{
- GList *stream_list = NULL;
- gboolean ret = FALSE;
-
- if (self->audio_sid)
- stream_list = g_list_append (stream_list, g_strdup (self->audio_sid));
- if (self->video_sid)
- stream_list = g_list_append (stream_list, g_strdup (self->video_sid));
- if (self->subtitle_sid)
- stream_list = g_list_append (stream_list, g_strdup (self->subtitle_sid));
-
- g_mutex_unlock (&self->lock);
- if (stream_list) {
- ret = gst_element_send_event (self->playbin,
- gst_event_new_select_streams (stream_list));
- g_list_free_full (stream_list, g_free);
- } else {
- GST_ERROR_OBJECT (self, "No available streams for select-streams");
+ info = gst_play_get_current_subtitle_track (self->play);
+ if (info != NULL) {
+ ret = gst_player_subtitle_info_wrapped (info);
+ g_object_unref (info);
}
- g_mutex_lock (&self->lock);
-
return ret;
}
@@ -3853,33 +1035,9 @@ gst_player_select_streams (GstPlayer * self)
gboolean
gst_player_set_audio_track (GstPlayer * self, gint stream_index)
{
- GstPlayerStreamInfo *info;
- gboolean ret = TRUE;
-
g_return_val_if_fail (GST_IS_PLAYER (self), 0);
- g_mutex_lock (&self->lock);
- info = gst_player_stream_info_find (self->media_info,
- GST_TYPE_PLAYER_AUDIO_INFO, stream_index);
- g_mutex_unlock (&self->lock);
- if (!info) {
- GST_ERROR_OBJECT (self, "invalid audio stream index %d", stream_index);
- return FALSE;
- }
-
- if (self->use_playbin3) {
- g_mutex_lock (&self->lock);
- g_free (self->audio_sid);
- self->audio_sid = g_strdup (info->stream_id);
- ret = gst_player_select_streams (self);
- g_mutex_unlock (&self->lock);
- } else {
- g_object_set (G_OBJECT (self->playbin), "current-audio", stream_index,
- NULL);
- }
-
- GST_DEBUG_OBJECT (self, "set stream index '%d'", stream_index);
- return ret;
+ return gst_play_set_audio_track (self->play, stream_index);
}
/**
@@ -3894,34 +1052,9 @@ gst_player_set_audio_track (GstPlayer * self, gint stream_index)
gboolean
gst_player_set_video_track (GstPlayer * self, gint stream_index)
{
- GstPlayerStreamInfo *info;
- gboolean ret = TRUE;
-
g_return_val_if_fail (GST_IS_PLAYER (self), 0);
- /* check if stream_index exist in our internal media_info list */
- g_mutex_lock (&self->lock);
- info = gst_player_stream_info_find (self->media_info,
- GST_TYPE_PLAYER_VIDEO_INFO, stream_index);
- g_mutex_unlock (&self->lock);
- if (!info) {
- GST_ERROR_OBJECT (self, "invalid video stream index %d", stream_index);
- return FALSE;
- }
-
- if (self->use_playbin3) {
- g_mutex_lock (&self->lock);
- g_free (self->video_sid);
- self->video_sid = g_strdup (info->stream_id);
- ret = gst_player_select_streams (self);
- g_mutex_unlock (&self->lock);
- } else {
- g_object_set (G_OBJECT (self->playbin), "current-video", stream_index,
- NULL);
- }
-
- GST_DEBUG_OBJECT (self, "set stream index '%d'", stream_index);
- return ret;
+ return gst_play_set_video_track (self->play, stream_index);
}
/**
@@ -3936,32 +1069,9 @@ gst_player_set_video_track (GstPlayer * self, gint stream_index)
gboolean
gst_player_set_subtitle_track (GstPlayer * self, gint stream_index)
{
- GstPlayerStreamInfo *info;
- gboolean ret = TRUE;
-
g_return_val_if_fail (GST_IS_PLAYER (self), 0);
- g_mutex_lock (&self->lock);
- info = gst_player_stream_info_find (self->media_info,
- GST_TYPE_PLAYER_SUBTITLE_INFO, stream_index);
- g_mutex_unlock (&self->lock);
- if (!info) {
- GST_ERROR_OBJECT (self, "invalid subtitle stream index %d", stream_index);
- return FALSE;
- }
-
- if (self->use_playbin3) {
- g_mutex_lock (&self->lock);
- g_free (self->subtitle_sid);
- self->subtitle_sid = g_strdup (info->stream_id);
- ret = gst_player_select_streams (self);
- g_mutex_unlock (&self->lock);
- } else {
- g_object_set (G_OBJECT (self->playbin), "current-text", stream_index, NULL);
- }
-
- GST_DEBUG_OBJECT (self, "set stream index '%d'", stream_index);
- return ret;
+ return gst_play_set_subtitle_track (self->play, stream_index);
}
/**
@@ -3976,12 +1086,7 @@ gst_player_set_audio_track_enabled (GstPlayer * self, gboolean enabled)
{
g_return_if_fail (GST_IS_PLAYER (self));
- if (enabled)
- player_set_flag (self, GST_PLAY_FLAG_AUDIO);
- else
- player_clear_flag (self, GST_PLAY_FLAG_AUDIO);
-
- GST_DEBUG_OBJECT (self, "track is '%s'", enabled ? "Enabled" : "Disabled");
+ gst_play_set_audio_track_enabled (self->play, enabled);
}
/**
@@ -3996,12 +1101,7 @@ gst_player_set_video_track_enabled (GstPlayer * self, gboolean enabled)
{
g_return_if_fail (GST_IS_PLAYER (self));
- if (enabled)
- player_set_flag (self, GST_PLAY_FLAG_VIDEO);
- else
- player_clear_flag (self, GST_PLAY_FLAG_VIDEO);
-
- GST_DEBUG_OBJECT (self, "track is '%s'", enabled ? "Enabled" : "Disabled");
+ gst_play_set_video_track_enabled (self->play, enabled);
}
/**
@@ -4016,12 +1116,7 @@ gst_player_set_subtitle_track_enabled (GstPlayer * self, gboolean enabled)
{
g_return_if_fail (GST_IS_PLAYER (self));
- if (enabled)
- player_set_flag (self, GST_PLAY_FLAG_SUBTITLE);
- else
- player_clear_flag (self, GST_PLAY_FLAG_SUBTITLE);
-
- GST_DEBUG_OBJECT (self, "track is '%s'", enabled ? "Enabled" : "Disabled");
+ gst_play_set_subtitle_track_enabled (self->play, enabled);
}
/**
@@ -4038,29 +1133,7 @@ gst_player_set_visualization (GstPlayer * self, const gchar * name)
{
g_return_val_if_fail (GST_IS_PLAYER (self), FALSE);
- g_mutex_lock (&self->lock);
- if (self->current_vis_element) {
- gst_object_unref (self->current_vis_element);
- self->current_vis_element = NULL;
- }
-
- if (name) {
- self->current_vis_element = gst_element_factory_make (name, NULL);
- if (!self->current_vis_element)
- goto error_no_element;
- gst_object_ref_sink (self->current_vis_element);
- }
- g_object_set (self->playbin, "vis-plugin", self->current_vis_element, NULL);
-
- g_mutex_unlock (&self->lock);
- GST_DEBUG_OBJECT (self, "set vis-plugin to '%s'", name);
-
- return TRUE;
-
-error_no_element:
- g_mutex_unlock (&self->lock);
- GST_WARNING_OBJECT (self, "could not find visualization '%s'", name);
- return FALSE;
+ return gst_play_set_visualization (self->play, name);
}
/**
@@ -4073,26 +1146,9 @@ error_no_element:
gchar *
gst_player_get_current_visualization (GstPlayer * self)
{
- gchar *name = NULL;
- GstElement *vis_plugin = NULL;
-
g_return_val_if_fail (GST_IS_PLAYER (self), NULL);
- if (!is_track_enabled (self, GST_PLAY_FLAG_VIS))
- return NULL;
-
- g_object_get (self->playbin, "vis-plugin", &vis_plugin, NULL);
-
- if (vis_plugin) {
- GstElementFactory *factory = gst_element_get_factory (vis_plugin);
- if (factory)
- name = g_strdup (gst_plugin_feature_get_name (factory));
- gst_object_unref (vis_plugin);
- }
-
- GST_DEBUG_OBJECT (self, "vis-plugin '%s' %p", name, vis_plugin);
-
- return name;
+ return gst_play_get_current_visualization (self->play);
}
/**
@@ -4107,13 +1163,7 @@ gst_player_set_visualization_enabled (GstPlayer * self, gboolean enabled)
{
g_return_if_fail (GST_IS_PLAYER (self));
- if (enabled)
- player_set_flag (self, GST_PLAY_FLAG_VIS);
- else
- player_clear_flag (self, GST_PLAY_FLAG_VIS);
-
- GST_DEBUG_OBJECT (self, "visualization is '%s'",
- enabled ? "Enabled" : "Disabled");
+ gst_play_set_visualization_enabled (self->play, enabled);
}
struct CBChannelMap
@@ -4129,28 +1179,6 @@ static const struct CBChannelMap cb_channel_map[] = {
/* GST_PLAYER_COLOR_BALANCE_HUE */ {"HUE", "hue"},
};
-static GstColorBalanceChannel *
-gst_player_color_balance_find_channel (GstPlayer * self,
- GstPlayerColorBalanceType type)
-{
- GstColorBalanceChannel *channel;
- const GList *l, *channels;
-
- if (type < GST_PLAYER_COLOR_BALANCE_BRIGHTNESS ||
- type > GST_PLAYER_COLOR_BALANCE_HUE)
- return NULL;
-
- channels =
- gst_color_balance_list_channels (GST_COLOR_BALANCE (self->playbin));
- for (l = channels; l; l = l->next) {
- channel = l->data;
- if (g_strrstr (channel->label, cb_channel_map[type].label))
- return channel;
- }
-
- return NULL;
-}
-
/**
* gst_player_has_color_balance:
* @player:#GstPlayer instance
@@ -4163,16 +1191,9 @@ gst_player_color_balance_find_channel (GstPlayer * self,
gboolean
gst_player_has_color_balance (GstPlayer * self)
{
- const GList *channels;
-
g_return_val_if_fail (GST_IS_PLAYER (self), FALSE);
- if (!GST_IS_COLOR_BALANCE (self->playbin))
- return FALSE;
-
- channels =
- gst_color_balance_list_channels (GST_COLOR_BALANCE (self->playbin));
- return (channels != NULL);
+ return gst_play_has_color_balance (self->play);
}
/**
@@ -4188,27 +1209,11 @@ void
gst_player_set_color_balance (GstPlayer * self, GstPlayerColorBalanceType type,
gdouble value)
{
- GstColorBalanceChannel *channel;
- gdouble new_val;
-
g_return_if_fail (GST_IS_PLAYER (self));
g_return_if_fail (value >= 0.0 && value <= 1.0);
- if (!GST_IS_COLOR_BALANCE (self->playbin))
- return;
-
- channel = gst_player_color_balance_find_channel (self, type);
- if (!channel)
- return;
-
- value = CLAMP (value, 0.0, 1.0);
-
- /* Convert to channel range */
- new_val = channel->min_value + value * ((gdouble) channel->max_value -
- (gdouble) channel->min_value);
-
- gst_color_balance_set_value (GST_COLOR_BALANCE (self->playbin), channel,
- new_val);
+ gst_play_set_color_balance (self->play, (GstPlayColorBalanceType) type,
+ value);
}
/**
@@ -4224,24 +1229,10 @@ gst_player_set_color_balance (GstPlayer * self, GstPlayerColorBalanceType type,
gdouble
gst_player_get_color_balance (GstPlayer * self, GstPlayerColorBalanceType type)
{
- GstColorBalanceChannel *channel;
- gint value;
-
g_return_val_if_fail (GST_IS_PLAYER (self), -1);
- if (!GST_IS_COLOR_BALANCE (self->playbin))
- return -1;
-
- channel = gst_player_color_balance_find_channel (self, type);
- if (!channel)
- return -1;
-
- value = gst_color_balance_get_value (GST_COLOR_BALANCE (self->playbin),
- channel);
-
- return ((gdouble) value -
- (gdouble) channel->min_value) / ((gdouble) channel->max_value -
- (gdouble) channel->min_value);
+ return gst_play_get_color_balance (self->play,
+ (GstPlayColorBalanceType) type);
}
/**
@@ -4558,21 +1549,7 @@ gst_player_set_config (GstPlayer * self, GstStructure * config)
g_return_val_if_fail (GST_IS_PLAYER (self), FALSE);
g_return_val_if_fail (config != NULL, FALSE);
- g_mutex_lock (&self->lock);
-
- if (self->app_state != GST_PLAYER_STATE_STOPPED) {
- GST_INFO_OBJECT (self, "can't change config while player is %s",
- gst_player_state_get_name (self->app_state));
- g_mutex_unlock (&self->lock);
- return FALSE;
- }
-
- if (self->config)
- gst_structure_free (self->config);
- self->config = config;
- g_mutex_unlock (&self->lock);
-
- return TRUE;
+ return gst_play_set_config (self->play, config);
}
/**
@@ -4591,15 +1568,9 @@ gst_player_set_config (GstPlayer * self, GstStructure * config)
GstStructure *
gst_player_get_config (GstPlayer * self)
{
- GstStructure *ret;
-
g_return_val_if_fail (GST_IS_PLAYER (self), NULL);
- g_mutex_lock (&self->lock);
- ret = gst_structure_copy (self->config);
- g_mutex_unlock (&self->lock);
-
- return ret;
+ return gst_play_get_config (self->play);
}
/**
@@ -4631,6 +1602,7 @@ gst_player_config_set_user_agent (GstStructure * config, const gchar * agent)
* gst_player_config_set_user_agent() if any.
*
* Returns: (transfer full): the configured agent, or %NULL
+ *
* Since: 1.10
*/
gchar *
@@ -4653,6 +1625,7 @@ gst_player_config_get_user_agent (const GstStructure * config)
*
* set interval in milliseconds between two position-updated signals.
* pass 0 to stop updating the position.
+ *
* Since: 1.10
*/
void
@@ -4755,78 +1728,8 @@ GstSample *
gst_player_get_video_snapshot (GstPlayer * self,
GstPlayerSnapshotFormat format, const GstStructure * config)
{
- gint video_tracks = 0;
- GstSample *sample = NULL;
- GstCaps *caps = NULL;
- gint width = -1;
- gint height = -1;
- gint par_n = 1;
- gint par_d = 1;
g_return_val_if_fail (GST_IS_PLAYER (self), NULL);
- g_object_get (self->playbin, "n-video", &video_tracks, NULL);
- if (video_tracks == 0) {
- GST_DEBUG_OBJECT (self, "total video track num is 0");
- return NULL;
- }
-
- switch (format) {
- case GST_PLAYER_THUMBNAIL_RAW_xRGB:
- caps = gst_caps_new_simple ("video/x-raw",
- "format", G_TYPE_STRING, "xRGB", NULL);
- break;
- case GST_PLAYER_THUMBNAIL_RAW_BGRx:
- caps = gst_caps_new_simple ("video/x-raw",
- "format", G_TYPE_STRING, "BGRx", NULL);
- break;
- case GST_PLAYER_THUMBNAIL_JPG:
- caps = gst_caps_new_empty_simple ("image/jpeg");
- break;
- case GST_PLAYER_THUMBNAIL_PNG:
- caps = gst_caps_new_empty_simple ("image/png");
- break;
- case GST_PLAYER_THUMBNAIL_RAW_NATIVE:
- default:
- caps = gst_caps_new_empty_simple ("video/x-raw");
- break;
- }
-
- if (NULL != config) {
- if (!gst_structure_get_int (config, "width", &width))
- width = -1;
- if (!gst_structure_get_int (config, "height", &height))
- height = -1;
- if (!gst_structure_get_fraction (config, "pixel-aspect-ratio", &par_n,
- &par_d)) {
- if (format != GST_PLAYER_THUMBNAIL_RAW_NATIVE) {
- par_n = 1;
- par_d = 1;
- } else {
- par_n = 0;
- par_d = 0;
- }
- }
- }
-
- if (width > 0 && height > 0) {
- gst_caps_set_simple (caps, "width", G_TYPE_INT, width,
- "height", G_TYPE_INT, height, NULL);
- }
-
- if (format != GST_PLAYER_THUMBNAIL_RAW_NATIVE) {
- gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
- par_n, par_d, NULL);
- } else if (NULL != config && par_n != 0 && par_d != 0) {
- gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
- par_n, par_d, NULL);
- }
-
- g_signal_emit_by_name (self->playbin, "convert-sample", caps, &sample);
- gst_caps_unref (caps);
- if (!sample) {
- GST_WARNING_OBJECT (self, "Failed to retrieve or convert video frame");
- return NULL;
- }
-
- return sample;
+ return gst_play_get_video_snapshot (self->play,
+ (GstPlaySnapshotFormat) format, config);
}
diff --git a/gst-libs/gst/player/meson.build b/gst-libs/gst/player/meson.build
index ea8fcc8f7..1056494a0 100644
--- a/gst-libs/gst/player/meson.build
+++ b/gst-libs/gst/player/meson.build
@@ -5,6 +5,7 @@ gstplayer_sources = [
'gstplayer-media-info.c',
'gstplayer-g-main-context-signal-dispatcher.c',
'gstplayer-video-overlay-video-renderer.c',
+ 'gstplayer-wrapped-video-renderer.c',
'gstplayer-visualization.c',
]
@@ -31,7 +32,7 @@ gstplayer = library('gstplayer-' + api_version,
soversion : soversion,
darwin_versions : osxversion,
install : true,
- dependencies : [gstbase_dep, gstvideo_dep, gstaudio_dep,
+ dependencies : [gstbase_dep, gstvideo_dep, gstaudio_dep, gstplay_dep,
gsttag_dep, gstpbutils_dep],
)
@@ -56,7 +57,7 @@ if build_gir
'GstAudio-1.0', 'GstTag-1.0'],
install : true,
extra_args : gir_init_section + ['-DGST_USE_UNSTABLE_API'] + ['--c-include=gst/player/player.h'],
- dependencies : [gstbase_dep, gstvideo_dep, gstaudio_dep,
+ dependencies : [gstbase_dep, gstvideo_dep, gstaudio_dep, gstplay_dep,
gsttag_dep, gstpbutils_dep]
)
gen_sources += player_gir
@@ -65,7 +66,7 @@ endif
gstplayer_dep = declare_dependency(link_with : gstplayer,
include_directories : [libsinc],
sources: gen_sources,
- dependencies : [gstbase_dep, gstvideo_dep, gstaudio_dep,
+ dependencies : [gstbase_dep, gstvideo_dep, gstaudio_dep, gstplay_dep,
gsttag_dep, gstpbutils_dep])
meson.override_dependency('gstreamer-player-1.0', gstplayer_dep)