3 * unit test for hlsdemux
5 * Copyright (C) <2012> Fluendo S.A <support@fluendo.com>
6 * Authors: Andoni Morales Alastruey <amorales@fluendo.com>
7 * Copyright (C) 2014 Sebastian Dröge <sebastian@centricular.com>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
25 #include <gst/check/gstcheck.h>
27 #undef GST_CAT_DEFAULT
31 GST_DEBUG_CATEGORY (hls_debug);
33 static const gchar *INVALID_PLAYLIST = "#EXTM3 UINVALID";
35 static const gchar *ON_DEMAND_PLAYLIST = "#EXTM3U \n\
36 #EXT-X-TARGETDURATION:10\n\
38 http://media.example.com/001.ts\n\
40 http://media.example.com/002.ts\n\
42 http://media.example.com/003.ts\n\
44 http://media.example.com/004.ts\n\
47 static const gchar *DOUBLES_PLAYLIST = "#EXTM3U \n\
48 #EXT-X-TARGETDURATION:10\n\
49 #EXTINF:10.321,Test\n\
50 http://media.example.com/001.ts\n\
51 #EXTINF:9.6789,Test\n\
52 http://media.example.com/002.ts\n\
53 #EXTINF:10.2344,Test\n\
54 http://media.example.com/003.ts\n\
56 http://media.example.com/004.ts\n\
59 static const gchar *LIVE_PLAYLIST = "#EXTM3U\n\
60 #EXT-X-TARGETDURATION:8\n\
61 #EXT-X-MEDIA-SEQUENCE:2680\n\
64 https://priv.example.com/fileSequence2680.ts\n\
66 https://priv.example.com/fileSequence2681.ts\n\
68 https://priv.example.com/fileSequence2682.ts\n\
70 https://priv.example.com/fileSequence2683.ts";
72 static const gchar *LIVE_ROTATED_PLAYLIST = "#EXTM3U\n\
73 #EXT-X-TARGETDURATION:8\n\
74 #EXT-X-MEDIA-SEQUENCE:3001\n\
77 https://priv.example.com/fileSequence3001.ts\n\
79 https://priv.example.com/fileSequence3002.ts\n\
81 https://priv.example.com/fileSequence3003.ts\n\
83 https://priv.example.com/fileSequence3004.ts";
85 static const gchar *VARIANT_PLAYLIST = "#EXTM3U \n\
86 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=128000\n\
87 http://example.com/low.m3u8\n\
88 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=256000\n\
89 http://example.com/mid.m3u8\n\
90 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=768000\n\
91 http://example.com/hi.m3u8\n\
92 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=65000,CODECS=\"mp4a.40.5\"\n\
93 http://example.com/audio-only.m3u8";
95 static const gchar *VARIANT_PLAYLIST_WITH_URI_MISSING = "#EXTM3U \n\
96 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=128000\n\
97 http://example.com/low.m3u8\n\
98 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=256000\n\
100 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=768000\n\
101 http://example.com/hi.m3u8\n\
102 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=65000,CODECS=\"mp4a.40.5\"\n\
103 http://example.com/audio-only.m3u8";
105 static const gchar *EMPTY_LINES_VARIANT_PLAYLIST = "#EXTM3U \n\
106 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=128000\n\n\
107 http://example.com/low.m3u8\n\n\
108 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=256000\n\n\
109 http://example.com/mid.m3u8\n\n\
110 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=768000\n\n\
111 http://example.com/hi.m3u8\n\n\
112 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=65000,CODECS=\"mp4a.40.5\"\n\n\
113 http://example.com/audio-only.m3u8";
115 static const gchar *WINDOWS_EMPTY_LINES_VARIANT_PLAYLIST = "#EXTM3U \r\n\
116 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=128000\r\n\r\n\
117 http://example.com/low.m3u8\r\n\r\n\
118 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=256000\r\n\r\n\
119 http://example.com/mid.m3u8\r\n\r\n\
120 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=768000\r\n\r\n\
121 http://example.com/hi.m3u8\r\n\r\n\
122 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=65000,CODECS=\"mp4a.40.5\"\r\n\r\n\
123 http://example.com/audio-only.m3u8";
125 static const gchar *EMPTY_LINES_PLAYLIST = "#EXTM3U \n\n\
126 #EXT-X-TARGETDURATION:10\n\
127 #EXTINF:10,Testr\n\n\
128 http://media.example.com/001.ts\n\n\
130 http://media.example.com/002.ts\n\n\
132 http://media.example.com/003.ts\n\n\
134 http://media.example.com/004.ts\n\n\
137 static const gchar *WINDOWS_EMPTY_LINES_PLAYLIST = "#EXTM3U \r\n\
138 #EXT-X-TARGETDURATION:10\r\n\r\n\
139 #EXTINF:10,Test\r\n\r\n\
140 http://media.example.com/001.ts\r\n\r\n\
141 #EXTINF:10,Test\r\n\r\n\
142 http://media.example.com/002.ts\r\n\r\n\
143 #EXTINF:10,Test\r\n\r\n\
144 http://media.example.com/003.ts\r\n\r\n\
145 #EXTINF:10,Test\r\n\r\n\
146 http://media.example.com/004.ts\r\n\r\n\
149 static const gchar *BYTE_RANGES_PLAYLIST = "#EXTM3U \n\
150 #EXT-X-TARGETDURATION:40\n\
152 #EXT-X-BYTERANGE:1000@100\n\
153 http://media.example.com/all.ts\n\
155 #EXT-X-BYTERANGE:1000@1000\n\
156 http://media.example.com/all.ts\n\
158 #EXT-X-BYTERANGE:1000@2000\n\
159 http://media.example.com/all.ts\n\
161 #EXT-X-BYTERANGE:1000@3000\n\
162 http://media.example.com/all.ts\n\
165 static const gchar *BYTE_RANGES_ACC_OFFSET_PLAYLIST = "#EXTM3U \n\
166 #EXT-X-TARGETDURATION:40\n\
168 #EXT-X-BYTERANGE:1000\n\
169 http://media.example.com/all.ts\n\
171 #EXT-X-BYTERANGE:1000\n\
172 http://media.example.com/all.ts\n\
174 #EXT-X-BYTERANGE:1000\n\
175 http://media.example.com/all.ts\n\
177 #EXT-X-BYTERANGE:1000\n\
178 http://media.example.com/all.ts\n\
182 static const gchar *ALTERNATE_AUDIO_PLAYLIST = "#EXTM3U\n\
183 #EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID=\"aac\",NAME=\"English\",\
184 DEFAULT=YES,AUTOSELECT=YES,LANGUAGE=\"en\" \n\
185 #EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID=\"aac\",NAME=\"Deutsche\",\
186 DEFAULT=NO,AUTOSELECT=YES,LANGUAGE=\"de\",\
187 URI=\"http://localhost/main/german-audio.m3u8\"\n\
188 #EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID=\"aac\",NAME=\"Commentary\",\
189 DEFAULT=NO,AUTOSELECT=NO,\
190 URI=\"http://localhost/commentary/audio-only.m3u8\"\n\
191 #EXT-X-STREAM-INF:BANDWIDTH=128000,CODECS=\"avc1.42001f\",AUDIO=\"aac\"\n\
192 low/video-only.m3u8\n\
193 #EXT-X-STREAM-INF:BANDWIDTH=256000,CODECS=\"avc1.42001f\",AUDIO=\"aac\"\n\
194 mid/video-only.m3u8\n\
195 #EXT-X-STREAM-INF:BANDWIDTH=768000,CODECS=\"avc1.42001f\",AUDIO=\"aac\"\n\
196 hi/video-only.m3u8\n\
197 #EXT-X-STREAM-INF:BANDWIDTH=65000,CODECS=\"mp4a.40.5\",AUDIO=\"aac\"\n\
198 main/english-audio.m3u8";
200 static const gchar *ALT_AUDIO_PLAYLIST_WITH_VIDEO_AUDIO = "#EXTM3U\n\
201 #EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID=\"aac\",NAME=\"English\",\
202 DEFAULT=YES,AUTOSELECT=YES,LANGUAGE=\"en\" \n\
203 #EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID=\"aac\",NAME=\"Deutsche\",\
204 DEFAULT=NO,AUTOSELECT=YES,LANGUAGE=\"de\",\
205 URI=\"http://localhost/main/german-audio.m3u8\"\n\
206 #EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID=\"aac\",NAME=\"Commentary\",\
207 DEFAULT=NO,AUTOSELECT=NO,\
208 URI=\"http://localhost/commentary/audio-only.m3u8\"\n\
209 #EXT-X-STREAM-INF:BANDWIDTH=128000,CODECS=\"avc1.42001f, mp4a.40.5\",AUDIO=\"aac\"\n\
210 low/video-audio.m3u8\n\
211 #EXT-X-STREAM-INF:BANDWIDTH=256000,CODECS=\"avc1.42001f, mp4a.40.5\",AUDIO=\"aac\"\n\
212 mid/video-audio.m3u8\n\
213 #EXT-X-STREAM-INF:BANDWIDTH=768000,CODECS=\"avc1.42001f, mp4a.40.5\",AUDIO=\"aac\"\n\
214 hi/video-audio.m3u8\n\
215 #EXT-X-STREAM-INF:BANDWIDTH=65000,CODECS=\"mp4a.40.5\",AUDIO=\"aac\"\n\
216 main/english-audio.m3u8";
218 static const gchar *ON_DEMAND_LOW_VIDEO_ONLY_PLAYLIST = "#EXTM3U \n\
219 #EXT-X-TARGETDURATION:10\n\
221 http://media.example.com/low/video-only-001.ts\n\
223 http://media.example.com/low/video-only-002.ts\n\
225 http://media.example.com/low/video-only-003.ts\n\
227 http://media.example.com/low/video-only-004.ts\n\
230 static const gchar *ON_DEMAND_MID_VIDEO_ONLY_PLAYLIST = "#EXTM3U \n\
231 #EXT-X-TARGETDURATION:10\n\
233 http://media.example.com/mid/video-only-001.ts\n\
235 http://media.example.com/mid/video-only-002.ts\n\
237 http://media.example.com/mid/video-only-003.ts\n\
239 http://media.example.com/mid/video-only-004.ts\n\
242 static const gchar *ON_DEMAND_ENGLISH_PLAYLIST = "#EXTM3U \n\
243 #EXT-X-TARGETDURATION:10\n\
245 http://media.example.com/audio/english-001.ts\n\
247 http://media.example.com/audio/english-002.ts\n\
249 http://media.example.com/audio/english-003.ts\n\
251 http://media.example.com/audio/english-004.ts\n\
254 static const gchar *ON_DEMAND_GERMAN_PLAYLIST = "#EXTM3U \n\
255 #EXT-X-TARGETDURATION:10\n\
257 http://media.example.com/audio/german-001.ts\n\
259 http://media.example.com/audio/german-002.ts\n\
261 http://media.example.com/audio/german-003.ts\n\
263 http://media.example.com/audio/german-004.ts\n\
266 static const gchar *SUBTITLES_PLAYLIST = "#EXTM3U\n\
267 #EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID=\"subs\",NAME=\"English\",\
268 DEFAULT=YES,LANGUAGE=\"en\",\
269 URI=\"http://localhost/main/subs-en.m3u8\"\n\
270 #EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID=\"subs\",NAME=\"Deutsche\",\
271 DEFAULT=NO,LANGUAGE=\"de\",\
272 URI=\"http://localhost/main/subs-de.m3u8\"\n\
273 #EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID=\"subs\",NAME=\"Spanish\",\
274 DEFAULT=NO,LANGUAGE=\"es\",\
275 URI=\"http://localhost/main/subs-es.m3u8\"\n\
276 #EXT-X-STREAM-INF:BANDWIDTH=128000,CODECS=\"avc1.42001f, mp4a.40.5\",SUBTITLES=\"subs\"\n\
277 low/video-audio.m3u8\n\
278 #EXT-X-STREAM-INF:BANDWIDTH=256000,CODECS=\"avc1.42001f, mp4a.40.5\",SUBTITLES=\"subs\"\n\
279 mid/video-audio.m3u8\n\
280 #EXT-X-STREAM-INF:BANDWIDTH=768000,CODECS=\"avc1.42001f, mp4a.40.5\",SUBTITLES=\"subs\"\n\
281 hi/video-audio.m3u8";
284 static const gchar *AES_128_ENCRYPTED_PLAYLIST = "#EXTM3U \n\
285 #EXT-X-TARGETDURATION:10\n\
287 http://media.example.com/mid/video-only-001.ts\n\
288 #EXT-X-KEY:METHOD=NONE\n\
290 http://media.example.com/mid/video-only-002.ts\n\
291 #EXT-X-KEY:METHOD=AES-128,URI=\"https://priv.example.com/key.bin\"\n\
293 http://media.example.com/mid/video-only-003.ts\n\
294 #EXT-X-KEY:METHOD=AES-128,URI=\"https://priv.example.com/key2.bin\",IV=0x00000000000000000000000000000001\n\
296 http://media.example.com/mid/video-only-004.ts\n\
298 http://media.example.com/mid/video-only-005.ts\n\
301 static const gchar *WINDOWS_LINE_ENDINGS_PLAYLIST = "#EXTM3U \r\n\
302 #EXT-X-TARGETDURATION:10\r\n\
304 http://media.example.com/001.ts\r\n\
306 http://media.example.com/002.ts\r\n\
308 http://media.example.com/003.ts\r\n\
310 http://media.example.com/004.ts\r\n\
313 static const gchar *WINDOWS_LINE_ENDINGS_VARIANT_PLAYLIST = "#EXTM3U \r\n\
314 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=128000\r\n\
315 http://example.com/low.m3u8\r\n\
316 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=256000\r\n\
317 http://example.com/mid.m3u8\r\n\
318 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=768000\r\n\
319 http://example.com/hi.m3u8\r\n\
320 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=65000,CODECS=\"mp4a.40.5\"\r\n\
321 http://example.com/audio-only.m3u8";
323 static const gchar *MAP_TAG_PLAYLIST = "#EXTM3U \n\
325 #EXT-X-MAP:URI=\"init1.mp4\",BYTERANGE=\"50@50\"\n\
327 #EXT-X-BYTERANGE:100@50\n\
330 #EXT-X-BYTERANGE:100@150\n\
332 #EXT-X-MAP:URI=\"init2.mp4\"\n\
334 #EXT-X-BYTERANGE:100@300\n\
338 static GstHLSMasterPlaylist *
339 load_playlist (const gchar * data)
341 GstHLSMasterPlaylist *master;
343 master = gst_hls_master_playlist_new_from_data (g_strdup (data),
344 "http://localhost/test.m3u8");
345 fail_unless (master != NULL);
350 GST_START_TEST (test_load_main_playlist_invalid)
352 GstHLSMasterPlaylist *master;
355 gst_hls_master_playlist_new_from_data (g_strdup (INVALID_PLAYLIST), NULL);
356 fail_unless (master == NULL);
361 GST_START_TEST (test_load_main_playlist_rendition)
363 GstHLSMasterPlaylist *master;
364 GstHLSVariantStream *variant;
366 master = load_playlist (ON_DEMAND_PLAYLIST);
367 variant = master->default_variant;
369 assert_equals_int (g_list_length (variant->m3u8->files), 4);
370 assert_equals_int (master->version, 0);
372 gst_hls_master_playlist_unref (master);
378 do_test_load_main_playlist_variant (const gchar * playlist)
380 GstHLSMasterPlaylist *master;
381 GstHLSVariantStream *stream;
384 master = gst_hls_master_playlist_new_from_data (g_strdup (playlist), NULL);
385 fail_unless (master != NULL);
387 assert_equals_int (g_list_length (master->variants), 4);
390 tmp = g_list_first (master->variants);
392 assert_equals_int (stream->bandwidth, 65000);
393 assert_equals_int (stream->program_id, 1);
394 assert_equals_string (stream->uri, "http://example.com/audio-only.m3u8");
395 assert_equals_string (stream->codecs, "mp4a.40.5");
398 tmp = g_list_next (tmp);
400 assert_equals_int (stream->bandwidth, 128000);
401 assert_equals_int (stream->program_id, 1);
402 assert_equals_string (stream->uri, "http://example.com/low.m3u8");
405 tmp = g_list_next (tmp);
407 assert_equals_int (stream->bandwidth, 256000);
408 assert_equals_int (stream->program_id, 1);
409 assert_equals_string (stream->uri, "http://example.com/mid.m3u8");
412 tmp = g_list_next (tmp);
414 assert_equals_int (stream->bandwidth, 768000);
415 assert_equals_int (stream->program_id, 1);
416 assert_equals_string (stream->uri, "http://example.com/hi.m3u8");
418 /* Check the first playlist is selected */
419 assert_equals_int (master->default_variant != NULL, TRUE);
420 assert_equals_int (master->default_variant->bandwidth, 128000);
422 gst_hls_master_playlist_unref (master);
425 GST_START_TEST (test_load_main_playlist_variant)
427 do_test_load_main_playlist_variant (VARIANT_PLAYLIST);
432 GST_START_TEST (test_load_main_playlist_variant_with_missing_uri)
434 GstHLSMasterPlaylist *master;
436 master = load_playlist (VARIANT_PLAYLIST_WITH_URI_MISSING);
437 assert_equals_int (g_list_length (master->variants), 3);
438 gst_hls_master_playlist_unref (master);
443 GST_START_TEST (test_load_windows_line_endings_variant_playlist)
445 do_test_load_main_playlist_variant (WINDOWS_LINE_ENDINGS_VARIANT_PLAYLIST);
450 GST_START_TEST (test_load_main_playlist_with_empty_lines)
452 do_test_load_main_playlist_variant (EMPTY_LINES_VARIANT_PLAYLIST);
457 GST_START_TEST (test_load_windows_main_playlist_with_empty_lines)
459 do_test_load_main_playlist_variant (WINDOWS_EMPTY_LINES_VARIANT_PLAYLIST);
465 check_on_demand_playlist (const gchar * data)
467 GstHLSMasterPlaylist *master;
469 GstM3U8MediaFile *file;
471 master = load_playlist (data);
472 pl = master->default_variant->m3u8;
474 /* Sequence should be 0 as it's an ondemand playlist */
475 assert_equals_int (pl->sequence, 0);
476 /* Check that we are not live */
477 assert_equals_int (gst_m3u8_is_live (pl), FALSE);
478 /* Check number of entries */
479 assert_equals_int (g_list_length (pl->files), 4);
480 /* Check first media segments */
481 file = GST_M3U8_MEDIA_FILE (g_list_first (pl->files)->data);
482 assert_equals_string (file->uri, "http://media.example.com/001.ts");
483 assert_equals_int (file->sequence, 0);
484 /* Check last media segments */
485 file = GST_M3U8_MEDIA_FILE (g_list_last (pl->files)->data);
486 assert_equals_string (file->uri, "http://media.example.com/004.ts");
487 assert_equals_int (file->sequence, 3);
489 gst_hls_master_playlist_unref (master);
492 GST_START_TEST (test_on_demand_playlist)
494 check_on_demand_playlist (ON_DEMAND_PLAYLIST);
499 GST_START_TEST (test_windows_line_endings_playlist)
501 check_on_demand_playlist (WINDOWS_LINE_ENDINGS_PLAYLIST);
506 GST_START_TEST (test_empty_lines_playlist)
508 check_on_demand_playlist (EMPTY_LINES_PLAYLIST);
513 GST_START_TEST (test_windows_empty_lines_playlist)
515 check_on_demand_playlist (WINDOWS_EMPTY_LINES_PLAYLIST);
520 GST_START_TEST (test_live_playlist)
522 GstHLSMasterPlaylist *master;
524 GstM3U8MediaFile *file;
528 master = load_playlist (LIVE_PLAYLIST);
530 pl = master->default_variant->m3u8;
531 /* Check that we are live */
532 assert_equals_int (gst_m3u8_is_live (pl), TRUE);
533 assert_equals_int (pl->sequence, 2680);
534 /* Check number of entries */
535 assert_equals_int (g_list_length (pl->files), 4);
536 /* Check first media segments */
537 file = GST_M3U8_MEDIA_FILE (g_list_first (pl->files)->data);
538 assert_equals_string (file->uri,
539 "https://priv.example.com/fileSequence2680.ts");
540 assert_equals_int (file->sequence, 2680);
541 /* Check last media segments */
542 file = GST_M3U8_MEDIA_FILE (g_list_last (pl->files)->data);
543 assert_equals_string (file->uri,
544 "https://priv.example.com/fileSequence2683.ts");
545 assert_equals_int (file->sequence, 2683);
546 fail_unless (gst_m3u8_get_seek_range (pl, &start, &stop));
547 assert_equals_int64 (start, 0);
548 assert_equals_float (stop / (double) GST_SECOND, 8.0);
550 gst_hls_master_playlist_unref (master);
555 /* This test is for live sreams in which we pause the stream for more than the
556 * DVR window and we resume playback. The playlist has rotated completely and
557 * there is a jump in the media sequence that must be handled correctly. */
558 GST_START_TEST (test_live_playlist_rotated)
560 GstHLSMasterPlaylist *master;
562 GstM3U8MediaFile *file;
565 master = load_playlist (LIVE_PLAYLIST);
566 pl = master->default_variant->m3u8;
568 assert_equals_int (pl->sequence, 2680);
569 /* Check first media segments */
570 file = GST_M3U8_MEDIA_FILE (g_list_first (pl->files)->data);
571 assert_equals_int (file->sequence, 2680);
573 ret = gst_m3u8_update (pl, g_strdup (LIVE_ROTATED_PLAYLIST));
574 assert_equals_int (ret, TRUE);
575 file = gst_m3u8_get_next_fragment (pl, TRUE, NULL, NULL);
576 fail_unless (file != NULL);
577 gst_m3u8_media_file_unref (file);
579 /* FIXME: Sequence should last - 3. Should it? */
580 assert_equals_int (pl->sequence, 3001);
581 /* Check first media segments */
582 file = GST_M3U8_MEDIA_FILE (g_list_first (pl->files)->data);
583 assert_equals_int (file->sequence, 3001);
585 gst_hls_master_playlist_unref (master);
590 GST_START_TEST (test_playlist_with_doubles_duration)
592 GstHLSMasterPlaylist *master;
594 GstM3U8MediaFile *file;
598 master = load_playlist (DOUBLES_PLAYLIST);
599 pl = master->default_variant->m3u8;
601 /* Check first media segments */
602 file = GST_M3U8_MEDIA_FILE (g_list_nth_data (pl->files, 0));
603 assert_equals_float (file->duration / (double) GST_SECOND, 10.321);
604 file = GST_M3U8_MEDIA_FILE (g_list_nth_data (pl->files, 1));
605 assert_equals_float (file->duration / (double) GST_SECOND, 9.6789);
606 file = GST_M3U8_MEDIA_FILE (g_list_nth_data (pl->files, 2));
607 assert_equals_float (file->duration / (double) GST_SECOND, 10.2344);
608 file = GST_M3U8_MEDIA_FILE (g_list_nth_data (pl->files, 3));
609 assert_equals_float (file->duration / (double) GST_SECOND, 9.92);
610 fail_unless (gst_m3u8_get_seek_range (pl, &start, &stop));
611 assert_equals_int64 (start, 0);
612 assert_equals_float (stop / (double) GST_SECOND,
613 10.321 + 9.6789 + 10.2344 + 9.92);
615 gst_hls_master_playlist_unref (master);
620 GST_START_TEST (test_playlist_with_encryption)
622 GstHLSMasterPlaylist *master;
624 GstM3U8MediaFile *file;
625 guint8 iv1[16] = { 0, };
626 guint8 iv2[16] = { 0, };
631 master = load_playlist (AES_128_ENCRYPTED_PLAYLIST);
632 pl = master->default_variant->m3u8;
634 assert_equals_int (g_list_length (pl->files), 5);
636 /* Check all media segments */
637 file = GST_M3U8_MEDIA_FILE (g_list_nth_data (pl->files, 0));
638 fail_unless (file->key == NULL);
640 file = GST_M3U8_MEDIA_FILE (g_list_nth_data (pl->files, 1));
641 fail_unless (file->key == NULL);
643 file = GST_M3U8_MEDIA_FILE (g_list_nth_data (pl->files, 2));
644 fail_unless (file->key != NULL);
645 assert_equals_string (file->key, "https://priv.example.com/key.bin");
646 fail_unless (memcmp (&file->iv, iv2, 16) == 0);
648 file = GST_M3U8_MEDIA_FILE (g_list_nth_data (pl->files, 3));
649 fail_unless (file->key != NULL);
650 assert_equals_string (file->key, "https://priv.example.com/key2.bin");
651 fail_unless (memcmp (&file->iv, iv1, 16) == 0);
653 file = GST_M3U8_MEDIA_FILE (g_list_nth_data (pl->files, 4));
654 fail_unless (file->key != NULL);
655 assert_equals_string (file->key, "https://priv.example.com/key2.bin");
656 fail_unless (memcmp (&file->iv, iv1, 16) == 0);
658 gst_hls_master_playlist_unref (master);
664 GST_START_TEST (test_update_invalid_playlist)
666 GstHLSMasterPlaylist *master;
670 /* Test updates in on-demand playlists */
671 master = load_playlist (ON_DEMAND_PLAYLIST);
672 pl = master->default_variant->m3u8;
673 assert_equals_int (g_list_length (pl->files), 4);
674 ret = gst_m3u8_update (pl, g_strdup ("#INVALID"));
675 assert_equals_int (ret, FALSE);
677 gst_hls_master_playlist_unref (master);
682 GST_START_TEST (test_update_playlist)
684 GstHLSMasterPlaylist *master;
689 /* Test updates in on-demand playlists */
690 master = load_playlist (ON_DEMAND_PLAYLIST);
691 pl = master->default_variant->m3u8;
692 assert_equals_int (g_list_length (pl->files), 4);
693 ret = gst_m3u8_update (pl, g_strdup (ON_DEMAND_PLAYLIST));
694 assert_equals_int (ret, TRUE);
695 assert_equals_int (g_list_length (pl->files), 4);
696 gst_hls_master_playlist_unref (master);
698 /* Test updates in live playlists */
699 master = load_playlist (LIVE_PLAYLIST);
700 pl = master->default_variant->m3u8;
701 assert_equals_int (g_list_length (pl->files), 4);
702 /* Add a new entry to the playlist and check the update */
703 live_pl = g_strdup_printf ("%s\n%s\n%s", LIVE_PLAYLIST, "#EXTINF:8",
704 "https://priv.example.com/fileSequence2683.ts");
705 ret = gst_m3u8_update (pl, live_pl);
706 assert_equals_int (ret, TRUE);
707 assert_equals_int (g_list_length (pl->files), 5);
708 /* Test sliding window */
709 ret = gst_m3u8_update (pl, g_strdup (LIVE_PLAYLIST));
710 assert_equals_int (ret, TRUE);
711 assert_equals_int (g_list_length (pl->files), 4);
712 gst_hls_master_playlist_unref (master);
717 GST_START_TEST (test_playlist_media_files)
719 GstHLSMasterPlaylist *master;
721 GstM3U8MediaFile *file;
723 master = load_playlist (ON_DEMAND_PLAYLIST);
724 pl = master->default_variant->m3u8;
726 /* Check number of entries */
727 assert_equals_int (g_list_length (pl->files), 4);
728 /* Check first media segments */
729 file = GST_M3U8_MEDIA_FILE (g_list_first (pl->files)->data);
730 assert_equals_string (file->uri, "http://media.example.com/001.ts");
731 assert_equals_int (file->sequence, 0);
732 assert_equals_float (file->duration, 10 * (double) GST_SECOND);
733 assert_equals_int (file->offset, 0);
734 assert_equals_int (file->size, -1);
735 assert_equals_string (file->title, "Test");
737 gst_hls_master_playlist_unref (master);
742 GST_START_TEST (test_playlist_byte_range_media_files)
744 GstHLSMasterPlaylist *master;
746 GstM3U8MediaFile *file;
748 master = load_playlist (BYTE_RANGES_PLAYLIST);
749 pl = master->default_variant->m3u8;
751 /* Check number of entries */
752 assert_equals_int (g_list_length (pl->files), 4);
753 /* Check first media segments */
754 file = GST_M3U8_MEDIA_FILE (g_list_first (pl->files)->data);
755 assert_equals_string (file->uri, "http://media.example.com/all.ts");
756 assert_equals_int (file->sequence, 0);
757 assert_equals_float (file->duration, 10 * (double) GST_SECOND);
758 assert_equals_int (file->offset, 100);
759 assert_equals_int (file->size, 1000);
760 /* Check last media segments */
761 file = GST_M3U8_MEDIA_FILE (g_list_last (pl->files)->data);
762 assert_equals_string (file->uri, "http://media.example.com/all.ts");
763 assert_equals_int (file->sequence, 3);
764 assert_equals_float (file->duration, 10 * (double) GST_SECOND);
765 assert_equals_int (file->offset, 3000);
766 assert_equals_int (file->size, 1000);
768 gst_hls_master_playlist_unref (master);
771 master = load_playlist (BYTE_RANGES_ACC_OFFSET_PLAYLIST);
772 pl = master->default_variant->m3u8;
774 /* Check number of entries */
775 assert_equals_int (g_list_length (pl->files), 4);
776 /* Check first media segments */
777 file = GST_M3U8_MEDIA_FILE (g_list_first (pl->files)->data);
778 assert_equals_string (file->uri, "http://media.example.com/all.ts");
779 assert_equals_int (file->sequence, 0);
780 assert_equals_float (file->duration, 10 * (double) GST_SECOND);
781 assert_equals_int (file->offset, 0);
782 assert_equals_int (file->size, 1000);
783 /* Check last media segments */
784 file = GST_M3U8_MEDIA_FILE (g_list_last (pl->files)->data);
785 assert_equals_string (file->uri, "http://media.example.com/all.ts");
786 assert_equals_int (file->sequence, 3);
787 assert_equals_float (file->duration, 10 * (double) GST_SECOND);
788 assert_equals_int (file->offset, 3000);
789 assert_equals_int (file->size, 1000);
791 gst_hls_master_playlist_unref (master);
796 GST_START_TEST (test_get_next_fragment)
798 GstHLSMasterPlaylist *master;
800 GstM3U8MediaFile *mf;
801 gboolean discontinuous;
802 GstClockTime timestamp;
804 master = load_playlist (BYTE_RANGES_PLAYLIST);
805 pl = master->default_variant->m3u8;
807 /* Check the next fragment */
808 mf = gst_m3u8_get_next_fragment (pl, TRUE, ×tamp, &discontinuous);
809 fail_unless (mf != NULL);
810 assert_equals_int (discontinuous, FALSE);
811 assert_equals_string (mf->uri, "http://media.example.com/all.ts");
812 assert_equals_uint64 (timestamp, 0);
813 assert_equals_uint64 (mf->duration, 10 * GST_SECOND);
814 assert_equals_uint64 (mf->offset, 100);
815 assert_equals_uint64 (mf->offset + mf->size, 1100);
816 gst_m3u8_media_file_unref (mf);
818 gst_m3u8_advance_fragment (pl, TRUE);
820 /* Check next media segments */
821 mf = gst_m3u8_get_next_fragment (pl, TRUE, ×tamp, &discontinuous);
822 fail_unless (mf != NULL);
823 assert_equals_int (discontinuous, FALSE);
824 assert_equals_string (mf->uri, "http://media.example.com/all.ts");
825 assert_equals_uint64 (timestamp, 10 * GST_SECOND);
826 assert_equals_uint64 (mf->duration, 10 * GST_SECOND);
827 assert_equals_uint64 (mf->offset, 1000);
828 assert_equals_uint64 (mf->offset + mf->size, 2000);
829 gst_m3u8_media_file_unref (mf);
831 gst_m3u8_advance_fragment (pl, TRUE);
833 /* Check next media segments */
834 mf = gst_m3u8_get_next_fragment (pl, TRUE, ×tamp, &discontinuous);
835 assert_equals_int (discontinuous, FALSE);
836 assert_equals_string (mf->uri, "http://media.example.com/all.ts");
837 assert_equals_uint64 (timestamp, 20 * GST_SECOND);
838 assert_equals_uint64 (mf->duration, 10 * GST_SECOND);
839 assert_equals_uint64 (mf->offset, 2000);
840 assert_equals_uint64 (mf->offset + mf->size, 3000);
841 gst_m3u8_media_file_unref (mf);
843 gst_hls_master_playlist_unref (master);
848 GST_START_TEST (test_get_duration)
850 GstHLSMasterPlaylist *master;
853 /* Test duration for on-demand playlists */
854 master = load_playlist (ON_DEMAND_PLAYLIST);
855 pl = master->default_variant->m3u8;
857 assert_equals_uint64 (gst_m3u8_get_duration (pl), 40 * GST_SECOND);
858 gst_hls_master_playlist_unref (master);
860 /* Test duration for live playlists */
861 master = load_playlist (LIVE_PLAYLIST);
862 pl = master->default_variant->m3u8;
863 assert_equals_uint64 (gst_m3u8_get_duration (pl), GST_CLOCK_TIME_NONE);
865 gst_hls_master_playlist_unref (master);
870 GST_START_TEST (test_get_target_duration)
872 GstHLSMasterPlaylist *master;
875 master = load_playlist (ON_DEMAND_PLAYLIST);
876 pl = master->default_variant->m3u8;
878 assert_equals_uint64 (gst_m3u8_get_target_duration (pl), 10 * GST_SECOND);
880 gst_hls_master_playlist_unref (master);
886 GST_START_TEST (test_get_stream_for_bitrate)
888 GstHLSMasterPlaylist *master;
889 GstHLSVariantStream *stream;
891 master = load_playlist (VARIANT_PLAYLIST);
892 stream = gst_hls_master_playlist_get_variant_for_bitrate (master, NULL, 0);
894 assert_equals_int (stream->bandwidth, 65000);
897 gst_hls_master_playlist_get_variant_for_bitrate (master, NULL,
899 assert_equals_int (stream->bandwidth, 768000);
901 gst_hls_master_playlist_get_variant_for_bitrate (master, NULL, 300000);
902 assert_equals_int (stream->bandwidth, 256000);
904 gst_hls_master_playlist_get_variant_for_bitrate (master, NULL, 500000);
905 assert_equals_int (stream->bandwidth, 256000);
907 gst_hls_master_playlist_get_variant_for_bitrate (master, NULL, 255000);
908 assert_equals_int (stream->bandwidth, 128000);
910 gst_hls_master_playlist_unref (master);
917 do_test_seek (GstM3U8Client * client, guint seek_pos, gint pos)
919 GstClockTime cur_pos;
922 ret = gst_m3u8_client_seek (client, seek_pos * GST_SECOND);
924 assert_equals_int (ret, FALSE);
927 assert_equals_int (ret, TRUE);
928 gst_m3u8_client_get_current_position (client, &cur_pos, NULL);
929 assert_equals_uint64 (cur_pos, pos * GST_SECOND);
932 GST_START_TEST (test_seek)
934 GstM3U8Client *client;
936 master = load_playlist (ON_DEMAND_PLAYLIST);
938 /* Test seek in the middle of a fragment */
939 do_test_seek (client, 1, 0);
940 do_test_seek (client, 11, 10);
941 do_test_seek (client, 22, 20);
942 do_test_seek (client, 39, 30);
944 /* Test exact seeks */
945 do_test_seek (client, 0, 0);
946 do_test_seek (client, 10, 10);
947 do_test_seek (client, 20, 20);
948 do_test_seek (client, 30, 30);
950 /* Test invalid seeks (end if list should be 30 + 10) */
951 do_test_seek (client, 39, 30);
952 do_test_seek (client, 40, -1);
953 gst_hls_master_playlist_unref (master);
955 /* Test seeks on a live playlist */
956 master = load_playlist (LIVE_PLAYLIST);
957 do_test_seek (client, 0, 0);
959 do_test_seek (client, 8, 8);
960 do_test_seek (client, 20, 16);
961 do_test_seek (client, 30, 24);
963 do_test_seek (client, 3000, -1);
964 gst_hls_master_playlist_unref (master);
969 GST_START_TEST (test_alternate_audio_playlist)
971 GstM3U8Client *client;
975 master = load_playlist (ALTERNATE_AUDIO_PLAYLIST);
977 assert_equals_int (g_list_length (client->main->streams), 4);
978 assert_equals_int (g_hash_table_size (client->main->video_rendition_groups),
980 assert_equals_int (g_hash_table_size (client->main->audio_rendition_groups),
982 assert_equals_int (g_hash_table_size (client->
983 selected_stream->audio_alternates), 3);
984 assert_equals_int (g_hash_table_size (client->
985 selected_stream->video_alternates), 0);
988 g_hash_table_lookup (client->main->audio_rendition_groups, "aac");
989 assert_equals_int (alternates != NULL, TRUE);
990 media = GST_M3U8_MEDIA (g_list_nth_data (alternates, 0));
991 assert_equals_int (media->media_type, GST_M3U8_MEDIA_TYPE_AUDIO);
992 assert_equals_string (media->group_id, "aac");
993 assert_equals_string (media->name, "English");
994 assert_equals_string (media->language, "en");
995 assert_equals_string (media->uri, "http://localhost/main/english-audio.m3u8");
996 assert_equals_string (media->uri, GST_M3U8 (media->playlist)->uri);
997 assert_equals_int (media->is_default, TRUE);
998 assert_equals_int (media->autoselect, TRUE);
1000 assert_equals_int (g_hash_table_size (client->
1001 selected_stream->audio_alternates), 3);
1002 /* Check the list of audio alternates */
1003 alternates = gst_m3u8_client_get_alternates (client,
1004 GST_M3U8_MEDIA_TYPE_AUDIO);
1005 assert_equals_int (g_list_length (alternates), 3);
1006 /* Default comes always first */
1007 assert_equals_string (g_list_nth_data (alternates, 0), "English");
1008 assert_equals_string (g_list_nth_data (alternates, 1), "Commentary");
1009 assert_equals_string (g_list_nth_data (alternates, 2), "Deutsche");
1011 gst_hls_master_playlist_unref (master);
1016 GST_START_TEST (test_subtitles_playlist)
1018 GstM3U8Client *client;
1019 GstM3U8Media *media;
1022 master = load_playlist (SUBTITLES_PLAYLIST);
1024 assert_equals_int (g_list_length (client->main->streams), 3);
1025 assert_equals_int (g_hash_table_size (client->main->video_rendition_groups),
1027 assert_equals_int (g_hash_table_size (client->main->audio_rendition_groups),
1029 assert_equals_int (g_hash_table_size (client->main->subtt_rendition_groups),
1031 assert_equals_int (g_hash_table_size (client->
1032 selected_stream->audio_alternates), 0);
1033 assert_equals_int (g_hash_table_size (client->
1034 selected_stream->video_alternates), 0);
1035 assert_equals_int (g_hash_table_size (client->
1036 selected_stream->subtt_alternates), 3);
1039 g_hash_table_lookup (client->main->subtt_rendition_groups, "subs");
1040 assert_equals_int (alternates != NULL, TRUE);
1041 media = GST_M3U8_MEDIA (g_list_nth_data (alternates, 0));
1042 assert_equals_int (media->media_type, GST_M3U8_MEDIA_TYPE_SUBTITLES);
1043 assert_equals_string (media->group_id, "subs");
1044 assert_equals_string (media->name, "English");
1045 assert_equals_string (media->language, "en");
1046 assert_equals_string (media->uri, "http://localhost/main/subs-en.m3u8");
1047 assert_equals_string (media->uri, GST_M3U8 (media->playlist)->uri);
1048 assert_equals_int (media->is_default, TRUE);
1049 assert_equals_int (media->autoselect, FALSE);
1051 /* Check the list of subtitles */
1052 alternates = gst_m3u8_client_get_alternates (client,
1053 GST_M3U8_MEDIA_TYPE_SUBTITLES);
1054 assert_equals_int (g_list_length (alternates), 3);
1055 assert_equals_string (g_list_nth_data (alternates, 0), "Deutsche");
1056 assert_equals_string (g_list_nth_data (alternates, 1), "Spanish");
1057 assert_equals_string (g_list_nth_data (alternates, 2), "English");
1059 gst_hls_master_playlist_unref (master);
1063 GST_START_TEST (test_select_subs_alternate)
1065 GstM3U8Client *client;
1066 const gchar *a_uri, *v_uri, *s_uri;
1069 /* Check with a playlist with alternative audio renditions where the video
1070 * stream is video-only and therefor we always have 2 playlists, one for
1071 * video and another one for audio */
1072 master = load_playlist (SUBTITLES_PLAYLIST);
1073 gst_m3u8_client_get_current_uri (client, &v_uri, &a_uri, &s_uri);
1074 assert_equals_int (a_uri == NULL, TRUE);
1075 assert_equals_int (s_uri != NULL, TRUE);
1076 assert_equals_string (s_uri, "http://localhost/main/subs-de.m3u8");
1077 assert_equals_int (v_uri != NULL, TRUE);
1078 assert_equals_string (v_uri, "http://localhost/low/video-audio.m3u8");
1081 gst_m3u8_client_set_alternate (client, GST_M3U8_MEDIA_TYPE_SUBTITLES,
1083 assert_equals_int (ret, TRUE);
1084 gst_m3u8_client_get_current_uri (client, &v_uri, &a_uri, &s_uri);
1085 assert_equals_int (a_uri == NULL, TRUE);
1086 assert_equals_int (v_uri != NULL, TRUE);
1087 assert_equals_string (v_uri, "http://localhost/low/video-audio.m3u8");
1088 assert_equals_int (s_uri != NULL, TRUE);
1089 assert_equals_string (s_uri, "http://localhost/main/subs-en.m3u8");
1092 gst_m3u8_client_set_alternate (client, GST_M3U8_MEDIA_TYPE_SUBTITLES,
1094 assert_equals_int (ret, TRUE);
1095 gst_m3u8_client_get_current_uri (client, &v_uri, &a_uri, &s_uri);
1096 assert_equals_int (a_uri == NULL, TRUE);
1097 assert_equals_int (v_uri != NULL, TRUE);
1098 assert_equals_string (v_uri, "http://localhost/low/video-audio.m3u8");
1099 assert_equals_int (s_uri != NULL, TRUE);
1100 assert_equals_string (s_uri, "http://localhost/main/subs-es.m3u8");
1103 gst_m3u8_client_set_alternate (client, GST_M3U8_MEDIA_TYPE_SUBTITLES,
1105 assert_equals_int (ret, TRUE);
1106 gst_m3u8_client_get_current_uri (client, &v_uri, &a_uri, &s_uri);
1107 assert_equals_int (a_uri == NULL, TRUE);
1108 assert_equals_int (v_uri != NULL, TRUE);
1109 assert_equals_string (v_uri, "http://localhost/low/video-audio.m3u8");
1110 assert_equals_int (s_uri == NULL, TRUE);
1112 gst_hls_master_playlist_unref (master);
1116 GST_START_TEST (test_select_alternate)
1118 GstM3U8Client *client;
1119 const gchar *a_uri, *v_uri, *s_uri;
1122 /* Check with a playlist with alternative audio renditions where the video
1123 * stream is video-only and therefor we always have 2 playlists, one for
1124 * video and another one for audio */
1125 master = load_playlist (ALTERNATE_AUDIO_PLAYLIST);
1126 gst_m3u8_client_get_current_uri (client, &v_uri, &a_uri, &s_uri);
1127 assert_equals_int (a_uri != NULL, TRUE);
1128 assert_equals_string (a_uri, "http://localhost/main/english-audio.m3u8");
1129 assert_equals_int (v_uri != NULL, TRUE);
1130 assert_equals_string (v_uri, "http://localhost/low/video-only.m3u8");
1131 assert_equals_int (s_uri == NULL, TRUE);
1134 gst_m3u8_client_set_alternate (client, GST_M3U8_MEDIA_TYPE_AUDIO,
1136 assert_equals_int (ret, TRUE);
1137 gst_m3u8_client_get_current_uri (client, &v_uri, &a_uri, &s_uri);
1138 assert_equals_int (a_uri != NULL, TRUE);
1139 assert_equals_string (a_uri, "http://localhost/main/german-audio.m3u8");
1140 assert_equals_int (v_uri != NULL, TRUE);
1141 assert_equals_string (v_uri, "http://localhost/low/video-only.m3u8");
1142 assert_equals_int (s_uri == NULL, TRUE);
1144 /* Check that selecting the audio-only fallback stream we only have the audio
1146 gst_m3u8_client_set_current (client,
1147 GST_M3U8_STREAM (client->main->streams->data));
1148 gst_m3u8_client_get_current_uri (client, &v_uri, &a_uri, &s_uri);
1149 assert_equals_int (a_uri != NULL, TRUE);
1150 assert_equals_string (a_uri, "http://localhost/main/german-audio.m3u8");
1151 assert_equals_int (v_uri == NULL, TRUE);
1152 assert_equals_int (s_uri == NULL, TRUE);
1154 gst_hls_master_playlist_unref (master);
1156 /* Now check with a playlist with alternative audio renditions where the
1157 * video * stream has the default audio rendition muxed and therefore we
1158 * only have 2 playlists when the audio alternative rendition is not the
1160 master = load_playlist (ALT_AUDIO_PLAYLIST_WITH_VIDEO_AUDIO);
1161 gst_m3u8_client_get_current_uri (client, &v_uri, &a_uri, &s_uri);
1162 assert_equals_int (a_uri == NULL, TRUE);
1163 assert_equals_int (v_uri != NULL, TRUE);
1164 assert_equals_string (v_uri, "http://localhost/low/video-audio.m3u8");
1165 assert_equals_int (s_uri == NULL, TRUE);
1167 /* Check that selecting the audio-only fallback stream we only have the audio
1169 gst_m3u8_client_set_current (client,
1170 GST_M3U8_STREAM (client->main->streams->data));
1171 gst_m3u8_client_get_current_uri (client, &v_uri, &a_uri, &s_uri);
1172 assert_equals_int (a_uri != NULL, TRUE);
1173 assert_equals_string (a_uri, "http://localhost/main/english-audio.m3u8");
1174 assert_equals_int (v_uri == NULL, TRUE);
1175 assert_equals_int (s_uri == NULL, TRUE);
1177 /* Get back to the audio-video stream */
1178 gst_m3u8_client_set_current (client,
1179 GST_M3U8_STREAM (client->main->streams->next->data));
1180 /* Now set a different audio and check that we have 2 playlists */
1182 gst_m3u8_client_set_alternate (client, GST_M3U8_MEDIA_TYPE_AUDIO,
1184 assert_equals_int (ret, TRUE);
1185 gst_m3u8_client_get_current_uri (client, &v_uri, &a_uri, &s_uri);
1186 assert_equals_int (a_uri != NULL, TRUE);
1187 assert_equals_string (a_uri, "http://localhost/main/german-audio.m3u8");
1188 assert_equals_int (v_uri != NULL, TRUE);
1189 assert_equals_string (v_uri, "http://localhost/low/video-audio.m3u8");
1190 assert_equals_int (s_uri == NULL, TRUE);
1192 gst_hls_master_playlist_unref (master);
1197 GST_START_TEST (test_simulation)
1199 GstM3U8Client *client;
1200 const gchar *a_uri, *v_uri, *s_uri;
1201 GstFragment *a_frag, *v_frag, *s_frag;
1204 master = load_playlist (ALTERNATE_AUDIO_PLAYLIST);
1205 /* The default selection should be audio-only, which only has audio and not
1207 gst_m3u8_client_get_current_uri (client, &v_uri, &a_uri, &s_uri);
1208 assert_equals_int (a_uri != NULL, TRUE);
1209 assert_equals_string (a_uri, "http://localhost/main/english-audio.m3u8");
1210 assert_equals_int (v_uri != NULL, TRUE);
1211 assert_equals_string (v_uri, "http://localhost/low/video-only.m3u8");
1212 assert_equals_int (s_uri == NULL, TRUE);
1214 /* Update the playlists */
1215 ret = gst_m3u8_update (client,
1216 g_strdup (ON_DEMAND_LOW_VIDEO_ONLY_PLAYLIST),
1217 g_strdup (ON_DEMAND_ENGLISH_PLAYLIST), NULL);
1218 assert_equals_int (ret, TRUE);
1219 assert_equals_int (g_list_length (client->selected_stream->selected_video->
1221 assert_equals_int (g_list_length (client->selected_stream->selected_audio->
1224 /* Get the first fragment */
1225 gst_m3u8_client_get_next_fragment (client, &v_frag, &a_frag, &s_frag);
1226 assert_equals_int (v_frag != NULL, TRUE);
1227 assert_equals_int (a_frag != NULL, TRUE);
1228 assert_equals_string (v_frag->name,
1229 "http://media.example.com/low/video-only-001.ts");
1230 assert_equals_string (a_frag->name,
1231 "http://media.example.com/audio/english-001.ts");
1232 g_object_unref (v_frag);
1233 g_object_unref (a_frag);
1235 /* Get the next fragment */
1236 gst_m3u8_client_get_next_fragment (client, &v_frag, &a_frag, &s_frag);
1237 assert_equals_int (v_frag != NULL, TRUE);
1238 assert_equals_int (a_frag != NULL, TRUE);
1239 assert_equals_string (v_frag->name,
1240 "http://media.example.com/low/video-only-002.ts");
1241 assert_equals_string (a_frag->name,
1242 "http://media.example.com/audio/english-002.ts");
1243 g_object_unref (v_frag);
1244 g_object_unref (a_frag);
1246 /* Switch to German audio */
1248 gst_m3u8_client_set_alternate (client, GST_M3U8_MEDIA_TYPE_AUDIO,
1250 assert_equals_int (ret, TRUE);
1251 /* Get the new uri's */
1252 gst_m3u8_client_get_current_uri (client, &v_uri, &a_uri, &s_uri);
1253 assert_equals_int (a_uri != NULL, TRUE);
1254 assert_equals_string (a_uri, "http://localhost/main/german-audio.m3u8");
1255 /* On demand so the uri does not need to be downloaded again */
1256 assert_equals_int (v_uri == NULL, TRUE);
1257 assert_equals_int (s_uri == NULL, TRUE);
1258 /* Update the new uri's */
1260 gst_m3u8_update (client,
1261 g_strdup (ON_DEMAND_LOW_VIDEO_ONLY_PLAYLIST),
1262 g_strdup (ON_DEMAND_GERMAN_PLAYLIST), NULL);
1263 assert_equals_int (ret, TRUE);
1264 gst_m3u8_client_get_next_fragment (client, &v_frag, &a_frag, &s_frag);
1265 assert_equals_int (s_frag == NULL, TRUE);
1266 assert_equals_int (v_frag != NULL, TRUE);
1267 assert_equals_int (a_frag != NULL, TRUE);
1268 assert_equals_string (a_frag->name,
1269 "http://media.example.com/audio/german-003.ts");
1270 assert_equals_string (v_frag->name,
1271 "http://media.example.com/low/video-only-003.ts");
1272 g_object_unref (v_frag);
1273 g_object_unref (a_frag);
1275 /* Switch to a higher bitrate */
1276 gst_m3u8_client_set_current (client,
1277 gst_m3u8_client_get_stream_for_bitrate (client, 260000));
1278 gst_m3u8_client_get_current_uri (client, &v_uri, &a_uri, &s_uri);
1279 assert_equals_int (a_uri != NULL, TRUE);
1280 assert_equals_string (a_uri, "http://localhost/main/german-audio.m3u8");
1281 assert_equals_int (v_uri != NULL, TRUE);
1282 assert_equals_string (v_uri, "http://localhost/mid/video-only.m3u8");
1283 assert_equals_int (s_uri == NULL, TRUE);
1285 gst_m3u8_update (client,
1286 g_strdup (ON_DEMAND_MID_VIDEO_ONLY_PLAYLIST),
1287 g_strdup (ON_DEMAND_GERMAN_PLAYLIST), NULL);
1288 assert_equals_int (ret, TRUE);
1289 gst_m3u8_client_get_next_fragment (client, &v_frag, &a_frag, &s_frag);
1290 assert_equals_int (s_frag == NULL, TRUE);
1291 assert_equals_int (a_frag != NULL, TRUE);
1292 assert_equals_int (v_frag != NULL, TRUE);
1293 assert_equals_string (a_frag->name,
1294 "http://media.example.com/audio/german-004.ts");
1295 assert_equals_string (v_frag->name,
1296 "http://media.example.com/mid/video-only-004.ts");
1297 g_object_unref (v_frag);
1298 g_object_unref (a_frag);
1300 /* Seek to the beginning */
1301 gst_m3u8_client_seek (client, 0);
1302 gst_m3u8_client_get_next_fragment (client, &v_frag, &a_frag, &s_frag);
1303 assert_equals_int (s_frag == NULL, TRUE);
1304 assert_equals_int (a_frag != NULL, TRUE);
1305 assert_equals_int (v_frag != NULL, TRUE);
1306 assert_equals_string (a_frag->name,
1307 "http://media.example.com/audio/german-001.ts");
1308 assert_equals_string (v_frag->name,
1309 "http://media.example.com/mid/video-only-001.ts");
1310 g_object_unref (v_frag);
1311 g_object_unref (a_frag);
1313 /* Select English audio again */
1315 gst_m3u8_client_set_alternate (client, GST_M3U8_MEDIA_TYPE_AUDIO,
1317 assert_equals_int (ret, TRUE);
1318 gst_m3u8_client_get_next_fragment (client, &v_frag, &a_frag, &s_frag);
1319 assert_equals_int (s_frag == NULL, TRUE);
1320 assert_equals_int (a_frag != NULL, TRUE);
1321 assert_equals_int (v_frag != NULL, TRUE);
1322 assert_equals_string (a_frag->name,
1323 "http://media.example.com/audio/english-002.ts");
1324 assert_equals_string (v_frag->name,
1325 "http://media.example.com/mid/video-only-002.ts");
1326 g_object_unref (v_frag);
1327 g_object_unref (a_frag);
1329 /* Go to the audio-only fallback */
1330 gst_m3u8_client_set_current (client,
1331 gst_m3u8_client_get_stream_for_bitrate (client, 20000));
1332 gst_m3u8_client_get_next_fragment (client, &v_frag, &a_frag, &s_frag);
1333 assert_equals_int (s_frag == NULL, TRUE);
1334 assert_equals_int (a_frag != NULL, TRUE);
1335 assert_equals_int (v_frag == NULL, TRUE);
1336 assert_equals_string (a_frag->name,
1337 "http://media.example.com/audio/english-003.ts");
1338 g_object_unref (a_frag);
1340 /* Go to mid again */
1341 gst_m3u8_client_set_current (client,
1342 gst_m3u8_client_get_stream_for_bitrate (client, 260000));
1343 gst_m3u8_client_get_next_fragment (client, &v_frag, &a_frag, &s_frag);
1344 assert_equals_int (s_frag == NULL, TRUE);
1345 assert_equals_int (a_frag != NULL, TRUE);
1346 assert_equals_int (v_frag != NULL, TRUE);
1347 assert_equals_string (a_frag->name,
1348 "http://media.example.com/audio/english-004.ts");
1349 assert_equals_string (v_frag->name,
1350 "http://media.example.com/mid/video-only-004.ts");
1351 g_object_unref (a_frag);
1352 g_object_unref (v_frag);
1355 ret = gst_m3u8_client_get_next_fragment (client, &v_frag, &a_frag, &s_frag);
1356 assert_equals_int (ret, FALSE);
1358 gst_hls_master_playlist_unref (master);
1364 GST_START_TEST (test_url_with_slash_query_param)
1366 static const gchar *MASTER_PLAYLIST = "#EXTM3U \n"
1367 "#EXT-X-VERSION:4\n"
1368 "#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=1251135, CODECS=\"avc1.42001f, mp4a.40.2\", RESOLUTION=640x352\n"
1369 "1251/media.m3u8?acl=/*1054559_h264_1500k.mp4\n";
1370 GstHLSMasterPlaylist *master;
1371 GstHLSVariantStream *stream;
1374 master = load_playlist (MASTER_PLAYLIST);
1376 assert_equals_int (g_list_length (master->variants), 1);
1377 stream = g_list_nth_data (master->variants, 0);
1378 media = stream->m3u8;
1380 assert_equals_string (media->uri,
1381 "http://localhost/1251/media.m3u8?acl=/*1054559_h264_1500k.mp4");
1382 gst_hls_master_playlist_unref (master);
1387 GST_START_TEST (test_stream_inf_tag)
1389 static const gchar *MASTER_PLAYLIST = "#EXTM3U \n"
1390 "#EXT-X-VERSION:4\n"
1391 "#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=1251135, CODECS=\"avc1.42001f, mp4a.40.2\", RESOLUTION=640x352\n"
1393 GstHLSMasterPlaylist *master;
1394 GstHLSVariantStream *stream;
1396 master = load_playlist (MASTER_PLAYLIST);
1398 assert_equals_int (g_list_length (master->variants), 1);
1399 stream = g_list_nth_data (master->variants, 0);
1401 assert_equals_int64 (stream->program_id, 1);
1402 assert_equals_int64 (stream->width, 640);
1403 assert_equals_int64 (stream->height, 352);
1404 assert_equals_int64 (stream->bandwidth, 1251135);
1405 assert_equals_string (stream->codecs, "avc1.42001f, mp4a.40.2");
1406 gst_hls_master_playlist_unref (master);
1411 GST_START_TEST (test_map_tag)
1413 GstHLSMasterPlaylist *master;
1414 GstHLSVariantStream *stream;
1416 GList *files, *walk;
1417 GstM3U8MediaFile *seg1, *seg2, *seg3;
1418 GstM3U8InitFile *init1, *init2;
1420 /* Test EXT-X-MAP tag
1421 * This M3U8 has two EXT-X-MAP tag.
1422 * the first one is applied to the 1st and 2nd segments, and the other is
1423 * applied only to the 3rd segment
1426 master = load_playlist (MAP_TAG_PLAYLIST);
1428 assert_equals_int (master->is_simple, TRUE);
1429 assert_equals_int (g_list_length (master->variants), 1);
1430 stream = g_list_nth_data (master->variants, 0);
1432 m3u8 = stream->m3u8;
1433 fail_unless (m3u8 != NULL);
1435 files = m3u8->files;
1436 fail_unless (m3u8 != NULL);
1437 assert_equals_int (g_list_length (files), 3);
1438 for (walk = files; walk; walk = g_list_next (walk)) {
1439 GstM3U8MediaFile *file = (GstM3U8MediaFile *) walk->data;
1441 GstM3U8InitFile *init_file = file->init_file;
1442 fail_unless (init_file != NULL);
1443 fail_unless (init_file->uri != NULL);
1446 seg1 = g_list_nth_data (files, 0);
1447 seg2 = g_list_nth_data (files, 1);
1448 seg3 = g_list_nth_data (files, 2);
1450 /* Segment 1 and 2 share the identical init segment */
1451 fail_unless (seg1->init_file == seg2->init_file);
1452 assert_equals_int (seg1->init_file->ref_count, 2);
1454 fail_unless (seg2->init_file != seg3->init_file);
1455 assert_equals_int (seg3->init_file->ref_count, 1);
1457 init1 = seg1->init_file;
1458 init2 = seg3->init_file;
1460 fail_unless (g_strcmp0 (init1->uri, init2->uri));
1461 assert_equals_int (init1->offset, 50);
1462 assert_equals_int (init1->size, 50);
1464 assert_equals_int (init2->offset, 0);
1465 assert_equals_int (init2->size, -1);
1467 gst_hls_master_playlist_unref (master);
1473 hlsdemux_suite (void)
1475 Suite *s = suite_create ("hlsdemux_m3u8");
1476 TCase *tc_m3u8 = tcase_create ("m3u8client");
1478 GST_DEBUG_CATEGORY_INIT (hls_debug, "hlsdemux_m3u", 0, "hlsdemux m3u test");
1480 suite_add_tcase (s, tc_m3u8);
1481 tcase_add_test (tc_m3u8, test_load_main_playlist_invalid);
1482 tcase_add_test (tc_m3u8, test_load_main_playlist_rendition);
1483 tcase_add_test (tc_m3u8, test_load_main_playlist_variant);
1484 tcase_add_test (tc_m3u8, test_load_main_playlist_variant_with_missing_uri);
1485 tcase_add_test (tc_m3u8, test_load_windows_line_endings_variant_playlist);
1486 tcase_add_test (tc_m3u8, test_load_main_playlist_with_empty_lines);
1487 tcase_add_test (tc_m3u8, test_load_windows_main_playlist_with_empty_lines);
1488 tcase_add_test (tc_m3u8, test_on_demand_playlist);
1489 tcase_add_test (tc_m3u8, test_windows_line_endings_playlist);
1490 tcase_add_test (tc_m3u8, test_windows_empty_lines_playlist);
1491 tcase_add_test (tc_m3u8, test_empty_lines_playlist);
1492 tcase_add_test (tc_m3u8, test_live_playlist);
1493 tcase_add_test (tc_m3u8, test_live_playlist_rotated);
1494 tcase_add_test (tc_m3u8, test_playlist_with_doubles_duration);
1495 tcase_add_test (tc_m3u8, test_playlist_with_encryption);
1496 tcase_add_test (tc_m3u8, test_update_invalid_playlist);
1497 tcase_add_test (tc_m3u8, test_update_playlist);
1498 tcase_add_test (tc_m3u8, test_playlist_media_files);
1499 tcase_add_test (tc_m3u8, test_playlist_byte_range_media_files);
1500 tcase_add_test (tc_m3u8, test_get_next_fragment);
1501 tcase_add_test (tc_m3u8, test_get_duration);
1502 tcase_add_test (tc_m3u8, test_get_target_duration);
1503 tcase_add_test (tc_m3u8, test_get_stream_for_bitrate);
1505 tcase_add_test (tc_m3u8, test_seek);
1506 tcase_add_test (tc_m3u8, test_alternate_audio_playlist);
1507 tcase_add_test (tc_m3u8, test_subtitles_playlist);
1508 tcase_add_test (tc_m3u8, test_select_alternate);
1509 tcase_add_test (tc_m3u8, test_select_subs_alternate);
1510 tcase_add_test (tc_m3u8, test_simulation);
1512 tcase_add_test (tc_m3u8, test_url_with_slash_query_param);
1513 tcase_add_test (tc_m3u8, test_stream_inf_tag);
1514 tcase_add_test (tc_m3u8, test_map_tag);
1518 GST_CHECK_MAIN (hlsdemux);