mirror of
https://github.com/Rafostar/clapper.git
synced 2025-08-31 00:11:59 +02:00
clapper: Ability to request adaptive bitrates
Add APIs to allow apps to select start, min and max bitrates for adaptive streaming. Combining min+max values can allow to implement a video quality selector, although possible bitrates/qualities are not communicated with an app yet.
This commit is contained in:
@@ -87,6 +87,9 @@ struct _ClapperPlayer
|
|||||||
gboolean pending_eos; // when pausing due to EOS
|
gboolean pending_eos; // when pausing due to EOS
|
||||||
gint eos; // atomic integer
|
gint eos; // atomic integer
|
||||||
|
|
||||||
|
/* Set adaptive props immediately */
|
||||||
|
GstElement *adaptive_demuxer;
|
||||||
|
|
||||||
/* Playbin2 compat */
|
/* Playbin2 compat */
|
||||||
gint n_video, n_audio, n_text;
|
gint n_video, n_audio, n_text;
|
||||||
|
|
||||||
@@ -104,6 +107,9 @@ struct _ClapperPlayer
|
|||||||
gboolean subtitles_enabled;
|
gboolean subtitles_enabled;
|
||||||
gchar *download_dir;
|
gchar *download_dir;
|
||||||
gboolean download_enabled;
|
gboolean download_enabled;
|
||||||
|
guint start_bitrate;
|
||||||
|
guint min_bitrate;
|
||||||
|
guint max_bitrate;
|
||||||
gdouble audio_offset;
|
gdouble audio_offset;
|
||||||
gdouble subtitle_offset;
|
gdouble subtitle_offset;
|
||||||
};
|
};
|
||||||
|
@@ -62,6 +62,7 @@
|
|||||||
#define DEFAULT_AUDIO_ENABLED TRUE
|
#define DEFAULT_AUDIO_ENABLED TRUE
|
||||||
#define DEFAULT_SUBTITLES_ENABLED TRUE
|
#define DEFAULT_SUBTITLES_ENABLED TRUE
|
||||||
#define DEFAULT_DOWNLOAD_ENABLED FALSE
|
#define DEFAULT_DOWNLOAD_ENABLED FALSE
|
||||||
|
#define DEFAULT_ADAPTIVE_START_BITRATE 1600000
|
||||||
|
|
||||||
#define GST_CAT_DEFAULT clapper_player_debug
|
#define GST_CAT_DEFAULT clapper_player_debug
|
||||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||||
@@ -93,6 +94,9 @@ enum
|
|||||||
PROP_SUBTITLES_ENABLED,
|
PROP_SUBTITLES_ENABLED,
|
||||||
PROP_DOWNLOAD_DIR,
|
PROP_DOWNLOAD_DIR,
|
||||||
PROP_DOWNLOAD_ENABLED,
|
PROP_DOWNLOAD_ENABLED,
|
||||||
|
PROP_ADAPTIVE_START_BITRATE,
|
||||||
|
PROP_ADAPTIVE_MIN_BITRATE,
|
||||||
|
PROP_ADAPTIVE_MAX_BITRATE,
|
||||||
PROP_AUDIO_OFFSET,
|
PROP_AUDIO_OFFSET,
|
||||||
PROP_SUBTITLE_OFFSET,
|
PROP_SUBTITLE_OFFSET,
|
||||||
PROP_SUBTITLE_FONT_DESC,
|
PROP_SUBTITLE_FONT_DESC,
|
||||||
@@ -727,6 +731,8 @@ clapper_player_reset (ClapperPlayer *self, gboolean pending_dispose)
|
|||||||
gst_clear_object (&self->audio_decoder);
|
gst_clear_object (&self->audio_decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gst_clear_object (&self->adaptive_demuxer);
|
||||||
|
|
||||||
GST_OBJECT_UNLOCK (self);
|
GST_OBJECT_UNLOCK (self);
|
||||||
|
|
||||||
gst_clear_tag_list (&self->pending_tags);
|
gst_clear_tag_list (&self->pending_tags);
|
||||||
@@ -768,13 +774,15 @@ static void
|
|||||||
_element_setup_cb (GstElement *playbin, GstElement *element, ClapperPlayer *self)
|
_element_setup_cb (GstElement *playbin, GstElement *element, ClapperPlayer *self)
|
||||||
{
|
{
|
||||||
GstElementFactory *factory = gst_element_get_factory (element);
|
GstElementFactory *factory = gst_element_get_factory (element);
|
||||||
|
const gchar *factory_name;
|
||||||
|
|
||||||
if (G_UNLIKELY (factory == NULL))
|
if (G_UNLIKELY (factory == NULL))
|
||||||
return;
|
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;
|
gchar *download_template;
|
||||||
|
|
||||||
/* Only set props if we have download template */
|
/* Only set props if we have download template */
|
||||||
@@ -785,6 +793,27 @@ _element_setup_cb (GstElement *playbin, GstElement *element, ClapperPlayer *self
|
|||||||
NULL);
|
NULL);
|
||||||
g_free (download_template);
|
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;
|
||||||
|
|
||||||
|
gst_object_replace ((GstObject **) &self->adaptive_demuxer, GST_OBJECT_CAST (element));
|
||||||
|
|
||||||
|
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 +1697,168 @@ clapper_player_get_download_enabled (ClapperPlayer *self)
|
|||||||
return enabled;
|
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_set_audio_offset:
|
* clapper_player_set_audio_offset:
|
||||||
* @player: a #ClapperPlayer
|
* @player: a #ClapperPlayer
|
||||||
@@ -2031,6 +2222,7 @@ clapper_player_init (ClapperPlayer *self)
|
|||||||
self->audio_enabled = DEFAULT_AUDIO_ENABLED;
|
self->audio_enabled = DEFAULT_AUDIO_ENABLED;
|
||||||
self->subtitles_enabled = DEFAULT_SUBTITLES_ENABLED;
|
self->subtitles_enabled = DEFAULT_SUBTITLES_ENABLED;
|
||||||
self->download_enabled = DEFAULT_DOWNLOAD_ENABLED;
|
self->download_enabled = DEFAULT_DOWNLOAD_ENABLED;
|
||||||
|
self->start_bitrate = DEFAULT_ADAPTIVE_START_BITRATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -2164,6 +2356,15 @@ clapper_player_get_property (GObject *object, guint prop_id,
|
|||||||
case PROP_DOWNLOAD_ENABLED:
|
case PROP_DOWNLOAD_ENABLED:
|
||||||
g_value_set_boolean (value, clapper_player_get_download_enabled (self));
|
g_value_set_boolean (value, clapper_player_get_download_enabled (self));
|
||||||
break;
|
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_AUDIO_OFFSET:
|
case PROP_AUDIO_OFFSET:
|
||||||
g_value_set_double (value, clapper_player_get_audio_offset (self));
|
g_value_set_double (value, clapper_player_get_audio_offset (self));
|
||||||
break;
|
break;
|
||||||
@@ -2225,6 +2426,15 @@ clapper_player_set_property (GObject *object, guint prop_id,
|
|||||||
case PROP_DOWNLOAD_ENABLED:
|
case PROP_DOWNLOAD_ENABLED:
|
||||||
clapper_player_set_download_enabled (self, g_value_get_boolean (value));
|
clapper_player_set_download_enabled (self, g_value_get_boolean (value));
|
||||||
break;
|
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:
|
case PROP_AUDIO_OFFSET:
|
||||||
clapper_player_set_audio_offset (self, g_value_get_double (value));
|
clapper_player_set_audio_offset (self, g_value_get_double (value));
|
||||||
break;
|
break;
|
||||||
@@ -2476,6 +2686,55 @@ clapper_player_class_init (ClapperPlayerClass *klass)
|
|||||||
NULL, NULL, DEFAULT_DOWNLOAD_ENABLED,
|
NULL, NULL, DEFAULT_DOWNLOAD_ENABLED,
|
||||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
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:audio-offset:
|
* ClapperPlayer:audio-offset:
|
||||||
*
|
*
|
||||||
|
@@ -147,6 +147,24 @@ void clapper_player_set_download_enabled (ClapperPlayer *player, gboolean enable
|
|||||||
CLAPPER_API
|
CLAPPER_API
|
||||||
gboolean clapper_player_get_download_enabled (ClapperPlayer *player);
|
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
|
CLAPPER_API
|
||||||
void clapper_player_set_audio_offset (ClapperPlayer *player, gdouble offset);
|
void clapper_player_set_audio_offset (ClapperPlayer *player, gdouble offset);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user