diff --git a/meson.build b/meson.build
index 377fe254..1d5298f3 100644
--- a/meson.build
+++ b/meson.build
@@ -9,7 +9,7 @@ project('clapper', 'c',
)
glib_req = '>= 2.76.0'
-gst_req = '>= 1.20.0'
+gst_req = '>= 1.24.0'
gtk4_req = '>= 4.10.0'
adw_req = '>= 1.4.0'
diff --git a/pkgs/flatpak/com.github.rafostar.Clapper.json b/pkgs/flatpak/com.github.rafostar.Clapper.json
index 44d7611a..d18c46c5 100644
--- a/pkgs/flatpak/com.github.rafostar.Clapper.json
+++ b/pkgs/flatpak/com.github.rafostar.Clapper.json
@@ -1,11 +1,11 @@
{
"app-id": "com.github.rafostar.Clapper",
"runtime": "org.gnome.Platform",
- "runtime-version": "45",
+ "runtime-version": "47",
"sdk": "org.gnome.Sdk",
"add-extensions": {
"org.freedesktop.Platform.ffmpeg-full": {
- "version": "23.08",
+ "version": "24.08",
"directory": "lib/ffmpeg",
"add-ld-path": ".",
"no-autodownload": false,
@@ -40,15 +40,12 @@
"flathub/lib/libass.json",
"flathub/lib/uchardet.json",
"flathub/lib/libmicrodns.json",
- "flathub/gstreamer-1.0/gstreamer.json",
+ "testing/gstreamer_stable.json",
"testing/yt-dlp.json",
"testing/libpeas.json",
{
"name": "clapper",
"buildsystem": "meson",
- "config-opts": [
- "-Dc_args=\"-DHAVE_GST_PATCHES=1\""
- ],
"sources": [
{
"type": "dir",
diff --git a/pkgs/flatpak/testing/gstreamer_stable.json b/pkgs/flatpak/testing/gstreamer_stable.json
new file mode 100644
index 00000000..a9140864
--- /dev/null
+++ b/pkgs/flatpak/testing/gstreamer_stable.json
@@ -0,0 +1,99 @@
+{
+ "name": "gstreamer",
+ "buildsystem": "meson",
+ "config-opts": [
+ "--buildtype=release",
+ "--wrap-mode=nodownload",
+
+ "-Dbase=enabled",
+ "-Dgood=enabled",
+ "-Dbad=enabled",
+ "-Dugly=enabled",
+ "-Dlibav=enabled",
+ "-Dvaapi=enabled",
+ "-Dsharp=disabled",
+ "-Drs=disabled",
+ "-Dpython=disabled",
+ "-Ddevtools=disabled",
+ "-Dges=disabled",
+ "-Drtsp_server=disabled",
+ "-Dgst-examples=disabled",
+ "-Dqt5=disabled",
+ "-Dtests=disabled",
+ "-Dexamples=disabled",
+ "-Dintrospection=enabled",
+ "-Ddoc=disabled",
+ "-Dgtk_doc=disabled",
+ "-Dgpl=enabled",
+
+ "-Dgstreamer:benchmarks=disabled",
+ "-Dgstreamer:gobject-cast-checks=disabled",
+ "-Dgstreamer:glib-asserts=disabled",
+ "-Dgstreamer:glib-checks=disabled",
+ "-Dgstreamer:extra-checks=disabled",
+
+ "-Dgst-plugins-base:gobject-cast-checks=disabled",
+ "-Dgst-plugins-base:glib-asserts=disabled",
+ "-Dgst-plugins-base:glib-checks=disabled",
+ "-Dgst-plugins-base:gl_api=opengl,gles2",
+ "-Dgst-plugins-base:gl_platform=egl,glx",
+
+ "-Dgst-plugins-good:gobject-cast-checks=disabled",
+ "-Dgst-plugins-good:glib-asserts=disabled",
+ "-Dgst-plugins-good:glib-checks=disabled",
+ "-Dgst-plugins-good:gtk3=disabled",
+
+ "-Dgst-plugins-bad:gobject-cast-checks=disabled",
+ "-Dgst-plugins-bad:glib-asserts=disabled",
+ "-Dgst-plugins-bad:glib-checks=disabled",
+ "-Dgst-plugins-bad:extra-checks=disabled",
+ "-Dgst-plugins-bad:vulkan=disabled",
+ "-Dgst-plugins-bad:webrtc=disabled",
+ "-Dgst-plugins-bad:wasapi=disabled",
+ "-Dgst-plugins-bad:wasapi2=disabled",
+ "-Dgst-plugins-bad:winks=disabled",
+ "-Dgst-plugins-bad:winscreencap=disabled",
+ "-Dgst-plugins-bad:assrender=enabled",
+ "-Dgst-plugins-bad:nvcodec=enabled",
+ "-Dgst-plugins-bad:v4l2codecs=enabled",
+ "-Dgst-plugins-bad:va=enabled",
+
+ "-Dgst-plugins-ugly:gobject-cast-checks=disabled",
+ "-Dgst-plugins-ugly:glib-asserts=disabled",
+ "-Dgst-plugins-ugly:glib-checks=disabled",
+ "-Dgst-plugins-ugly:mpeg2dec=enabled"
+ ],
+ "sources": [
+ {
+ "type": "git",
+ "url": "https://gitlab.freedesktop.org/gstreamer/gstreamer.git",
+ "tag": "1.24.9",
+ "commit": "b309f90bfde36e6d175b70bfa0c941f2829dd6a5",
+ "disable-submodules": true
+ },
+ {
+ "type": "patch",
+ "path": "../flathub/gstreamer-1.0/gst-libav-stop-caching-codecs.patch"
+ },
+ {
+ "type": "patch",
+ "path": "../flathub/gstreamer-1.0/gst-plugins-base-autodetect-subtitle-text-encoding.patch"
+ },
+ {
+ "type": "patch",
+ "path": "../flathub/gstreamer-1.0/gst-plugins-good-matroska-fix-attachments-detection.patch"
+ },
+ {
+ "type": "patch",
+ "path": "../flathub/gstreamer-1.0/gst-plugins-good-dashdemux2-play-last-subfragment.patch"
+ },
+ {
+ "type": "patch",
+ "path": "../flathub/gstreamer-1.0/gst-plugins-bad-dashdemux-sidx-range-download.patch"
+ },
+ {
+ "type": "patch",
+ "path": "../flathub/gstreamer-1.0/gst-plugins-bad-dashdemux-improve-initial-representation-selection.patch"
+ }
+ ]
+}
diff --git a/src/bin/clapper-app/clapper-app-application.c b/src/bin/clapper-app/clapper-app-application.c
index 1232255a..703d8dec 100644
--- a/src/bin/clapper-app/clapper-app-application.c
+++ b/src/bin/clapper-app/clapper-app-application.c
@@ -144,6 +144,8 @@ clapper_app_apply_options_to_window (ClapperAppWindow *dest_window, GVariantDict
clapper_player_set_mute (dest_player, option_bool);
if (clapper_app_options_get ("speed", "d", options, src_player_obj, settings, &option_dbl))
clapper_player_set_speed (dest_player, PERCENTAGE_ROUND (CLAMP (option_dbl, 0.05, 2.0)));
+ if (clapper_app_options_get ("adaptive-start-bitrate", "i", options, src_player_obj, settings, &option_int))
+ clapper_player_set_adaptive_start_bitrate (dest_player, option_int);
if (clapper_app_options_get ("progression-mode", "i", options, src_queue_obj, settings, &option_int))
clapper_queue_set_progression_mode (clapper_player_get_queue (dest_player), CLAMP (option_int, 0, 4));
if (clapper_app_options_get ("subtitles-enabled", "b", NULL, src_player_obj, settings, &option_bool))
@@ -196,6 +198,8 @@ _store_settings_from_window (ClapperAppApplication *self, ClapperAppWindow *app_
g_settings_set_double (self->settings, "volume", clapper_player_get_volume (player));
g_settings_set_boolean (self->settings, "mute", clapper_player_get_mute (player));
g_settings_set_double (self->settings, "speed", clapper_player_get_speed (player));
+ g_settings_set_int (self->settings, "adaptive-start-bitrate",
+ CLAMP (clapper_player_get_adaptive_bandwidth (player) * 0.8, 0, G_MAXINT));
g_settings_set_boolean (self->settings, "subtitles-enabled", clapper_player_get_subtitles_enabled (player));
g_settings_set_int (self->settings, "progression-mode", clapper_queue_get_progression_mode (queue));
@@ -676,6 +680,7 @@ clapper_app_application_constructed (GObject *object)
{ "enqueue", 0, 0, G_OPTION_ARG_NONE, NULL, _("Add media to queue in primary application instance"), NULL },
{ "volume", 0, 0, G_OPTION_ARG_DOUBLE, NULL, _("Audio volume to set (0 - 2.0 range)"), NULL },
{ "speed", 0, 0, G_OPTION_ARG_DOUBLE, NULL, _("Playback speed to set (0.05 - 2.0 range)"), NULL },
+ { "adaptive-start-bitrate", 0, 0, G_OPTION_ARG_INT, NULL, _("Initial bitrate for adaptive streaming"), NULL },
{ "progression-mode", 0, 0, G_OPTION_ARG_INT, NULL, _("Initial queue progression mode (0=none, 1=consecutive, 2=repeat-item, 3=carousel, 4=shuffle)"), NULL },
{ "fullscreen", 'f', 0, G_OPTION_ARG_NONE, NULL, _("Set window to be fullscreen"), NULL },
{ "video-filter", 0, 0, G_OPTION_ARG_STRING, NULL, _("Video filter to use (\"none\" to disable)"), NULL },
diff --git a/src/bin/clapper-app/clapper-app-window.c b/src/bin/clapper-app/clapper-app-window.c
index c7d0dbdb..9157b1a2 100644
--- a/src/bin/clapper-app/clapper-app-window.c
+++ b/src/bin/clapper-app/clapper-app-window.c
@@ -151,6 +151,15 @@ _queue_current_item_changed_cb (ClapperQueue *queue,
gst_clear_object (¤t_item);
}
+static void
+_player_adaptive_bandwidth_changed_cb (ClapperPlayer *player,
+ GParamSpec *pspec G_GNUC_UNUSED, gpointer *user_data G_GNUC_UNUSED)
+{
+ /* Do not take whole bandwidth */
+ clapper_player_set_adaptive_start_bitrate (player,
+ clapper_player_get_adaptive_bandwidth (player) * 0.8);
+}
+
static gboolean
_get_seek_method_mapping (GValue *value,
GVariant *variant, gpointer user_data G_GNUC_UNUSED)
@@ -1280,10 +1289,12 @@ clapper_app_window_constructed (GObject *object)
clapper_player_set_autoplay (player, TRUE);
- /* No need to also call this here, as item is selected
+ /* No need to also call these here, as they only change
* after application window is contructed */
g_signal_connect (queue, "notify::current-item",
G_CALLBACK (_queue_current_item_changed_cb), self);
+ g_signal_connect (player, "notify::adaptive-bandwidth",
+ G_CALLBACK (_player_adaptive_bandwidth_changed_cb), NULL);
g_settings_bind (self->settings, "audio-offset",
player, "audio-offset", G_SETTINGS_BIND_GET);
diff --git a/src/bin/clapper-app/data/glib-2.0/schemas/com.github.rafostar.Clapper.gschema.xml b/src/bin/clapper-app/data/glib-2.0/schemas/com.github.rafostar.Clapper.gschema.xml
index a73d1d55..9429f861 100644
--- a/src/bin/clapper-app/data/glib-2.0/schemas/com.github.rafostar.Clapper.gschema.xml
+++ b/src/bin/clapper-app/data/glib-2.0/schemas/com.github.rafostar.Clapper.gschema.xml
@@ -49,6 +49,10 @@
1.0
Stores last speed value to apply on startup
+
+ 1600000
+ Stores initial adaptive streaming bitrate to apply on startup
+
1
Stores last queue progression mode used to apply on startup
diff --git a/src/lib/clapper/clapper-player-private.h b/src/lib/clapper/clapper-player-private.h
index b29f64dc..43116cd2 100644
--- a/src/lib/clapper/clapper-player-private.h
+++ b/src/lib/clapper/clapper-player-private.h
@@ -87,6 +87,9 @@ struct _ClapperPlayer
gboolean pending_eos; // when pausing due to EOS
gint eos; // atomic integer
+ /* Set adaptive props immediately */
+ GstElement *adaptive_demuxer;
+
/* Playbin2 compat */
gint n_video, n_audio, n_text;
@@ -104,6 +107,10 @@ struct _ClapperPlayer
gboolean subtitles_enabled;
gchar *download_dir;
gboolean download_enabled;
+ guint start_bitrate;
+ guint min_bitrate;
+ guint max_bitrate;
+ guint bandwidth;
gdouble audio_offset;
gdouble subtitle_offset;
};
diff --git a/src/lib/clapper/clapper-player.c b/src/lib/clapper/clapper-player.c
index dc15c258..52f4e22c 100644
--- a/src/lib/clapper/clapper-player.c
+++ b/src/lib/clapper/clapper-player.c
@@ -62,6 +62,7 @@
#define DEFAULT_AUDIO_ENABLED TRUE
#define DEFAULT_SUBTITLES_ENABLED TRUE
#define DEFAULT_DOWNLOAD_ENABLED FALSE
+#define DEFAULT_ADAPTIVE_START_BITRATE 1600000
#define GST_CAT_DEFAULT clapper_player_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
@@ -93,6 +94,10 @@ enum
PROP_SUBTITLES_ENABLED,
PROP_DOWNLOAD_DIR,
PROP_DOWNLOAD_ENABLED,
+ PROP_ADAPTIVE_START_BITRATE,
+ PROP_ADAPTIVE_MIN_BITRATE,
+ PROP_ADAPTIVE_MAX_BITRATE,
+ PROP_ADAPTIVE_BANDWIDTH,
PROP_AUDIO_OFFSET,
PROP_SUBTITLE_OFFSET,
PROP_SUBTITLE_FONT_DESC,
@@ -712,6 +717,32 @@ clapper_player_playbin_update_current_decoders (ClapperPlayer *self)
GST_DEBUG_OBJECT (self, "Active audio decoder not found");
}
+static void
+_adaptive_demuxer_bandwidth_changed_cb (GstElement *adaptive_demuxer,
+ GParamSpec *pspec G_GNUC_UNUSED, ClapperPlayer *self)
+{
+ guint bandwidth = 0;
+ gboolean changed;
+
+ g_object_get (adaptive_demuxer, "current-bandwidth", &bandwidth, NULL);
+
+ /* Skip uncalculated bandwidth from
+ * new adaptive demuxer instance */
+ if (bandwidth == 0)
+ return;
+
+ GST_OBJECT_LOCK (self);
+ if ((changed = bandwidth != self->bandwidth))
+ self->bandwidth = bandwidth;
+ GST_OBJECT_UNLOCK (self);
+
+ if (changed) {
+ GST_LOG_OBJECT (self, "Adaptive bandwidth: %u", bandwidth);
+ clapper_app_bus_post_prop_notify (self->app_bus,
+ GST_OBJECT_CAST (self), param_specs[PROP_ADAPTIVE_BANDWIDTH]);
+ }
+}
+
void
clapper_player_reset (ClapperPlayer *self, gboolean pending_dispose)
{
@@ -727,6 +758,12 @@ clapper_player_reset (ClapperPlayer *self, gboolean pending_dispose)
gst_clear_object (&self->audio_decoder);
}
+ if (self->adaptive_demuxer) {
+ g_signal_handlers_disconnect_by_func (self->adaptive_demuxer,
+ _adaptive_demuxer_bandwidth_changed_cb, self);
+ gst_clear_object (&self->adaptive_demuxer);
+ }
+
GST_OBJECT_UNLOCK (self);
gst_clear_tag_list (&self->pending_tags);
@@ -768,13 +805,15 @@ static void
_element_setup_cb (GstElement *playbin, GstElement *element, ClapperPlayer *self)
{
GstElementFactory *factory = gst_element_get_factory (element);
+ const gchar *factory_name;
if (G_UNLIKELY (factory == NULL))
return;
- GST_INFO_OBJECT (self, "Element setup: %s", GST_OBJECT_NAME (factory));
+ factory_name = g_intern_static_string (GST_OBJECT_NAME (factory));
+ GST_INFO_OBJECT (self, "Element setup: %s", factory_name);
- if (strcmp (GST_OBJECT_NAME (factory), "downloadbuffer") == 0) {
+ if (factory_name == g_intern_static_string ("downloadbuffer")) {
gchar *download_template;
/* Only set props if we have download template */
@@ -785,6 +824,37 @@ _element_setup_cb (GstElement *playbin, GstElement *element, ClapperPlayer *self
NULL);
g_free (download_template);
}
+ } else if (factory_name == g_intern_static_string ("dashdemux2")
+ || factory_name == g_intern_static_string ("hlsdemux2")) {
+ guint start_bitrate, min_bitrate, max_bitrate;
+
+ GST_OBJECT_LOCK (self);
+
+ start_bitrate = self->start_bitrate;
+ min_bitrate = self->min_bitrate;
+ max_bitrate = self->max_bitrate;
+
+ if (self->adaptive_demuxer) {
+ g_signal_handlers_disconnect_by_func (self->adaptive_demuxer,
+ _adaptive_demuxer_bandwidth_changed_cb, self);
+ }
+
+ gst_object_replace ((GstObject **) &self->adaptive_demuxer, GST_OBJECT_CAST (element));
+
+ if (self->adaptive_demuxer) {
+ g_signal_connect (self->adaptive_demuxer, "notify::current-bandwidth",
+ G_CALLBACK (_adaptive_demuxer_bandwidth_changed_cb), self);
+ }
+
+ GST_OBJECT_UNLOCK (self);
+
+ g_object_set (element,
+ "low-watermark-time", 3 * GST_SECOND,
+ "high-watermark-time", 10 * GST_SECOND,
+ "start-bitrate", start_bitrate,
+ "min-bitrate", min_bitrate,
+ "max-bitrate", max_bitrate,
+ NULL);
}
}
@@ -1668,6 +1738,193 @@ clapper_player_get_download_enabled (ClapperPlayer *self)
return enabled;
}
+static void
+_set_adaptive_bitrate (ClapperPlayer *self, guint *internal_ptr,
+ const gchar *prop_name, guint bitrate, GParamSpec *pspec)
+{
+ GstElement *element = NULL;
+ gboolean changed;
+
+ if (!self->use_playbin3) {
+ GST_WARNING_OBJECT (self, "Setting adaptive-%s when using playbin2"
+ " has no effect", prop_name);
+ }
+
+ GST_OBJECT_LOCK (self);
+ if ((changed = (*internal_ptr != bitrate))) {
+ *internal_ptr = bitrate;
+
+ if (self->adaptive_demuxer)
+ element = gst_object_ref (self->adaptive_demuxer);
+ }
+ GST_OBJECT_UNLOCK (self);
+
+ if (changed) {
+ GST_INFO_OBJECT (self, "Set adaptive-%s: %u", prop_name, bitrate);
+
+ if (element)
+ g_object_set (element, prop_name, bitrate, NULL);
+
+ clapper_app_bus_post_prop_notify (self->app_bus, GST_OBJECT_CAST (self), pspec);
+ }
+
+ gst_clear_object (&element);
+}
+
+/**
+ * clapper_player_set_adaptive_start_bitrate:
+ * @player: a #ClapperPlayer
+ * @bitrate: a bitrate to set (bits/s)
+ *
+ * Set initial bitrate to select when starting adaptive
+ * streaming such as DASH or HLS.
+ *
+ * Since: 0.8
+ */
+void
+clapper_player_set_adaptive_start_bitrate (ClapperPlayer *self, guint bitrate)
+{
+ g_return_if_fail (CLAPPER_IS_PLAYER (self));
+
+ _set_adaptive_bitrate (self, &self->start_bitrate,
+ "start-bitrate", bitrate, param_specs[PROP_ADAPTIVE_START_BITRATE]);
+}
+
+/**
+ * clapper_player_get_adaptive_start_bitrate:
+ * @player: a #ClapperPlayer
+ *
+ * Get currently set initial bitrate (bits/s) for adaptive streaming.
+ *
+ * Returns: the start bitrate value.
+ *
+ * Since: 0.8
+ */
+guint
+clapper_player_get_adaptive_start_bitrate (ClapperPlayer *self)
+{
+ guint bitrate;
+
+ g_return_val_if_fail (CLAPPER_IS_PLAYER (self), 0);
+
+ GST_OBJECT_LOCK (self);
+ bitrate = self->start_bitrate;
+ GST_OBJECT_UNLOCK (self);
+
+ return bitrate;
+}
+
+/**
+ * clapper_player_set_adaptive_min_bitrate:
+ * @player: a #ClapperPlayer
+ * @bitrate: a bitrate to set (bits/s)
+ *
+ * Set minimal bitrate to select for adaptive streaming
+ * such as DASH or HLS.
+ *
+ * Since: 0.8
+ */
+void
+clapper_player_set_adaptive_min_bitrate (ClapperPlayer *self, guint bitrate)
+{
+ g_return_if_fail (CLAPPER_IS_PLAYER (self));
+
+ _set_adaptive_bitrate (self, &self->min_bitrate,
+ "min-bitrate", bitrate, param_specs[PROP_ADAPTIVE_MIN_BITRATE]);
+}
+
+/**
+ * clapper_player_get_adaptive_min_bitrate:
+ * @player: a #ClapperPlayer
+ *
+ * Get currently set minimal bitrate (bits/s) for adaptive streaming.
+ *
+ * Returns: the minimal bitrate value.
+ *
+ * Since: 0.8
+ */
+guint
+clapper_player_get_adaptive_min_bitrate (ClapperPlayer *self)
+{
+ guint bitrate;
+
+ g_return_val_if_fail (CLAPPER_IS_PLAYER (self), 0);
+
+ GST_OBJECT_LOCK (self);
+ bitrate = self->min_bitrate;
+ GST_OBJECT_UNLOCK (self);
+
+ return bitrate;
+}
+
+/**
+ * clapper_player_set_adaptive_max_bitrate:
+ * @player: a #ClapperPlayer
+ * @bitrate: a bitrate to set (bits/s)
+ *
+ * Set maximal bitrate to select for adaptive streaming
+ * such as DASH or HLS.
+ *
+ * Since: 0.8
+ */
+void
+clapper_player_set_adaptive_max_bitrate (ClapperPlayer *self, guint bitrate)
+{
+ g_return_if_fail (CLAPPER_IS_PLAYER (self));
+
+ _set_adaptive_bitrate (self, &self->max_bitrate,
+ "max-bitrate", bitrate, param_specs[PROP_ADAPTIVE_MAX_BITRATE]);
+}
+
+/**
+ * clapper_player_get_adaptive_max_bitrate:
+ * @player: a #ClapperPlayer
+ *
+ * Get currently set maximal bitrate (bits/s) for adaptive streaming.
+ *
+ * Returns: the maximal bitrate value.
+ *
+ * Since: 0.8
+ */
+guint
+clapper_player_get_adaptive_max_bitrate (ClapperPlayer *self)
+{
+ guint bitrate;
+
+ g_return_val_if_fail (CLAPPER_IS_PLAYER (self), 0);
+
+ GST_OBJECT_LOCK (self);
+ bitrate = self->max_bitrate;
+ GST_OBJECT_UNLOCK (self);
+
+ return bitrate;
+}
+
+/**
+ * clapper_player_get_adaptive_bandwidth:
+ * @player: a #ClapperPlayer
+ *
+ * Get last fragment download bandwidth (bits/s) during
+ * adaptive streaming.
+ *
+ * Returns: the adaptive bandwidth.
+ *
+ * Since: 0.8
+ */
+guint
+clapper_player_get_adaptive_bandwidth (ClapperPlayer *self)
+{
+ guint bandwidth;
+
+ g_return_val_if_fail (CLAPPER_IS_PLAYER (self), 0);
+
+ GST_OBJECT_LOCK (self);
+ bandwidth = self->bandwidth;
+ GST_OBJECT_UNLOCK (self);
+
+ return bandwidth;
+}
+
/**
* clapper_player_set_audio_offset:
* @player: a #ClapperPlayer
@@ -1942,7 +2199,7 @@ clapper_player_thread_start (ClapperThreadedObject *threaded_object)
if (!(env = g_getenv ("CLAPPER_USE_PLAYBIN3"))) // Clapper override
env = g_getenv ("GST_CLAPPER_USE_PLAYBIN3"); // compat
- self->use_playbin3 = (env && g_str_has_prefix (env, "1"));
+ self->use_playbin3 = (!env || g_str_has_prefix (env, "1"));
playbin_str = (self->use_playbin3) ? "playbin3" : "playbin";
if (!(self->playbin = gst_element_factory_make (playbin_str, NULL))) {
@@ -2031,6 +2288,7 @@ clapper_player_init (ClapperPlayer *self)
self->audio_enabled = DEFAULT_AUDIO_ENABLED;
self->subtitles_enabled = DEFAULT_SUBTITLES_ENABLED;
self->download_enabled = DEFAULT_DOWNLOAD_ENABLED;
+ self->start_bitrate = DEFAULT_ADAPTIVE_START_BITRATE;
}
static void
@@ -2164,6 +2422,18 @@ clapper_player_get_property (GObject *object, guint prop_id,
case PROP_DOWNLOAD_ENABLED:
g_value_set_boolean (value, clapper_player_get_download_enabled (self));
break;
+ case PROP_ADAPTIVE_START_BITRATE:
+ g_value_set_uint (value, clapper_player_get_adaptive_start_bitrate (self));
+ break;
+ case PROP_ADAPTIVE_MIN_BITRATE:
+ g_value_set_uint (value, clapper_player_get_adaptive_min_bitrate (self));
+ break;
+ case PROP_ADAPTIVE_MAX_BITRATE:
+ g_value_set_uint (value, clapper_player_get_adaptive_max_bitrate (self));
+ break;
+ case PROP_ADAPTIVE_BANDWIDTH:
+ g_value_set_uint (value, clapper_player_get_adaptive_bandwidth (self));
+ break;
case PROP_AUDIO_OFFSET:
g_value_set_double (value, clapper_player_get_audio_offset (self));
break;
@@ -2225,6 +2495,15 @@ clapper_player_set_property (GObject *object, guint prop_id,
case PROP_DOWNLOAD_ENABLED:
clapper_player_set_download_enabled (self, g_value_get_boolean (value));
break;
+ case PROP_ADAPTIVE_START_BITRATE:
+ clapper_player_set_adaptive_start_bitrate (self, g_value_get_uint (value));
+ break;
+ case PROP_ADAPTIVE_MIN_BITRATE:
+ clapper_player_set_adaptive_min_bitrate (self, g_value_get_uint (value));
+ break;
+ case PROP_ADAPTIVE_MAX_BITRATE:
+ clapper_player_set_adaptive_max_bitrate (self, g_value_get_uint (value));
+ break;
case PROP_AUDIO_OFFSET:
clapper_player_set_audio_offset (self, g_value_get_double (value));
break;
@@ -2476,6 +2755,72 @@ clapper_player_class_init (ClapperPlayerClass *klass)
NULL, NULL, DEFAULT_DOWNLOAD_ENABLED,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+ /**
+ * ClapperPlayer:adaptive-start-bitrate:
+ *
+ * An initial bitrate (bits/s) to select during
+ * starting adaptive streaming such as DASH or HLS.
+ *
+ * If value is higher than lowest available bitrate in streaming
+ * manifest, then lowest possible bitrate will be selected.
+ *
+ * Since: 0.8
+ */
+ param_specs[PROP_ADAPTIVE_START_BITRATE] = g_param_spec_uint ("adaptive-start-bitrate",
+ NULL, NULL, 0, G_MAXUINT, DEFAULT_ADAPTIVE_START_BITRATE,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * ClapperPlayer:adaptive-min-bitrate:
+ *
+ * A minimal allowed bitrate (bits/s) during adaptive streaming
+ * such as DASH or HLS.
+ *
+ * Setting this will prevent streaming from entering lower qualities
+ * (even when connection speed cannot keep up). When set together with
+ * [property@Clapper.Player:adaptive-max-bitrate] it can be used to
+ * enforce some specific quality.
+ *
+ * Since: 0.8
+ */
+ param_specs[PROP_ADAPTIVE_MIN_BITRATE] = g_param_spec_uint ("adaptive-min-bitrate",
+ NULL, NULL, 0, G_MAXUINT, 0,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * ClapperPlayer:adaptive-max-bitrate:
+ *
+ * A maximal allowed bitrate (bits/s) during adaptive streaming
+ * such as DASH or HLS (`0` for unlimited).
+ *
+ * Setting this will prevent streaming from entering qualities with
+ * higher bandwidth than the one set. When set together with
+ * [property@Clapper.Player:adaptive-min-bitrate] it can be used to
+ * enforce some specific quality.
+ *
+ * Since: 0.8
+ */
+ param_specs[PROP_ADAPTIVE_MAX_BITRATE] = g_param_spec_uint ("adaptive-max-bitrate",
+ NULL, NULL, 0, G_MAXUINT, 0,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * ClapperPlayer:adaptive-bandwidth:
+ *
+ * Last fragment download bandwidth (bits/s) during adaptive streaming.
+ *
+ * This property only changes when adaptive streaming and later stays
+ * at the last value until streaming some adaptive content again.
+ *
+ * Apps can use this to determine and set an optimal value for
+ * [property@Clapper.Player:adaptive-start-bitrate].
+ *
+ * Since: 0.8
+ */
+ param_specs[PROP_ADAPTIVE_BANDWIDTH] = g_param_spec_uint ("adaptive-bandwidth",
+ NULL, NULL, 0, G_MAXUINT, 0,
+ G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
/**
* ClapperPlayer:audio-offset:
*
diff --git a/src/lib/clapper/clapper-player.h b/src/lib/clapper/clapper-player.h
index 1c14c453..c47b1a78 100644
--- a/src/lib/clapper/clapper-player.h
+++ b/src/lib/clapper/clapper-player.h
@@ -147,6 +147,27 @@ void clapper_player_set_download_enabled (ClapperPlayer *player, gboolean enable
CLAPPER_API
gboolean clapper_player_get_download_enabled (ClapperPlayer *player);
+CLAPPER_API
+void clapper_player_set_adaptive_start_bitrate (ClapperPlayer *player, guint bitrate);
+
+CLAPPER_API
+guint clapper_player_get_adaptive_start_bitrate (ClapperPlayer *player);
+
+CLAPPER_API
+void clapper_player_set_adaptive_min_bitrate (ClapperPlayer *player, guint bitrate);
+
+CLAPPER_API
+guint clapper_player_get_adaptive_min_bitrate (ClapperPlayer *player);
+
+CLAPPER_API
+void clapper_player_set_adaptive_max_bitrate (ClapperPlayer *player, guint bitrate);
+
+CLAPPER_API
+guint clapper_player_get_adaptive_max_bitrate (ClapperPlayer *player);
+
+CLAPPER_API
+guint clapper_player_get_adaptive_bandwidth (ClapperPlayer *player);
+
CLAPPER_API
void clapper_player_set_audio_offset (ClapperPlayer *player, gdouble offset);