/* The goal here is to figure out, once we have pushed a keyframe downstream,
* what the next ideal keyframe to download is.
- *
+ *
* This is done based on:
* * the current internal position (i.e. actual_position)
* * the reported downstream position (QoS feedback)
}
#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
- bitrate = (base_demux->max_bandwidth > DEFAULT_ADAPTIVE_VARIANT)?
- (guint64)(base_demux->max_bandwidth):(bitrate);
+ if (base_demux->max_bandwidth > DEFAULT_BANDWIDTH_LIMIT)
+ bitrate = (guint64)base_demux->max_bandwidth;
GST_DEBUG_OBJECT (stream->pad,
"Trying to change to bitrate under : %" G_GUINT64_FORMAT, bitrate);
/* get representation index with current max_bandwidth */
- if (GST_ADAPTIVE_DEMUX_IN_TRICKMODE_KEY_UNITS (base_demux) ||
+ if (GST_ADAPTIVE_DEMUX_IN_TRICKMODE_KEY_UNITS (base_demux) ||
ABS (base_demux->segment.rate) <= 1.0) {
new_index =
gst_mpdparser_get_rep_idx_with_max_bandwidth (rep_list, bitrate,
/*
Parse an RFC5322 (section 3.3) date-time from the Date: field in the
- HTTP response.
+ HTTP response.
See https://tools.ietf.org/html/rfc5322#section-3.3
*/
static GstDateTime *
/* select the initial variant stream */
#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
- if ((demux->connection_speed > 0) ||
- (demux->max_bandwidth > DEFAULT_ADAPTIVE_VARIANT) ||
- (demux->max_width > DEFAULT_ADAPTIVE_VARIANT) ||
- (demux->max_height > DEFAULT_ADAPTIVE_VARIANT)) {
- variant =
- gst_hls_master_playlist_get_variant_for_max_limit (hlsdemux->master,
- NULL, demux->connection_speed,
- demux->max_bandwidth, demux->max_width, demux->max_height);
- } else {
+ variant =
+ gst_hls_master_playlist_get_variant_for_bandwitdh_limit (hlsdemux->master,
+ NULL, demux->connection_speed, demux->start_bandwidth,
+ demux->min_bandwidth, demux->max_bandwidth, demux->max_width, demux->max_height);
+
+ if (!variant)
variant = hlsdemux->master->default_variant;
+
+ if (variant) {
+ GST_INFO_OBJECT (hlsdemux, "selected %s, %d, %d x %d",
+ variant->name, variant->bandwidth, variant->width, variant->height);
+ gst_hls_demux_set_current_variant (hlsdemux, variant);
}
#else
if (demux->connection_speed == 0) {
gst_hls_master_playlist_get_variant_for_bitrate (hlsdemux->master,
NULL, demux->connection_speed);
}
-#endif
if (variant) {
GST_INFO_OBJECT (hlsdemux, "selected %s", variant->name);
gst_hls_demux_set_current_variant (hlsdemux, variant); // FIXME: inline?
}
+#endif
/* get the selected media playlist (unless the inital list was one already) */
if (!hlsdemux->master->is_simple) {
previous_variant = demux->current_variant;
#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
new_variant =
- gst_hls_master_playlist_get_variant_for_max_limit (demux->master,
- demux->current_variant, max_bitrate,
- adaptive_demux->max_bandwidth, adaptive_demux->max_width, adaptive_demux->max_height);
+ gst_hls_master_playlist_get_variant_for_bandwitdh_limit (demux->master,
+ demux->current_variant, max_bitrate, NULL, adaptive_demux->min_bandwidth,
+ adaptive_demux->max_bandwidth, adaptive_demux->max_width, adaptive_demux->max_height);
+
+ GST_INFO_OBJECT (demux, "new_variant : %d, %d x %d",
+ new_variant->bandwidth, new_variant->width, new_variant->height);
#else
new_variant =
gst_hls_master_playlist_get_variant_for_bitrate (demux->master,
#define GST_CAT_DEFAULT hls_debug
#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
-#define DEFAULT_ADAPTIVE_VARIANT -1
+#define DEFAULT_RESOLUTION_LIMIT -1
+#define DEFAULT_BANDWIDTH_LIMIT -1
#endif
static GstM3U8MediaFile *gst_m3u8_media_file_new (gchar * uri,
}
}
if (m3u8->current_file) {
- /* Store duration of the fragment we're using to update the position
+ /* Store duration of the fragment we're using to update the position
* the next time we advance */
m3u8->current_file_duration =
GST_M3U8_MEDIA_FILE (m3u8->current_file->data)->duration;
if (!variant || !variant->codecs)
return 0;
- codec_list = g_strsplit(variant->codecs, ",", MAX_NUM_OF_CODEC);
+ codec_list = g_strsplit (variant->codecs, ",", MAX_NUM_OF_CODEC);
if (codec_list) {
- cnt = g_strv_length(codec_list);
- g_strfreev(codec_list);
+ cnt = g_strv_length (codec_list);
+ g_strfreev (codec_list);
}
return cnt;
if (!variant)
return FALSE;
- num_of_codec = get_num_of_codec(variant);
+ num_of_codec = get_num_of_codec (variant);
if (num_of_codec > 0 && req_num > 0 && num_of_codec != req_num) {
- GST_WARNING("can not support to change codec");
+ GST_WARNING ("can not support to change codec");
return FALSE;
}
return TRUE;
}
+static gint
+update_max_limit(gint min_limit, gint max_limit, gint start_limit, gint bitrate)
+{
+ if (start_limit > DEFAULT_BANDWIDTH_LIMIT && start_limit >= min_limit &&
+ (start_limit <= max_limit || max_limit == DEFAULT_BANDWIDTH_LIMIT)) {
+ GST_DEBUG ("set max to start : %d ", start_limit);
+ return start_limit;
+ }
+
+ if (bitrate > 0 && bitrate >= min_limit &&
+ (bitrate <= max_limit || max_limit == DEFAULT_BANDWIDTH_LIMIT)) {
+ GST_DEBUG ("set max to bitrate : %d ", bitrate);
+ return bitrate;
+ }
+
+ if (bitrate == 0 || bitrate < min_limit) {
+ GST_DEBUG ("set max to min : %d", min_limit);
+ return min_limit;
+ }
+
+ return max_limit;
+}
+
GstHLSVariantStream *
-gst_hls_master_playlist_get_variant_for_max_limit (GstHLSMasterPlaylist *
- playlist, GstHLSVariantStream * current_variant, guint bitrate, gint bandwidth, gint width, gint height)
+get_average_variant(GList *variants, guint num_of_codec, gint min_limit, gint max_limit)
+{
+ GList *l = NULL;
+ GList *valid_list = NULL;
+ gint cnt = 0;
+ guint num_of_valid_variant = 0;
+ GstHLSVariantStream *tmp = NULL;
+
+ for (l = g_list_first (variants); l; l = g_list_next (l)) {
+ if (!check_num_of_codec ((GstHLSVariantStream *)l->data, num_of_codec))
+ continue;
+
+ tmp = l->data;
+
+ if (max_limit != DEFAULT_BANDWIDTH_LIMIT && tmp->bandwidth > max_limit) {
+ GST_DEBUG ("over max limit");
+ break;
+ }
+
+ if (min_limit != DEFAULT_BANDWIDTH_LIMIT && tmp->bandwidth < min_limit) {
+ GST_DEBUG ("skip to next");
+ continue;
+ }
+
+ num_of_valid_variant++;
+ valid_list = l;
+ }
+
+ GST_DEBUG ("num of valid variant %d / %d", num_of_valid_variant, g_list_length (variants));
+
+ for (; valid_list; valid_list = g_list_previous (valid_list)) {
+ if (!check_num_of_codec ((GstHLSVariantStream *)valid_list->data, num_of_codec))
+ continue;
+
+ tmp = valid_list->data;
+ if (num_of_valid_variant/2 == cnt) {
+ GST_DEBUG ("get this stream %d", tmp->bandwidth);
+ return tmp;
+ }
+ cnt++;
+ }
+ return NULL;
+}
+
+GstHLSVariantStream *
+gst_hls_master_playlist_get_variant_for_bandwitdh_limit (GstHLSMasterPlaylist * playlist,
+ GstHLSVariantStream * current_variant, guint bitrate, gchar * start_bandwidth,
+ gint min_bandwidth, gint max_bandwidth, gint width, gint height)
{
GstHLSVariantStream *tmp = current_variant;
GstHLSVariantStream *variant = NULL;
- GList *l;
- guint max_bandwidth = (bandwidth > DEFAULT_ADAPTIVE_VARIANT)?(guint)(bandwidth):(bitrate);
+ GstHLSVariantStream *min_variant = NULL; // lowest
+ GstHLSVariantStream *max_variant = NULL; // highest
+ GList *variants = NULL;
+ GList *l = NULL;
+ gint max_limit = DEFAULT_BANDWIDTH_LIMIT;
+ gint min_limit = DEFAULT_BANDWIDTH_LIMIT;
+ gint start_limit = DEFAULT_BANDWIDTH_LIMIT;
+ gint adj_max_limit = DEFAULT_BANDWIDTH_LIMIT;
+ guint num_of_valid_variant = 0;
guint num_of_codec = 0;
- num_of_codec = get_num_of_codec(current_variant);
+ num_of_codec = get_num_of_codec (current_variant);
- GST_INFO("max limit : %u, %d, [w]%d [h]%d", bitrate, bandwidth, width, height);
+ GST_DEBUG ("bitrate: %u, bandwidth: %s, %d ~ %d, resolution: %d X %d",
+ bitrate, start_bandwidth, min_bandwidth, max_bandwidth, width, height);
- /* variant lists are sorted low to high, so iterate from highest to lowest */
+ /* get variant list */
if (current_variant == NULL || !current_variant->iframe)
- l = g_list_last (playlist->variants); /* highest */
+ variants = playlist->variants;
else
- l = g_list_last (playlist->iframe_variants);
+ variants = playlist->iframe_variants;
+
+ if (!variants) {
+ GST_ERROR ("invalid playlist");
+ return current_variant;
+ }
+
+ /* get valid min/max variant */
+ for (l = g_list_first (variants); l; l = g_list_next (l)) {
+ if (!check_num_of_codec ((GstHLSVariantStream *)l->data, num_of_codec))
+ continue;
+ tmp = l->data;
+ num_of_valid_variant++;
+
+ if (!min_variant) {
+ min_variant = tmp;
+ }
+ }
+ max_variant = tmp;
+
+ GST_DEBUG("num of valid variant %d / %d", num_of_valid_variant, g_list_length (variants));
+ if (num_of_valid_variant <= 1)
+ return tmp;
+
+ /* get valid range limit */
+ if (max_bandwidth == DEFAULT_BANDWIDTH_LIMIT || min_bandwidth <= max_bandwidth) {
+ if (min_variant->bandwidth <= max_bandwidth)
+ max_limit = adj_max_limit = max_bandwidth;
+
+ if (max_variant->bandwidth >= min_bandwidth)
+ min_limit = min_bandwidth;
+ }
+
+ GST_DEBUG ("range limit: %d ~ %d", min_limit, max_limit);
+
+ if (start_bandwidth) {
+ if (!g_strcmp0 (start_bandwidth, "LOWEST")) {
+ if (min_limit == DEFAULT_BANDWIDTH_LIMIT)
+ return min_variant;
+ adj_max_limit = min_limit;
+ } else if (!g_strcmp0 (start_bandwidth, "HIGHEST")) {
+ if (max_limit == DEFAULT_BANDWIDTH_LIMIT)
+ return max_variant;
+ } else if (!g_strcmp0 (start_bandwidth, "AVERAGE")) {
+ variant = get_average_variant (variants, num_of_codec, min_limit, max_limit);
+ if (variant)
+ return variant;
+ } else {
+ start_limit = atoi (start_bandwidth);
+ /* update max limit based on the start_bandwidth or network bitrate */
+ adj_max_limit = update_max_limit (min_limit, max_limit, start_limit, bitrate);
+ }
+ } else {
+ /* update max limit based on the network bitrate */
+ adj_max_limit = update_max_limit (min_limit, max_limit, DEFAULT_BANDWIDTH_LIMIT, bitrate);
+ }
+
+ if (min_limit < 0 && adj_max_limit < 0 && width < 0 && height < 0) {
+ GST_WARNING ("invalid condition, get default variant");
+ return NULL;
+ }
+
+ GST_DEBUG ("adj range limit: %d ~ %d (origin: %d)", min_limit, adj_max_limit, max_limit);
- for (; l; l = g_list_previous(l)) {
- if (!check_num_of_codec((GstHLSVariantStream *)l->data, num_of_codec))
+ /* variant lists are sorted low to high, so iterate from highest to lowest */
+ tmp = NULL;
+ for (l = g_list_last (variants); l; l = g_list_previous (l)) {
+ if (!check_num_of_codec ((GstHLSVariantStream *)l->data, num_of_codec))
continue;
tmp = l->data;
+ GST_DEBUG ("stream info: %d, %d x %d", tmp->bandwidth, tmp->width, tmp->height);
+
+ if (tmp->bandwidth < min_limit) {
+ GList *j = g_list_next(l);
+ if (variant)
+ break;
+
+ if (j &&
+ ((max_limit == DEFAULT_BANDWIDTH_LIMIT) ||
+ ((GstHLSVariantStream*)j->data)->bandwidth <= max_limit))
+ variant = j->data; /* get the lowest one in the valid range */
+ else
+ variant = tmp;
+ break;
+ }
- if (tmp->bandwidth > max_bandwidth)
+ if (adj_max_limit > DEFAULT_BANDWIDTH_LIMIT && adj_max_limit < tmp->bandwidth)
continue;
- if (((width > DEFAULT_ADAPTIVE_VARIANT) && (tmp->width > width)) ||
- ((height > DEFAULT_ADAPTIVE_VARIANT) && (tmp->height > height))) {
- if (!variant) /* will be kept with the last one with the same bitrate */
+ if (((width > DEFAULT_RESOLUTION_LIMIT) && (tmp->width > width)) ||
+ ((height > DEFAULT_RESOLUTION_LIMIT) && (tmp->height > height))) {
+ if (adj_max_limit > DEFAULT_BANDWIDTH_LIMIT && !variant) { /* will be kept with the first one with the same bitrate */
variant = tmp;
+ }
} else {
variant = tmp;
- GST_INFO("found %d, %d x %d", variant->bandwidth, variant->width, variant->height);
+ GST_DEBUG ("get this stream %d", variant->bandwidth);
break;
}
}
GstHLSMasterPlaylist * gst_hls_master_playlist_new_from_data (gchar * data,
const gchar * base_uri);
#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
-GstHLSVariantStream * gst_hls_master_playlist_get_variant_for_max_limit (GstHLSMasterPlaylist *playlist,
+GstHLSVariantStream * gst_hls_master_playlist_get_variant_for_bandwitdh_limit (GstHLSMasterPlaylist * playlist,
GstHLSVariantStream * current_variant,
- guint bitrate, gint bandwidth,
- gint width, gint height);
+ guint bitrate, gchar * start_bandwidth, gint min_bandwidth,
+ gint max_bandwidth, gint width, gint height);
#else
GstHLSVariantStream * gst_hls_master_playlist_get_variant_for_bitrate (GstHLSMasterPlaylist * playlist,
GstHLSVariantStream * current_variant,
PROP_CONNECTION_SPEED,
PROP_BITRATE_LIMIT,
#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+ PROP_START_BANDWIDTH,
+ PROP_MIN_BANDWIDTH,
PROP_MAX_BANDWIDTH,
PROP_MAX_WIDTH,
PROP_MAX_HEIGHT,
demux->bitrate_limit = g_value_get_float (value);
break;
#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+ case PROP_START_BANDWIDTH:
+ g_free(demux->start_bandwidth);
+ demux->start_bandwidth = g_strdup (g_value_get_string (value));
+ break;
+ case PROP_MIN_BANDWIDTH:
+ demux->min_bandwidth = g_value_get_int (value);
+ break;
case PROP_MAX_BANDWIDTH:
demux->max_bandwidth = g_value_get_int (value);
break;
g_value_set_float (value, demux->bitrate_limit);
break;
#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+ case PROP_START_BANDWIDTH:
+ if (demux->start_bandwidth == NULL)
+ g_value_set_static_string (value, "");
+ else
+ g_value_set_string (value, demux->start_bandwidth);
+ break;
+ case PROP_MIN_BANDWIDTH:
+ g_value_set_int (value, demux->min_bandwidth);
+ break;
case PROP_MAX_BANDWIDTH:
g_value_set_int (value, demux->max_bandwidth);
break;
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+ g_object_class_install_property (gobject_class, PROP_START_BANDWIDTH,
+ g_param_spec_string ("start-bandwidth", "Start Bandwidth",
+ "Set bandwidth to use when the playback is started. (LOWEST, HIGHEST, AVERAGE or specific bandwidth value)",
+ NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class, PROP_MIN_BANDWIDTH,
+ g_param_spec_int ("min-bandwidth",
+ "Min Bandwidth limit",
+ "Minimum limit of the available bandwidth to use when switching to alternates. (-1 = no limit)",
+ -1, G_MAXINT, DEFAULT_BANDWIDTH_LIMIT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
g_object_class_install_property (gobject_class, PROP_MAX_BANDWIDTH,
g_param_spec_int ("max-bandwidth",
"Max Bandwidth limit",
- "Limit of the available bandwidth to use when switching to alternates. (-1 = no limit)",
- -1, G_MAXINT, DEFAULT_ADAPTIVE_VARIANT,
+ "Maximum limit of the available bandwidth to use when switching to alternates. (-1 = no limit)",
+ -1, G_MAXINT, DEFAULT_BANDWIDTH_LIMIT,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_MAX_WIDTH,
g_param_spec_int ("max-video-width",
"Max video width limit",
- "Limit of the available video width to use when switching to alternates. (-1 = no limit)",
- -1, G_MAXINT, DEFAULT_ADAPTIVE_VARIANT,
+ "Maximum limit of the available video width to use when switching to alternates. (-1 = no limit)",
+ -1, G_MAXINT, DEFAULT_RESOLUTION_LIMIT,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_MAX_HEIGHT,
g_param_spec_int ("max-video-height",
"Max video height limit",
- "Limit of the available video height to use when switching to alternates. (-1 = no limit)",
- -1, G_MAXINT, DEFAULT_ADAPTIVE_VARIANT,
+ "Maximum limit of the available video height to use when switching to alternates. (-1 = no limit)",
+ -1, G_MAXINT, DEFAULT_RESOLUTION_LIMIT,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
#endif
demux->bitrate_limit = DEFAULT_BITRATE_LIMIT;
demux->connection_speed = DEFAULT_CONNECTION_SPEED;
#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
- demux->max_bandwidth = DEFAULT_ADAPTIVE_VARIANT;
- demux->max_width = DEFAULT_ADAPTIVE_VARIANT;
- demux->max_height = DEFAULT_ADAPTIVE_VARIANT;
+ demux->start_bandwidth = NULL;
+ demux->min_bandwidth = DEFAULT_BANDWIDTH_LIMIT;
+ demux->max_bandwidth = DEFAULT_BANDWIDTH_LIMIT;
+ demux->max_width = DEFAULT_RESOLUTION_LIMIT;
+ demux->max_height = DEFAULT_RESOLUTION_LIMIT;
#endif
gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
#define DEFAULT_ADAPTIVE_TIMEOUT -1
#define PLAYLIST_ADAPTIVE_RETRY 3
#define PLAYLIST_ADAPTIVE_TIMEOUT 2
-#define DEFAULT_ADAPTIVE_VARIANT -1
+#define DEFAULT_BANDWIDTH_LIMIT -1
+#define DEFAULT_RESOLUTION_LIMIT -1
#endif
typedef struct _GstAdaptiveDemuxStreamFragment GstAdaptiveDemuxStreamFragment;
/* < private > */
GstAdaptiveDemuxPrivate *priv;
#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+ gchar *start_bandwidth;
+ gint min_bandwidth;
gint max_bandwidth;
gint max_width;
gint max_height;
Name: gst-plugins-bad
Version: 1.16.2
-Release: 6
+Release: 7
Summary: GStreamer Streaming-Media Framework Plug-Ins
License: LGPL-2.0+
Group: Multimedia/Framework