mirror of
https://github.com/Rafostar/clapper.git
synced 2025-08-29 15:22:11 +02:00
Merge pull request #506 from Rafostar/adaptive
Add adaptive streaming bitrate control to Clapper API
This commit is contained in:
@@ -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'
|
||||
|
||||
|
@@ -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",
|
||||
|
99
pkgs/flatpak/testing/gstreamer_stable.json
Normal file
99
pkgs/flatpak/testing/gstreamer_stable.json
Normal file
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
@@ -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 },
|
||||
|
@@ -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);
|
||||
|
@@ -49,6 +49,10 @@
|
||||
<default>1.0</default>
|
||||
<summary>Stores last speed value to apply on startup</summary>
|
||||
</key>
|
||||
<key name="adaptive-start-bitrate" type="i">
|
||||
<default>1600000</default>
|
||||
<summary>Stores initial adaptive streaming bitrate to apply on startup</summary>
|
||||
</key>
|
||||
<key name="progression-mode" type="i">
|
||||
<default>1</default>
|
||||
<summary>Stores last queue progression mode used to apply on startup</summary>
|
||||
|
@@ -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;
|
||||
};
|
||||
|
@@ -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:
|
||||
*
|
||||
|
@@ -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);
|
||||
|
||||
|
Reference in New Issue
Block a user