mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 06:54:49 +00:00
mssmanifest: Keep the stream qualities list sorted by bitrate
This will help making adaptive streaming chose the best rate for a particular connection speed
This commit is contained in:
parent
013c11f7dd
commit
eec8164d9c
1 changed files with 57 additions and 12 deletions
|
@ -52,6 +52,14 @@ typedef struct _GstMssStreamFragment
|
||||||
guint64 duration;
|
guint64 duration;
|
||||||
} GstMssStreamFragment;
|
} GstMssStreamFragment;
|
||||||
|
|
||||||
|
typedef struct _GstMssStreamQuality
|
||||||
|
{
|
||||||
|
xmlNodePtr xmlnode;
|
||||||
|
|
||||||
|
gchar *bitrate_str;
|
||||||
|
guint64 bitrate;
|
||||||
|
} GstMssStreamQuality;
|
||||||
|
|
||||||
struct _GstMssStream
|
struct _GstMssStream
|
||||||
{
|
{
|
||||||
xmlNodePtr xmlnode;
|
xmlNodePtr xmlnode;
|
||||||
|
@ -85,6 +93,38 @@ node_has_type (xmlNodePtr node, const gchar * name)
|
||||||
return strcmp ((gchar *) node->name, name) == 0;
|
return strcmp ((gchar *) node->name, name) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstMssStreamQuality *
|
||||||
|
gst_mss_stream_quality_new (xmlNodePtr node)
|
||||||
|
{
|
||||||
|
GstMssStreamQuality *q = g_slice_new (GstMssStreamQuality);
|
||||||
|
|
||||||
|
q->xmlnode = node;
|
||||||
|
q->bitrate_str = (gchar *) xmlGetProp (node, (xmlChar *) MSS_PROP_BITRATE);
|
||||||
|
q->bitrate = strtoull (q->bitrate_str, NULL, 10);
|
||||||
|
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_mss_stream_quality_free (GstMssStreamQuality * quality)
|
||||||
|
{
|
||||||
|
g_return_if_fail (quality != NULL);
|
||||||
|
|
||||||
|
g_free (quality->bitrate_str);
|
||||||
|
g_slice_free (GstMssStreamQuality, quality);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gint
|
||||||
|
compare_bitrate (GstMssStreamQuality * a, GstMssStreamQuality * b)
|
||||||
|
{
|
||||||
|
if (a->bitrate > b->bitrate)
|
||||||
|
return 1;
|
||||||
|
if (a->bitrate < b->bitrate)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_gst_mss_stream_init (GstMssStream * stream, xmlNodePtr node)
|
_gst_mss_stream_init (GstMssStream * stream, xmlNodePtr node)
|
||||||
{
|
{
|
||||||
|
@ -145,14 +185,18 @@ _gst_mss_stream_init (GstMssStream * stream, xmlNodePtr node)
|
||||||
stream->fragments = g_list_prepend (stream->fragments, fragment);
|
stream->fragments = g_list_prepend (stream->fragments, fragment);
|
||||||
|
|
||||||
} else if (node_has_type (iter, MSS_NODE_STREAM_QUALITY)) {
|
} else if (node_has_type (iter, MSS_NODE_STREAM_QUALITY)) {
|
||||||
stream->qualities = g_list_prepend (stream->qualities, iter);
|
GstMssStreamQuality *quality = gst_mss_stream_quality_new (iter);
|
||||||
|
stream->qualities = g_list_prepend (stream->qualities, quality);
|
||||||
} else {
|
} else {
|
||||||
/* TODO gst log this */
|
/* TODO gst log this */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stream->fragments = g_list_reverse (stream->fragments);
|
stream->fragments = g_list_reverse (stream->fragments);
|
||||||
stream->qualities = g_list_reverse (stream->qualities);
|
|
||||||
|
/* order them from smaller to bigger based on bitrates */
|
||||||
|
stream->qualities =
|
||||||
|
g_list_sort (stream->qualities, (GCompareFunc) compare_bitrate);
|
||||||
|
|
||||||
stream->current_fragment = stream->fragments;
|
stream->current_fragment = stream->fragments;
|
||||||
stream->current_quality = stream->qualities;
|
stream->current_quality = stream->qualities;
|
||||||
|
@ -191,7 +235,8 @@ static void
|
||||||
gst_mss_stream_free (GstMssStream * stream)
|
gst_mss_stream_free (GstMssStream * stream)
|
||||||
{
|
{
|
||||||
g_list_free_full (stream->fragments, g_free);
|
g_list_free_full (stream->fragments, g_free);
|
||||||
g_list_free (stream->qualities);
|
g_list_free_full (stream->qualities,
|
||||||
|
(GDestroyNotify) gst_mss_stream_quality_free);
|
||||||
g_free (stream->url);
|
g_free (stream->url);
|
||||||
g_regex_unref (stream->regex_position);
|
g_regex_unref (stream->regex_position);
|
||||||
g_regex_unref (stream->regex_bitrate);
|
g_regex_unref (stream->regex_bitrate);
|
||||||
|
@ -538,13 +583,17 @@ GstCaps *
|
||||||
gst_mss_stream_get_caps (GstMssStream * stream)
|
gst_mss_stream_get_caps (GstMssStream * stream)
|
||||||
{
|
{
|
||||||
GstMssStreamType streamtype = gst_mss_stream_get_type (stream);
|
GstMssStreamType streamtype = gst_mss_stream_get_type (stream);
|
||||||
xmlNodePtr qualitylevel = stream->current_quality->data;
|
GstMssStreamQuality *qualitylevel = stream->current_quality->data;
|
||||||
GstCaps *caps = NULL;
|
GstCaps *caps = NULL;
|
||||||
|
|
||||||
if (streamtype == MSS_STREAM_TYPE_VIDEO)
|
if (streamtype == MSS_STREAM_TYPE_VIDEO)
|
||||||
caps = _gst_mss_stream_video_caps_from_qualitylevel_xml (qualitylevel);
|
caps =
|
||||||
|
_gst_mss_stream_video_caps_from_qualitylevel_xml
|
||||||
|
(qualitylevel->xmlnode);
|
||||||
else if (streamtype == MSS_STREAM_TYPE_AUDIO)
|
else if (streamtype == MSS_STREAM_TYPE_AUDIO)
|
||||||
caps = _gst_mss_stream_audio_caps_from_qualitylevel_xml (qualitylevel);
|
caps =
|
||||||
|
_gst_mss_stream_audio_caps_from_qualitylevel_xml
|
||||||
|
(qualitylevel->xmlnode);
|
||||||
|
|
||||||
return caps;
|
return caps;
|
||||||
}
|
}
|
||||||
|
@ -553,28 +602,24 @@ GstFlowReturn
|
||||||
gst_mss_stream_get_fragment_url (GstMssStream * stream, gchar ** url)
|
gst_mss_stream_get_fragment_url (GstMssStream * stream, gchar ** url)
|
||||||
{
|
{
|
||||||
gchar *tmp;
|
gchar *tmp;
|
||||||
gchar *bitrate_str;
|
|
||||||
gchar *start_time_str;
|
gchar *start_time_str;
|
||||||
GstMssStreamFragment *fragment;
|
GstMssStreamFragment *fragment;
|
||||||
|
GstMssStreamQuality *quality = stream->current_quality->data;
|
||||||
|
|
||||||
if (stream->current_fragment == NULL) /* stream is over */
|
if (stream->current_fragment == NULL) /* stream is over */
|
||||||
return GST_FLOW_UNEXPECTED;
|
return GST_FLOW_UNEXPECTED;
|
||||||
|
|
||||||
fragment = stream->current_fragment->data;
|
fragment = stream->current_fragment->data;
|
||||||
|
|
||||||
bitrate_str =
|
|
||||||
(gchar *) xmlGetProp (stream->current_quality->data,
|
|
||||||
(xmlChar *) MSS_PROP_BITRATE);
|
|
||||||
start_time_str = g_strdup_printf ("%" G_GUINT64_FORMAT, fragment->time);
|
start_time_str = g_strdup_printf ("%" G_GUINT64_FORMAT, fragment->time);
|
||||||
|
|
||||||
tmp = g_regex_replace_literal (stream->regex_bitrate, stream->url,
|
tmp = g_regex_replace_literal (stream->regex_bitrate, stream->url,
|
||||||
strlen (stream->url), 0, bitrate_str, 0, NULL);
|
strlen (stream->url), 0, quality->bitrate_str, 0, NULL);
|
||||||
*url = g_regex_replace_literal (stream->regex_position, tmp,
|
*url = g_regex_replace_literal (stream->regex_position, tmp,
|
||||||
strlen (tmp), 0, start_time_str, 0, NULL);
|
strlen (tmp), 0, start_time_str, 0, NULL);
|
||||||
|
|
||||||
g_free (tmp);
|
g_free (tmp);
|
||||||
g_free (start_time_str);
|
g_free (start_time_str);
|
||||||
g_free (bitrate_str);
|
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue