1 /* GStreamer 2 * Copyright (C) 2010 Marc-Andre Lureau <marcandre.lureau@gmail.com> 3 * Copyright (C) 2010 Andoni Morales Alastruey <ylatuya@gmail.com> 4 * Copyright (C) 2015 Tim-Philipp Müller <tim@centricular.com> 5 * 6 * m3u8.h: 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Library General Public 10 * License as published by the Free Software Foundation; either 11 * version 2 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Library General Public License for more details. 17 * 18 * You should have received a copy of the GNU Library General Public 19 * License along with this library; if not, write to the 20 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 21 * Boston, MA 02110-1301, USA. 22 */ 23 24 #ifndef __M3U8_H__ 25 #define __M3U8_H__ 26 27 #include <glib.h> 28 29 G_BEGIN_DECLS 30 31 typedef struct _GstM3U8 GstM3U8; 32 typedef struct _GstM3U8MediaFile GstM3U8MediaFile; 33 typedef struct _GstHLSMedia GstHLSMedia; 34 typedef struct _GstM3U8Client GstM3U8Client; 35 typedef struct _GstHLSVariantStream GstHLSVariantStream; 36 typedef struct _GstHLSMasterPlaylist GstHLSMasterPlaylist; 37 38 #define GST_M3U8(m) ((GstM3U8*)m) 39 #define GST_M3U8_MEDIA_FILE(f) ((GstM3U8MediaFile*)f) 40 41 #define GST_M3U8_LOCK(m) g_mutex_lock (&m->lock); 42 #define GST_M3U8_UNLOCK(m) g_mutex_unlock (&m->lock); 43 44 #define GST_M3U8_IS_LIVE(m) ((m)->endlist == FALSE) 45 46 /* hlsdemux must not get closer to the end of a live stream than 47 GST_M3U8_LIVE_MIN_FRAGMENT_DISTANCE fragments. Section 6.3.3 48 "Playing the Playlist file" of the HLS draft states that this 49 value is three fragments */ 50 #define GST_M3U8_LIVE_MIN_FRAGMENT_DISTANCE 3 51 52 struct _GstM3U8 53 { 54 gchar *uri; /* actually downloaded URI */ 55 gchar *base_uri; /* URI to use as base for resolving relative URIs. 56 * This will be different to uri in case of redirects */ 57 gchar *name; /* This will be the "name" of the playlist, the original 58 * relative/absolute uri in a variant playlist */ 59 60 /* parsed info */ 61 gboolean endlist; /* if ENDLIST has been reached */ 62 gint version; /* last EXT-X-VERSION */ 63 GstClockTime targetduration; /* last EXT-X-TARGETDURATION */ 64 gboolean allowcache; /* last EXT-X-ALLOWCACHE */ 65 66 GList *files; 67 68 /* state */ 69 GList *current_file; 70 GstClockTime current_file_duration; /* Duration of current fragment */ 71 gint64 sequence; /* the next sequence for this client */ 72 GstClockTime sequence_position; /* position of this sequence */ 73 gint64 highest_sequence_number; /* largest seen sequence number */ 74 GstClockTime first_file_start; /* timecode of the start of the first fragment in the current media playlist */ 75 GstClockTime last_file_end; /* timecode of the end of the last fragment in the current media playlist */ 76 GstClockTime duration; /* cached total duration */ 77 gint discont_sequence; /* currently expected EXT-X-DISCONTINUITY-SEQUENCE */ 78 79 /*< private > */ 80 gchar *last_data; 81 GMutex lock; 82 83 gint ref_count; /* ATOMIC */ 84 }; 85 86 GstM3U8 * gst_m3u8_ref (GstM3U8 * m3u8); 87 88 void gst_m3u8_unref (GstM3U8 * m3u8); 89 90 91 struct _GstM3U8MediaFile 92 { 93 gchar *title; 94 GstClockTime duration; 95 gchar *uri; 96 gint64 sequence; /* the sequence nb of this file */ 97 gboolean discont; /* this file marks a discontinuity */ 98 gchar *key; 99 guint8 iv[16]; 100 gint64 offset, size; 101 gint ref_count; /* ATOMIC */ 102 }; 103 104 GstM3U8MediaFile * gst_m3u8_media_file_ref (GstM3U8MediaFile * mfile); 105 106 void gst_m3u8_media_file_unref (GstM3U8MediaFile * mfile); 107 108 GstM3U8 * gst_m3u8_new (void); 109 110 gboolean gst_m3u8_update (GstM3U8 * m3u8, 111 gchar * data); 112 113 void gst_m3u8_set_uri (GstM3U8 * m3u8, 114 const gchar * uri, 115 const gchar * base_uri, 116 const gchar * name); 117 118 GstM3U8MediaFile * gst_m3u8_get_next_fragment (GstM3U8 * m3u8, 119 gboolean forward, 120 GstClockTime * sequence_position, 121 gboolean * discont); 122 123 gboolean gst_m3u8_has_next_fragment (GstM3U8 * m3u8, 124 gboolean forward); 125 126 void gst_m3u8_advance_fragment (GstM3U8 * m3u8, 127 gboolean forward); 128 129 GstClockTime gst_m3u8_get_duration (GstM3U8 * m3u8); 130 131 GstClockTime gst_m3u8_get_target_duration (GstM3U8 * m3u8); 132 133 gchar * gst_m3u8_get_uri (GstM3U8 * m3u8); 134 135 gboolean gst_m3u8_is_live (GstM3U8 * m3u8); 136 137 gboolean gst_m3u8_get_seek_range (GstM3U8 * m3u8, 138 gint64 * start, 139 gint64 * stop); 140 141 typedef enum 142 { 143 GST_HLS_MEDIA_TYPE_INVALID = -1, 144 GST_HLS_MEDIA_TYPE_AUDIO, 145 GST_HLS_MEDIA_TYPE_VIDEO, 146 GST_HLS_MEDIA_TYPE_SUBTITLES, 147 GST_HLS_MEDIA_TYPE_CLOSED_CAPTIONS, 148 GST_HLS_N_MEDIA_TYPES 149 } GstHLSMediaType; 150 151 struct _GstHLSMedia { 152 GstHLSMediaType mtype; 153 gchar *group_id; 154 gchar *name; 155 gchar *lang; 156 gchar *uri; 157 gboolean is_default; 158 gboolean autoselect; 159 gboolean forced; 160 161 GstM3U8 *playlist; /* media playlist */ 162 163 gint ref_count; /* ATOMIC */ 164 }; 165 166 GstHLSMedia * gst_hls_media_ref (GstHLSMedia * media); 167 168 void gst_hls_media_unref (GstHLSMedia * media); 169 170 171 struct _GstHLSVariantStream { 172 gchar *name; /* This will be the "name" of the playlist, the original 173 * relative/absolute uri in a variant playlist */ 174 gchar *uri; 175 gchar *codecs; 176 gint bandwidth; 177 gint program_id; 178 gint width; 179 gint height; 180 gboolean iframe; 181 182 gint refcount; /* ATOMIC */ 183 184 GstM3U8 *m3u8; /* media playlist */ 185 186 /* alternative renditions */ 187 gchar *media_groups[GST_HLS_N_MEDIA_TYPES]; 188 GList *media[GST_HLS_N_MEDIA_TYPES]; 189 }; 190 191 GstHLSVariantStream * gst_hls_variant_stream_ref (GstHLSVariantStream * stream); 192 193 void gst_hls_variant_stream_unref (GstHLSVariantStream * stream); 194 195 gboolean gst_hls_variant_stream_is_live (GstHLSVariantStream * stream); 196 197 GstHLSMedia * gst_hls_variant_find_matching_media (GstHLSVariantStream * stream, 198 GstHLSMedia *media); 199 200 201 struct _GstHLSMasterPlaylist 202 { 203 /* Available variant streams, sorted by bitrate (low -> high) */ 204 GList *variants; 205 GList *iframe_variants; 206 207 GstHLSVariantStream *default_variant; /* first in the list */ 208 209 gint version; /* EXT-X-VERSION */ 210 211 gint refcount; /* ATOMIC */ 212 213 gboolean is_simple; /* TRUE if simple main media playlist, 214 * FALSE if variant playlist (either 215 * way the variants list will be set) */ 216 217 /*< private > */ 218 gchar *last_data; 219 }; 220 221 GstHLSMasterPlaylist * gst_hls_master_playlist_new_from_data (gchar * data, 222 const gchar * base_uri); 223 224 GstHLSVariantStream * gst_hls_master_playlist_get_variant_for_bitrate (GstHLSMasterPlaylist * playlist, 225 GstHLSVariantStream * current_variant, 226 guint bitrate); 227 GstHLSVariantStream * gst_hls_master_playlist_get_matching_variant (GstHLSMasterPlaylist * playlist, 228 GstHLSVariantStream * current_variant); 229 230 void gst_hls_master_playlist_unref (GstHLSMasterPlaylist * playlist); 231 232 G_END_DECLS 233 234 #endif /* __M3U8_H__ */ 235