gstreamer/subprojects/gst-plugins-good/ext/adaptivedemux2/hls/m3u8.h
Edward Hervey 33db765f45 adaptivedemux2: Improve minimum buffering threshold
Previously the minimum buffering threshold was hardcoded to a specific
value (10s). This is suboptimal this an actual value will depend on the actual
stream being played.

This commit sets the low watermark threshold in time to 0, which is an automatic
mode. Subclasses can provide a stream `recommended_buffering_threshold` when
update_stream_info() is called.

Currently implemented for HLS, where we recommended 1.5 average segment
duration. This will result in buffering being at 100% when the 2nd segment has
been downloaded (minus a bit already being consumed downstream)

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3240>
2022-10-31 16:16:50 +01:00

399 lines
13 KiB
C

/* GStreamer
* Copyright (C) 2010 Marc-Andre Lureau <marcandre.lureau@gmail.com>
* Copyright (C) 2010 Andoni Morales Alastruey <ylatuya@gmail.com>
* Copyright (C) 2015 Tim-Philipp Müller <tim@centricular.com>
*
* Copyright (C) 2021-2022 Centricular Ltd
* Author: Edward Hervey <edward@centricular.com>
* Author: Jan Schmidt <jan@centricular.com>
*
* m3u8.h:
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __M3U8_H__
#define __M3U8_H__
#include <gst/gst.h>
G_BEGIN_DECLS
typedef struct _GstHLSMediaPlaylist GstHLSMediaPlaylist;
typedef struct _GstHLSTimeMap GstHLSTimeMap;
typedef struct _GstM3U8MediaSegment GstM3U8MediaSegment;
typedef struct _GstM3U8InitFile GstM3U8InitFile;
typedef struct _GstHLSRenditionStream GstHLSRenditionStream;
typedef struct _GstM3U8Client GstM3U8Client;
typedef struct _GstHLSVariantStream GstHLSVariantStream;
typedef struct _GstHLSMasterPlaylist GstHLSMasterPlaylist;
#define GST_HLS_MEDIA_PLAYLIST(m) ((GstHLSMediaPlaylist*)m)
#define GST_M3U8_MEDIA_SEGMENT(f) ((GstM3U8MediaSegment*)f)
#define GST_HLS_MEDIA_PLAYLIST_LOCK(m) g_mutex_lock (&m->lock);
#define GST_HLS_MEDIA_PLAYLIST_UNLOCK(m) g_mutex_unlock (&m->lock);
#define GST_HLS_MEDIA_PLAYLIST_IS_LIVE(m) ((m)->endlist == FALSE)
/* hlsdemux must not get closer to the end of a live stream than
GST_M3U8_LIVE_MIN_FRAGMENT_DISTANCE fragments. Section 6.3.3
"Playing the Playlist file" of the HLS draft states that this
value is three fragments */
#define GST_M3U8_LIVE_MIN_FRAGMENT_DISTANCE 3
typedef enum {
GST_HLS_PLAYLIST_TYPE_UNDEFINED,
GST_HLS_PLAYLIST_TYPE_EVENT,
GST_HLS_PLAYLIST_TYPE_VOD,
} GstHLSPlaylistType;
/**
* GstHLSMediaPlaylist:
*
* Official term in RFC : "Media Playlist". A List of Media Segments.
*
* It can be used by either a variant stream (GstHLSVariantStream) or an
* alternate rendition (GstHLSMedia).
*
* Note: Was called `GstM3u8` in legacy elements
*/
struct _GstHLSMediaPlaylist
{
gchar *uri; /* actually downloaded URI */
gchar *base_uri; /* URI to use as base for resolving relative URIs.
* This will be different to uri in case of redirects */
/* Base Tag */
gint version; /* EXT-X-VERSION (default 1) */
/* Media Playlist Tags */
GstClockTime targetduration; /* EXT-X-TARGETDURATION, default GST_CLOCK_TIME_NONE */
gint64 media_sequence; /* EXT-X-MEDIA-SEQUENCE, MSN of the first Media
Segment in the playlist. */
gint64 discont_sequence; /* EXT-X-DISCONTINUITY-SEQUENCE. Default : 0 */
gboolean has_ext_x_dsn; /* EXT-X-DISCONTINUITY-SEQUENCE present and specified */
gboolean endlist; /* EXT-X-ENDLIST present */
GstHLSPlaylistType type; /* EXT-X-PLAYLIST-TYPE. Default:
GST_HLS_PLAYLIST_TYE_UNDEFINED */
gboolean i_frame; /* EXT-X-I-FRAMES-ONLY present. */
gboolean allowcache; /* deprecated EXT-X-ALLOW-CACHE */
/* Overview of contained media segments */
gboolean ext_x_key_present; /* a valid EXT-X-KEY is present on at least one
media segment */
gboolean ext_x_pdt_present; /* a valid EXT-X-PROGRAM-DATE-TIME is present on
at least one media segment */
GPtrArray *segments; /* Array of GstM3U8MediaSegment */
/* Generated information */
GstClockTime duration; /* The estimated total duration of all segments
contained in this playlist */
gboolean reloaded; /* If TRUE, this indicates that this playlist
* was reloaded but had identical content */
/*< private > */
GMutex lock;
/* Copy of the incoming data that created this media playlist.
* See gst_hls_media_playlist_has_same_data() */
gchar *last_data;
gint ref_count; /* ATOMIC */
};
/* gst_hls_media_playlist_new: Internal function : Do not use from demuxer code, only for unit
* testing purposes */
GstHLSMediaPlaylist * gst_hls_media_playlist_new (const gchar * uri,
const gchar * base_uri);
GstHLSMediaPlaylist * gst_hls_media_playlist_ref (GstHLSMediaPlaylist * m3u8);
void gst_hls_media_playlist_unref (GstHLSMediaPlaylist * m3u8);
/**
* GstM3U8MediaSegment:
*
* Official term in RFC : "Media Segment"
*
* Note : Naming in legacy elements was GstM3U8MediaFile
*/
struct _GstM3U8MediaSegment
{
gchar *title;
GstClockTimeDiff stream_time; /* Computed stream time */
GstClockTime duration;
gchar *uri;
gint64 sequence; /* the sequence number of this segment */
gint64 discont_sequence; /* The Discontinuity Sequence Number of this segment */
gboolean discont; /* this file marks a discontinuity */
gchar *key;
guint8 iv[16];
gint64 offset, size;
gint ref_count; /* ATOMIC */
GstM3U8InitFile *init_file; /* Media Initialization (hold ref) */
GDateTime *datetime; /* EXT-X-PROGRAM-DATE-TIME */
};
struct _GstM3U8InitFile
{
gchar *uri;
gint64 offset, size;
guint ref_count; /* ATOMIC */
};
GstM3U8MediaSegment *
gst_m3u8_media_segment_ref (GstM3U8MediaSegment * mfile);
void
gst_m3u8_media_segment_unref (GstM3U8MediaSegment * mfile);
gboolean
gst_hls_media_playlist_has_same_data (GstHLSMediaPlaylist * m3u8,
gchar * playlist_data);
GstHLSMediaPlaylist *
gst_hls_media_playlist_parse (gchar * data,
const gchar * uri,
const gchar * base_uri);
void
gst_hls_media_playlist_recalculate_stream_time (GstHLSMediaPlaylist *playlist,
GstM3U8MediaSegment *anchor);
GstM3U8MediaSegment *
gst_hls_media_playlist_sync_to_segment (GstHLSMediaPlaylist * m3u8,
GstM3U8MediaSegment * segment);
gboolean
gst_hls_media_playlist_sync_to_playlist (GstHLSMediaPlaylist * m3u8,
GstHLSMediaPlaylist * reference);
gboolean
gst_hls_media_playlist_has_next_fragment (GstHLSMediaPlaylist * m3u8,
GstM3U8MediaSegment * current,
gboolean forward);
GstM3U8MediaSegment *
gst_hls_media_playlist_advance_fragment (GstHLSMediaPlaylist * m3u8,
GstM3U8MediaSegment * current,
gboolean forward);
GstM3U8MediaSegment *
gst_hls_media_playlist_get_starting_segment (GstHLSMediaPlaylist *self);
GstClockTime
gst_hls_media_playlist_get_duration (GstHLSMediaPlaylist * m3u8);
gchar *
gst_hls_media_playlist_get_uri (GstHLSMediaPlaylist * m3u8);
gboolean
gst_hls_media_playlist_is_live (GstHLSMediaPlaylist * m3u8);
gboolean
gst_hls_media_playlist_get_seek_range (GstHLSMediaPlaylist * m3u8,
gint64 * start,
gint64 * stop);
gboolean
gst_hls_media_playlist_has_lost_sync (GstHLSMediaPlaylist * m3u8,
GstClockTime position);
GstM3U8MediaSegment *
gst_hls_media_playlist_seek (GstHLSMediaPlaylist *playlist,
gboolean forward,
GstSeekFlags flags,
GstClockTimeDiff ts);
void
gst_hls_media_playlist_dump (GstHLSMediaPlaylist* self);
GstClockTime
gst_hls_media_playlist_recommended_buffering_threshold (GstHLSMediaPlaylist *playlist);
typedef enum
{
GST_HLS_RENDITION_STREAM_TYPE_INVALID = -1,
GST_HLS_RENDITION_STREAM_TYPE_AUDIO,
GST_HLS_RENDITION_STREAM_TYPE_VIDEO,
GST_HLS_RENDITION_STREAM_TYPE_SUBTITLES,
GST_HLS_RENDITION_STREAM_TYPE_CLOSED_CAPTIONS,
GST_HLS_N_MEDIA_TYPES
} GstHLSRenditionStreamType;
/**
* GstHLSRenditionStream:
*
* Official term in RFC : "Renditions are alternate versions of the content,
* such as audio produced in different languages or video recorded from
* different camera angles."
*
* Note: Was named GstHLSMedia in legacy elements
*/
struct _GstHLSRenditionStream {
GstHLSRenditionStreamType mtype;
gchar *group_id;
gchar *name;
gchar *lang;
gchar *uri;
GstCaps *caps;
gboolean is_default;
gboolean autoselect;
gboolean forced;
gint ref_count; /* ATOMIC */
};
GstHLSRenditionStream *
gst_hls_rendition_stream_ref (GstHLSRenditionStream * media);
void
gst_hls_rendition_stream_unref (GstHLSRenditionStream * media);
const gchar *
gst_hls_rendition_stream_type_get_name (GstHLSRenditionStreamType mtype);
/**
* GstHLSVariantStream:
*
* Official term in RFC :
* """
* A Master Playlist provides a set of Variant Streams, each of which describes
* a different version of the same content.
*
* A Variant Stream includes a Media Playlist that specifies media encoded at a
* particular bit rate, in a particular format, and at a particular resolution
* for media containing video.
* """
*/
struct _GstHLSVariantStream {
gchar *name; /* This will be the "name" of the playlist, the original
* relative/absolute uri in a variant playlist */
gchar *uri;
gchar *codecs;
GstCaps *caps;
GstStreamType codecs_stream_type; /* As defined by codecs */
gint bandwidth; /* bits per second */
gint program_id;
gint width;
gint height;
gboolean iframe;
gint refcount; /* ATOMIC */
/* alternative renditions (names) */
gchar *media_groups[GST_HLS_N_MEDIA_TYPES];
/* List of gchar* fallback uri */
GList *fallback;
};
/* Notes: #define are to avoid symbol clashes with legacy hlsdemux */
#define gst_hls_variant_stream_ref hls_variant_stream_ref
GstHLSVariantStream * hls_variant_stream_ref (GstHLSVariantStream * stream);
#define gst_hls_variant_stream_unref hls_variant_stream_unref
void hls_variant_stream_unref (GstHLSVariantStream * stream);
/**
* GstHLSMasterPlaylist:
*
* Official term in RFC : "A Playlist is either a Media Playlist or a Master
* Playlist."
*
* This is the top-level object, constructed by a manifest provided by external
* means.
*/
struct _GstHLSMasterPlaylist
{
/* Available variant streams, sorted by bitrate (low -> high) */
GList *variants; /* GstHLSVariantStream */
GList *iframe_variants; /* GstHLSVariantStream */
/* Default variant, first in the list (originally, before sorting) */
GstHLSVariantStream *default_variant;
/* Full list of Available Alternative Rendition (GstHLSRenditionStream) */
GList *renditions;
/* EXT-X-VERSION. 0 if unspecified */
gint version;
/* TRUE if this playlist is a simple media playlist (and not a master
* playlist). Implies that there is only a single variant and no alternate
* rendition groups */
gboolean is_simple;
/* TRUE if all variants have codecs specified */
gboolean have_codecs;
/*< private > */
gchar *last_data; /* Copy of the incoming data that created this master playlist */
gint refcount; /* ATOMIC */
};
/* Notes: #define are to avoid symbol clashes with legacy hlsdemux */
#define gst_hls_master_playlist_new_from_data hls_master_playlist_new_from_data
GstHLSMasterPlaylist * hls_master_playlist_new_from_data (gchar * data,
const gchar * base_uri);
#define gst_hls_master_playlist_get_variant_for_bitrate hls_master_playlist_get_variant_for_bitrate
GstHLSVariantStream * hls_master_playlist_get_variant_for_bitrate (GstHLSMasterPlaylist * playlist,
GstHLSVariantStream * current_variant,
guint bitrate,
guint min_bitrate);
#define gst_hls_master_playlist_get_common_caps hls_master_playlist_get_common_caps
GstCaps * hls_master_playlist_get_common_caps (GstHLSMasterPlaylist *playlist);
#define gst_hls_master_playlist_unref hls_master_playlist_unref
void hls_master_playlist_unref (GstHLSMasterPlaylist * playlist);
/* Time Mapping
*
* Used to map GStreamer times to internal segment timestamps
*/
struct _GstHLSTimeMap {
/* DISCONT SEQUENCE NUMBER */
gint64 dsn;
/* The stream time (used for gst timestamps, gst segments, seeking ...) */
GstClockTime stream_time;
/* The optional Program Date Time reference */
GDateTime *pdt;
/* The internal time (ex: mpeg-ts PTS) */
GstClockTime internal_time;
};
GstStreamType gst_stream_type_from_hls_type (GstHLSRenditionStreamType stype);
GstStreamType gst_hls_get_stream_type_from_structure (GstStructure *structure);
GstStreamType gst_hls_get_stream_type_from_caps (GstCaps *caps);
G_END_DECLS
#endif /* __M3U8_H__ */