mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-18 14:26:43 +00:00
hlsdemux2: Implement preload hint parsing
Load EXT-X-PRELOAD-HINT into a preload_hints array in the media playlist Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3883>
This commit is contained in:
parent
3ed6a23a4d
commit
3c50f54310
2 changed files with 146 additions and 0 deletions
|
@ -60,6 +60,9 @@ gst_hls_media_playlist_unref (GstHLSMediaPlaylist * self)
|
||||||
|
|
||||||
g_ptr_array_free (self->segments, TRUE);
|
g_ptr_array_free (self->segments, TRUE);
|
||||||
|
|
||||||
|
if (self->preload_hints != NULL)
|
||||||
|
g_ptr_array_free (self->preload_hints, TRUE);
|
||||||
|
|
||||||
g_free (self->last_data);
|
g_free (self->last_data);
|
||||||
g_mutex_clear (&self->lock);
|
g_mutex_clear (&self->lock);
|
||||||
g_free (self);
|
g_free (self);
|
||||||
|
@ -138,6 +141,26 @@ gst_m3u8_partial_segment_unref (GstM3U8PartialSegment * part)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GstM3U8PreloadHint *
|
||||||
|
gst_m3u8_preload_hint_ref (GstM3U8PreloadHint * hint)
|
||||||
|
{
|
||||||
|
g_assert (hint != NULL && hint->ref_count > 0);
|
||||||
|
|
||||||
|
g_atomic_int_add (&hint->ref_count, 1);
|
||||||
|
return hint;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_m3u8_preload_hint_unref (GstM3U8PreloadHint * hint)
|
||||||
|
{
|
||||||
|
g_return_if_fail (hint != NULL && hint->ref_count > 0);
|
||||||
|
|
||||||
|
if (g_atomic_int_dec_and_test (&hint->ref_count)) {
|
||||||
|
g_free (hint->uri);
|
||||||
|
g_free (hint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static GstM3U8InitFile *
|
static GstM3U8InitFile *
|
||||||
gst_m3u8_init_file_new (gchar * uri, gint64 size, gint64 offset)
|
gst_m3u8_init_file_new (gchar * uri, gint64 size, gint64 offset)
|
||||||
{
|
{
|
||||||
|
@ -474,6 +497,28 @@ gst_hls_media_playlist_dump (GstHLSMediaPlaylist * self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (self->preload_hints) {
|
||||||
|
GST_DEBUG ("Preload Hints: %d", self->preload_hints->len);
|
||||||
|
for (idx = 0; idx < self->preload_hints->len; idx++) {
|
||||||
|
GstM3U8PreloadHint *hint = g_ptr_array_index (self->preload_hints, idx);
|
||||||
|
const gchar *hint_type_str;
|
||||||
|
switch (hint->hint_type) {
|
||||||
|
case M3U8_PRELOAD_HINT_MAP:
|
||||||
|
hint_type_str = "MAP";
|
||||||
|
break;
|
||||||
|
case M3U8_PRELOAD_HINT_PART:
|
||||||
|
hint_type_str = "PART";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_DEBUG (" preload hint %u: type %s", idx, hint_type_str);
|
||||||
|
GST_DEBUG (" uri : %s %" G_GUINT64_FORMAT " %"
|
||||||
|
G_GINT64_FORMAT, hint->uri, hint->offset, hint->size);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -596,6 +641,62 @@ malformed_line:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstM3U8PreloadHint *
|
||||||
|
gst_m3u8_parse_preload_hint (gchar * data, const gchar * base_uri)
|
||||||
|
{
|
||||||
|
gchar *v, *a;
|
||||||
|
GstM3U8PreloadHint *hint = g_new0 (GstM3U8PreloadHint, 1);
|
||||||
|
gboolean have_hint_type = FALSE;
|
||||||
|
|
||||||
|
hint->ref_count = 1;
|
||||||
|
hint->size = -1;
|
||||||
|
|
||||||
|
while (data != NULL && parse_attributes (&data, &a, &v)) {
|
||||||
|
if (strcmp (a, "TYPE") == 0) {
|
||||||
|
if (g_ascii_strcasecmp (v, "MAP") == 0) {
|
||||||
|
hint->hint_type = M3U8_PRELOAD_HINT_MAP;
|
||||||
|
} else if (g_ascii_strcasecmp (v, "PART") == 0) {
|
||||||
|
hint->hint_type = M3U8_PRELOAD_HINT_PART;
|
||||||
|
} else {
|
||||||
|
GST_WARNING ("Unknown Preload Hint type %s", v);
|
||||||
|
goto malformed_line;
|
||||||
|
}
|
||||||
|
have_hint_type = TRUE;
|
||||||
|
} else if (strcmp (a, "URI") == 0) {
|
||||||
|
g_free (hint->uri);
|
||||||
|
hint->uri = uri_join (base_uri, v);
|
||||||
|
} else if (strcmp (a, "BYTERANGE-START") == 0) {
|
||||||
|
if (int64_from_string (v, NULL, &hint->offset)) {
|
||||||
|
goto malformed_line;
|
||||||
|
}
|
||||||
|
} else if (strcmp (a, "BYTERANGE-LENGTH") == 0) {
|
||||||
|
if (int64_from_string (v, NULL, &hint->size)) {
|
||||||
|
goto malformed_line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hint->uri == NULL || !have_hint_type) {
|
||||||
|
goto required_attributes_missing;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hint;
|
||||||
|
|
||||||
|
required_attributes_missing:
|
||||||
|
{
|
||||||
|
GST_WARNING
|
||||||
|
("EXT-X-PRELOAD-HINT is missing required URI or TYPE attributes");
|
||||||
|
gst_m3u8_preload_hint_unref (hint);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
malformed_line:
|
||||||
|
{
|
||||||
|
GST_WARNING ("Invalid EXT-X-PRELOAD-HINT entry in playlist");
|
||||||
|
gst_m3u8_preload_hint_unref (hint);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
parse_server_control (GstHLSMediaPlaylist * self, gchar * data)
|
parse_server_control (GstHLSMediaPlaylist * self, gchar * data)
|
||||||
{
|
{
|
||||||
|
@ -960,6 +1061,20 @@ gst_hls_media_playlist_parse (gchar * data, const gchar * uri,
|
||||||
} else if (g_str_has_prefix (data_ext_x, "SERVER-CONTROL:")) {
|
} else if (g_str_has_prefix (data_ext_x, "SERVER-CONTROL:")) {
|
||||||
data += strlen ("#EXT-X-SERVER-CONTROL:");
|
data += strlen ("#EXT-X-SERVER-CONTROL:");
|
||||||
parse_server_control (self, data);
|
parse_server_control (self, data);
|
||||||
|
} else if (g_str_has_prefix (data_ext_x, "PRELOAD-HINT:")) {
|
||||||
|
GstM3U8PreloadHint *hint = NULL;
|
||||||
|
|
||||||
|
hint =
|
||||||
|
gst_m3u8_parse_preload_hint (data + strlen ("#EXT-X-PRELOAD-HINT:"),
|
||||||
|
self->base_uri ? self->base_uri : self->uri);
|
||||||
|
if (hint == NULL)
|
||||||
|
goto next_line;
|
||||||
|
|
||||||
|
if (self->preload_hints == NULL) {
|
||||||
|
self->preload_hints = g_ptr_array_new_full (1,
|
||||||
|
(GDestroyNotify) gst_m3u8_preload_hint_unref);
|
||||||
|
}
|
||||||
|
g_ptr_array_add (self->preload_hints, hint);
|
||||||
} else {
|
} else {
|
||||||
GST_LOG ("Ignored line: %s", data);
|
GST_LOG ("Ignored line: %s", data);
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,8 @@ typedef struct _GstHLSTimeMap GstHLSTimeMap;
|
||||||
typedef struct _GstM3U8MediaSegment GstM3U8MediaSegment;
|
typedef struct _GstM3U8MediaSegment GstM3U8MediaSegment;
|
||||||
typedef struct _GstM3U8PartialSegment GstM3U8PartialSegment;
|
typedef struct _GstM3U8PartialSegment GstM3U8PartialSegment;
|
||||||
typedef struct _GstM3U8InitFile GstM3U8InitFile;
|
typedef struct _GstM3U8InitFile GstM3U8InitFile;
|
||||||
|
typedef enum _GstM3U8PreloadHintType GstM3U8PreloadHintType;
|
||||||
|
typedef struct _GstM3U8PreloadHint GstM3U8PreloadHint;
|
||||||
typedef struct _GstHLSRenditionStream GstHLSRenditionStream;
|
typedef struct _GstHLSRenditionStream GstHLSRenditionStream;
|
||||||
typedef struct _GstM3U8Client GstM3U8Client;
|
typedef struct _GstM3U8Client GstM3U8Client;
|
||||||
typedef struct _GstHLSVariantStream GstHLSVariantStream;
|
typedef struct _GstHLSVariantStream GstHLSVariantStream;
|
||||||
|
@ -105,6 +107,8 @@ struct _GstHLSMediaPlaylist
|
||||||
|
|
||||||
GPtrArray *segments; /* Array of GstM3U8MediaSegment */
|
GPtrArray *segments; /* Array of GstM3U8MediaSegment */
|
||||||
|
|
||||||
|
GPtrArray *preload_hints; /* Array of GstM3U8PreloadHint */
|
||||||
|
|
||||||
/* Generated information */
|
/* Generated information */
|
||||||
GstClockTime duration; /* The estimated total duration of all segments
|
GstClockTime duration; /* The estimated total duration of all segments
|
||||||
contained in this playlist */
|
contained in this playlist */
|
||||||
|
@ -164,6 +168,33 @@ gst_m3u8_partial_segment_ref (GstM3U8PartialSegment *part);
|
||||||
void
|
void
|
||||||
gst_m3u8_partial_segment_unref (GstM3U8PartialSegment *part);
|
gst_m3u8_partial_segment_unref (GstM3U8PartialSegment *part);
|
||||||
|
|
||||||
|
enum _GstM3U8PreloadHintType {
|
||||||
|
M3U8_PRELOAD_HINT_MAP,
|
||||||
|
M3U8_PRELOAD_HINT_PART,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstM3U8PreloadHint:
|
||||||
|
*
|
||||||
|
* Official term in RFC : "Preload Hint"
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct _GstM3U8PreloadHint
|
||||||
|
{
|
||||||
|
GstM3U8PreloadHintType hint_type;
|
||||||
|
|
||||||
|
gchar *uri;
|
||||||
|
gint64 offset, size;
|
||||||
|
|
||||||
|
gint ref_count; /* ATOMIC */
|
||||||
|
};
|
||||||
|
|
||||||
|
GstM3U8PreloadHint *
|
||||||
|
gst_m3u8_preload_hint_ref (GstM3U8PreloadHint *hint);
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_m3u8_preload_hint_unref (GstM3U8PreloadHint *hint);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstM3U8MediaSegment:
|
* GstM3U8MediaSegment:
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue