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 GstHLSMasterPlaylist *
324 load_playlist (const gchar * data)
326 GstHLSMasterPlaylist *master;
328 master = gst_hls_master_playlist_new_from_data (g_strdup (data),
329 "http://localhost/test.m3u8");
330 fail_unless (master != NULL);
335 GST_START_TEST (test_load_main_playlist_invalid)
337 GstHLSMasterPlaylist *master;
340 gst_hls_master_playlist_new_from_data (g_strdup (INVALID_PLAYLIST), NULL);
341 fail_unless (master == NULL);
346 GST_START_TEST (test_load_main_playlist_rendition)
348 GstHLSMasterPlaylist *master;
349 GstHLSVariantStream *variant;
351 master = load_playlist (ON_DEMAND_PLAYLIST);
352 variant = master->default_variant;
354 assert_equals_int (g_list_length (variant->m3u8->files), 4);
355 assert_equals_int (master->version, 0);
357 gst_hls_master_playlist_unref (master);
363 do_test_load_main_playlist_variant (const gchar * playlist)
365 GstHLSMasterPlaylist *master;
366 GstHLSVariantStream *stream;
369 master = gst_hls_master_playlist_new_from_data (g_strdup (playlist), NULL);
370 fail_unless (master != NULL);
372 assert_equals_int (g_list_length (master->variants), 4);
375 tmp = g_list_first (master->variants);
377 assert_equals_int (stream->bandwidth, 65000);
378 assert_equals_int (stream->program_id, 1);
379 assert_equals_string (stream->uri, "http://example.com/audio-only.m3u8");
380 assert_equals_string (stream->codecs, "mp4a.40.5");
383 tmp = g_list_next (tmp);
385 assert_equals_int (stream->bandwidth, 128000);
386 assert_equals_int (stream->program_id, 1);
387 assert_equals_string (stream->uri, "http://example.com/low.m3u8");
390 tmp = g_list_next (tmp);
392 assert_equals_int (stream->bandwidth, 256000);
393 assert_equals_int (stream->program_id, 1);
394 assert_equals_string (stream->uri, "http://example.com/mid.m3u8");
397 tmp = g_list_next (tmp);
399 assert_equals_int (stream->bandwidth, 768000);
400 assert_equals_int (stream->program_id, 1);
401 assert_equals_string (stream->uri, "http://example.com/hi.m3u8");
403 /* Check the first playlist is selected */
404 assert_equals_int (master->default_variant != NULL, TRUE);
405 assert_equals_int (master->default_variant->bandwidth, 128000);
407 gst_hls_master_playlist_unref (master);
410 GST_START_TEST (test_load_main_playlist_variant)
412 do_test_load_main_playlist_variant (VARIANT_PLAYLIST);
417 GST_START_TEST (test_load_main_playlist_variant_with_missing_uri)
419 GstHLSMasterPlaylist *master;
421 master = load_playlist (VARIANT_PLAYLIST_WITH_URI_MISSING);
422 assert_equals_int (g_list_length (master->variants), 3);
423 gst_hls_master_playlist_unref (master);
428 GST_START_TEST (test_load_windows_line_endings_variant_playlist)
430 do_test_load_main_playlist_variant (WINDOWS_LINE_ENDINGS_VARIANT_PLAYLIST);
435 GST_START_TEST (test_load_main_playlist_with_empty_lines)
437 do_test_load_main_playlist_variant (EMPTY_LINES_VARIANT_PLAYLIST);
442 GST_START_TEST (test_load_windows_main_playlist_with_empty_lines)
444 do_test_load_main_playlist_variant (WINDOWS_EMPTY_LINES_VARIANT_PLAYLIST);
450 check_on_demand_playlist (const gchar * data)
452 GstHLSMasterPlaylist *master;
454 GstM3U8MediaFile *file;
456 master = load_playlist (data);
457 pl = master->default_variant->m3u8;
459 /* Sequence should be 0 as it's an ondemand playlist */
460 assert_equals_int (pl->sequence, 0);
461 /* Check that we are not live */
462 assert_equals_int (gst_m3u8_is_live (pl), FALSE);
463 /* Check number of entries */
464 assert_equals_int (g_list_length (pl->files), 4);
465 /* Check first media segments */
466 file = GST_M3U8_MEDIA_FILE (g_list_first (pl->files)->data);
467 assert_equals_string (file->uri, "http://media.example.com/001.ts");
468 assert_equals_int (file->sequence, 0);
469 /* Check last media segments */
470 file = GST_M3U8_MEDIA_FILE (g_list_last (pl->files)->data);
471 assert_equals_string (file->uri, "http://media.example.com/004.ts");
472 assert_equals_int (file->sequence, 3);
474 gst_hls_master_playlist_unref (master);
477 GST_START_TEST (test_on_demand_playlist)
479 check_on_demand_playlist (ON_DEMAND_PLAYLIST);
484 GST_START_TEST (test_windows_line_endings_playlist)
486 check_on_demand_playlist (WINDOWS_LINE_ENDINGS_PLAYLIST);
491 GST_START_TEST (test_empty_lines_playlist)
493 check_on_demand_playlist (EMPTY_LINES_PLAYLIST);
498 GST_START_TEST (test_windows_empty_lines_playlist)
500 check_on_demand_playlist (WINDOWS_EMPTY_LINES_PLAYLIST);
505 GST_START_TEST (test_live_playlist)
507 GstHLSMasterPlaylist *master;
509 GstM3U8MediaFile *file;
513 master = load_playlist (LIVE_PLAYLIST);
515 pl = master->default_variant->m3u8;
516 /* Check that we are live */
517 assert_equals_int (gst_m3u8_is_live (pl), TRUE);
518 assert_equals_int (pl->sequence, 2680);
519 /* Check number of entries */
520 assert_equals_int (g_list_length (pl->files), 4);
521 /* Check first media segments */
522 file = GST_M3U8_MEDIA_FILE (g_list_first (pl->files)->data);
523 assert_equals_string (file->uri,
524 "https://priv.example.com/fileSequence2680.ts");
525 assert_equals_int (file->sequence, 2680);
526 /* Check last media segments */
527 file = GST_M3U8_MEDIA_FILE (g_list_last (pl->files)->data);
528 assert_equals_string (file->uri,
529 "https://priv.example.com/fileSequence2683.ts");
530 assert_equals_int (file->sequence, 2683);
531 fail_unless (gst_m3u8_get_seek_range (pl, &start, &stop));
532 assert_equals_int64 (start, 0);
533 assert_equals_float (stop / (double) GST_SECOND, 8.0);
535 gst_hls_master_playlist_unref (master);
540 /* This test is for live sreams in which we pause the stream for more than the
541 * DVR window and we resume playback. The playlist has rotated completely and
542 * there is a jump in the media sequence that must be handled correctly. */
543 GST_START_TEST (test_live_playlist_rotated)
545 GstHLSMasterPlaylist *master;
547 GstM3U8MediaFile *file;
550 master = load_playlist (LIVE_PLAYLIST);
551 pl = master->default_variant->m3u8;
553 assert_equals_int (pl->sequence, 2680);
554 /* Check first media segments */
555 file = GST_M3U8_MEDIA_FILE (g_list_first (pl->files)->data);
556 assert_equals_int (file->sequence, 2680);
558 ret = gst_m3u8_update (pl, g_strdup (LIVE_ROTATED_PLAYLIST));
559 assert_equals_int (ret, TRUE);
560 file = gst_m3u8_get_next_fragment (pl, TRUE, NULL, NULL);
561 fail_unless (file != NULL);
562 gst_m3u8_media_file_unref (file);
564 /* FIXME: Sequence should last - 3. Should it? */
565 assert_equals_int (pl->sequence, 3001);
566 /* Check first media segments */
567 file = GST_M3U8_MEDIA_FILE (g_list_first (pl->files)->data);
568 assert_equals_int (file->sequence, 3001);
570 gst_hls_master_playlist_unref (master);
575 GST_START_TEST (test_playlist_with_doubles_duration)
577 GstHLSMasterPlaylist *master;
579 GstM3U8MediaFile *file;
583 master = load_playlist (DOUBLES_PLAYLIST);
584 pl = master->default_variant->m3u8;
586 /* Check first media segments */
587 file = GST_M3U8_MEDIA_FILE (g_list_nth_data (pl->files, 0));
588 assert_equals_float (file->duration / (double) GST_SECOND, 10.321);
589 file = GST_M3U8_MEDIA_FILE (g_list_nth_data (pl->files, 1));
590 assert_equals_float (file->duration / (double) GST_SECOND, 9.6789);
591 file = GST_M3U8_MEDIA_FILE (g_list_nth_data (pl->files, 2));
592 assert_equals_float (file->duration / (double) GST_SECOND, 10.2344);
593 file = GST_M3U8_MEDIA_FILE (g_list_nth_data (pl->files, 3));
594 assert_equals_float (file->duration / (double) GST_SECOND, 9.92);
595 fail_unless (gst_m3u8_get_seek_range (pl, &start, &stop));
596 assert_equals_int64 (start, 0);
597 assert_equals_float (stop / (double) GST_SECOND,
598 10.321 + 9.6789 + 10.2344 + 9.92);
600 gst_hls_master_playlist_unref (master);
605 GST_START_TEST (test_playlist_with_encryption)
607 GstHLSMasterPlaylist *master;
609 GstM3U8MediaFile *file;
610 guint8 iv1[16] = { 0, };
611 guint8 iv2[16] = { 0, };
616 master = load_playlist (AES_128_ENCRYPTED_PLAYLIST);
617 pl = master->default_variant->m3u8;
619 assert_equals_int (g_list_length (pl->files), 5);
621 /* Check all media segments */
622 file = GST_M3U8_MEDIA_FILE (g_list_nth_data (pl->files, 0));
623 fail_unless (file->key == NULL);
625 file = GST_M3U8_MEDIA_FILE (g_list_nth_data (pl->files, 1));
626 fail_unless (file->key == NULL);
628 file = GST_M3U8_MEDIA_FILE (g_list_nth_data (pl->files, 2));
629 fail_unless (file->key != NULL);
630 assert_equals_string (file->key, "https://priv.example.com/key.bin");
631 fail_unless (memcmp (&file->iv, iv2, 16) == 0);
633 file = GST_M3U8_MEDIA_FILE (g_list_nth_data (pl->files, 3));
634 fail_unless (file->key != NULL);
635 assert_equals_string (file->key, "https://priv.example.com/key2.bin");
636 fail_unless (memcmp (&file->iv, iv1, 16) == 0);
638 file = GST_M3U8_MEDIA_FILE (g_list_nth_data (pl->files, 4));
639 fail_unless (file->key != NULL);
640 assert_equals_string (file->key, "https://priv.example.com/key2.bin");
641 fail_unless (memcmp (&file->iv, iv1, 16) == 0);
643 gst_hls_master_playlist_unref (master);
649 GST_START_TEST (test_update_invalid_playlist)
651 GstHLSMasterPlaylist *master;
655 /* Test updates in on-demand playlists */
656 master = load_playlist (ON_DEMAND_PLAYLIST);
657 pl = master->default_variant->m3u8;
658 assert_equals_int (g_list_length (pl->files), 4);
659 ret = gst_m3u8_update (pl, g_strdup ("#INVALID"));
660 assert_equals_int (ret, FALSE);
662 gst_hls_master_playlist_unref (master);
667 GST_START_TEST (test_update_playlist)
669 GstHLSMasterPlaylist *master;
674 /* Test updates in on-demand playlists */
675 master = load_playlist (ON_DEMAND_PLAYLIST);
676 pl = master->default_variant->m3u8;
677 assert_equals_int (g_list_length (pl->files), 4);
678 ret = gst_m3u8_update (pl, g_strdup (ON_DEMAND_PLAYLIST));
679 assert_equals_int (ret, TRUE);
680 assert_equals_int (g_list_length (pl->files), 4);
681 gst_hls_master_playlist_unref (master);
683 /* Test updates in live playlists */
684 master = load_playlist (LIVE_PLAYLIST);
685 pl = master->default_variant->m3u8;
686 assert_equals_int (g_list_length (pl->files), 4);
687 /* Add a new entry to the playlist and check the update */
688 live_pl = g_strdup_printf ("%s\n%s\n%s", LIVE_PLAYLIST, "#EXTINF:8",
689 "https://priv.example.com/fileSequence2683.ts");
690 ret = gst_m3u8_update (pl, live_pl);
691 assert_equals_int (ret, TRUE);
692 assert_equals_int (g_list_length (pl->files), 5);
693 /* Test sliding window */
694 ret = gst_m3u8_update (pl, g_strdup (LIVE_PLAYLIST));
695 assert_equals_int (ret, TRUE);
696 assert_equals_int (g_list_length (pl->files), 4);
697 gst_hls_master_playlist_unref (master);
702 GST_START_TEST (test_playlist_media_files)
704 GstHLSMasterPlaylist *master;
706 GstM3U8MediaFile *file;
708 master = load_playlist (ON_DEMAND_PLAYLIST);
709 pl = master->default_variant->m3u8;
711 /* Check number of entries */
712 assert_equals_int (g_list_length (pl->files), 4);
713 /* Check first media segments */
714 file = GST_M3U8_MEDIA_FILE (g_list_first (pl->files)->data);
715 assert_equals_string (file->uri, "http://media.example.com/001.ts");
716 assert_equals_int (file->sequence, 0);
717 assert_equals_float (file->duration, 10 * (double) GST_SECOND);
718 assert_equals_int (file->offset, 0);
719 assert_equals_int (file->size, -1);
720 assert_equals_string (file->title, "Test");
722 gst_hls_master_playlist_unref (master);
727 GST_START_TEST (test_playlist_byte_range_media_files)
729 GstHLSMasterPlaylist *master;
731 GstM3U8MediaFile *file;
733 master = load_playlist (BYTE_RANGES_PLAYLIST);
734 pl = master->default_variant->m3u8;
736 /* Check number of entries */
737 assert_equals_int (g_list_length (pl->files), 4);
738 /* Check first media segments */
739 file = GST_M3U8_MEDIA_FILE (g_list_first (pl->files)->data);
740 assert_equals_string (file->uri, "http://media.example.com/all.ts");
741 assert_equals_int (file->sequence, 0);
742 assert_equals_float (file->duration, 10 * (double) GST_SECOND);
743 assert_equals_int (file->offset, 100);
744 assert_equals_int (file->size, 1000);
745 /* Check last media segments */
746 file = GST_M3U8_MEDIA_FILE (g_list_last (pl->files)->data);
747 assert_equals_string (file->uri, "http://media.example.com/all.ts");
748 assert_equals_int (file->sequence, 3);
749 assert_equals_float (file->duration, 10 * (double) GST_SECOND);
750 assert_equals_int (file->offset, 3000);
751 assert_equals_int (file->size, 1000);
753 gst_hls_master_playlist_unref (master);
756 master = load_playlist (BYTE_RANGES_ACC_OFFSET_PLAYLIST);
757 pl = master->default_variant->m3u8;
759 /* Check number of entries */
760 assert_equals_int (g_list_length (pl->files), 4);
761 /* Check first media segments */
762 file = GST_M3U8_MEDIA_FILE (g_list_first (pl->files)->data);
763 assert_equals_string (file->uri, "http://media.example.com/all.ts");
764 assert_equals_int (file->sequence, 0);
765 assert_equals_float (file->duration, 10 * (double) GST_SECOND);
766 assert_equals_int (file->offset, 0);
767 assert_equals_int (file->size, 1000);
768 /* Check last media segments */
769 file = GST_M3U8_MEDIA_FILE (g_list_last (pl->files)->data);
770 assert_equals_string (file->uri, "http://media.example.com/all.ts");
771 assert_equals_int (file->sequence, 3);
772 assert_equals_float (file->duration, 10 * (double) GST_SECOND);
773 assert_equals_int (file->offset, 3000);
774 assert_equals_int (file->size, 1000);
776 gst_hls_master_playlist_unref (master);
781 GST_START_TEST (test_get_next_fragment)
783 GstHLSMasterPlaylist *master;
785 GstM3U8MediaFile *mf;
786 gboolean discontinous;
787 GstClockTime timestamp;
789 master = load_playlist (BYTE_RANGES_PLAYLIST);
790 pl = master->default_variant->m3u8;
792 /* Check the next fragment */
793 mf = gst_m3u8_get_next_fragment (pl, TRUE, ×tamp, &discontinous);
794 fail_unless (mf != NULL);
795 assert_equals_int (discontinous, FALSE);
796 assert_equals_string (mf->uri, "http://media.example.com/all.ts");
797 assert_equals_uint64 (timestamp, 0);
798 assert_equals_uint64 (mf->duration, 10 * GST_SECOND);
799 assert_equals_uint64 (mf->offset, 100);
800 assert_equals_uint64 (mf->offset + mf->size, 1100);
801 gst_m3u8_media_file_unref (mf);
803 gst_m3u8_advance_fragment (pl, TRUE);
805 /* Check next media segments */
806 mf = gst_m3u8_get_next_fragment (pl, TRUE, ×tamp, &discontinous);
807 fail_unless (mf != NULL);
808 assert_equals_int (discontinous, FALSE);
809 assert_equals_string (mf->uri, "http://media.example.com/all.ts");
810 assert_equals_uint64 (timestamp, 10 * GST_SECOND);
811 assert_equals_uint64 (mf->duration, 10 * GST_SECOND);
812 assert_equals_uint64 (mf->offset, 1000);
813 assert_equals_uint64 (mf->offset + mf->size, 2000);
814 gst_m3u8_media_file_unref (mf);
816 gst_m3u8_advance_fragment (pl, TRUE);
818 /* Check next media segments */
819 mf = gst_m3u8_get_next_fragment (pl, TRUE, ×tamp, &discontinous);
820 assert_equals_int (discontinous, FALSE);
821 assert_equals_string (mf->uri, "http://media.example.com/all.ts");
822 assert_equals_uint64 (timestamp, 20 * GST_SECOND);
823 assert_equals_uint64 (mf->duration, 10 * GST_SECOND);
824 assert_equals_uint64 (mf->offset, 2000);
825 assert_equals_uint64 (mf->offset + mf->size, 3000);
826 gst_m3u8_media_file_unref (mf);
828 gst_hls_master_playlist_unref (master);
833 GST_START_TEST (test_get_duration)
835 GstHLSMasterPlaylist *master;
838 /* Test duration for on-demand playlists */
839 master = load_playlist (ON_DEMAND_PLAYLIST);
840 pl = master->default_variant->m3u8;
842 assert_equals_uint64 (gst_m3u8_get_duration (pl), 40 * GST_SECOND);
843 gst_hls_master_playlist_unref (master);
845 /* Test duration for live playlists */
846 master = load_playlist (LIVE_PLAYLIST);
847 pl = master->default_variant->m3u8;
848 assert_equals_uint64 (gst_m3u8_get_duration (pl), GST_CLOCK_TIME_NONE);
850 gst_hls_master_playlist_unref (master);
855 GST_START_TEST (test_get_target_duration)
857 GstHLSMasterPlaylist *master;
860 master = load_playlist (ON_DEMAND_PLAYLIST);
861 pl = master->default_variant->m3u8;
863 assert_equals_uint64 (gst_m3u8_get_target_duration (pl), 10 * GST_SECOND);
865 gst_hls_master_playlist_unref (master);
871 GST_START_TEST (test_get_stream_for_bitrate)
873 GstHLSMasterPlaylist *master;
874 GstHLSVariantStream *stream;
876 master = load_playlist (VARIANT_PLAYLIST);
877 stream = gst_hls_master_playlist_get_variant_for_bitrate (master, NULL, 0);
879 assert_equals_int (stream->bandwidth, 65000);
882 gst_hls_master_playlist_get_variant_for_bitrate (master, NULL,
884 assert_equals_int (stream->bandwidth, 768000);
886 gst_hls_master_playlist_get_variant_for_bitrate (master, NULL, 300000);
887 assert_equals_int (stream->bandwidth, 256000);
889 gst_hls_master_playlist_get_variant_for_bitrate (master, NULL, 500000);
890 assert_equals_int (stream->bandwidth, 256000);
892 gst_hls_master_playlist_get_variant_for_bitrate (master, NULL, 255000);
893 assert_equals_int (stream->bandwidth, 128000);
895 gst_hls_master_playlist_unref (master);
902 do_test_seek (GstM3U8Client * client, guint seek_pos, gint pos)
904 GstClockTime cur_pos;
907 ret = gst_m3u8_client_seek (client, seek_pos * GST_SECOND);
909 assert_equals_int (ret, FALSE);
912 assert_equals_int (ret, TRUE);
913 gst_m3u8_client_get_current_position (client, &cur_pos, NULL);
914 assert_equals_uint64 (cur_pos, pos * GST_SECOND);
917 GST_START_TEST (test_seek)
919 GstM3U8Client *client;
921 master = load_playlist (ON_DEMAND_PLAYLIST);
923 /* Test seek in the middle of a fragment */
924 do_test_seek (client, 1, 0);
925 do_test_seek (client, 11, 10);
926 do_test_seek (client, 22, 20);
927 do_test_seek (client, 39, 30);
929 /* Test exact seeks */
930 do_test_seek (client, 0, 0);
931 do_test_seek (client, 10, 10);
932 do_test_seek (client, 20, 20);
933 do_test_seek (client, 30, 30);
935 /* Test invalid seeks (end if list should be 30 + 10) */
936 do_test_seek (client, 39, 30);
937 do_test_seek (client, 40, -1);
938 gst_hls_master_playlist_unref (master);
940 /* Test seeks on a live playlist */
941 master = load_playlist (LIVE_PLAYLIST);
942 do_test_seek (client, 0, 0);
944 do_test_seek (client, 8, 8);
945 do_test_seek (client, 20, 16);
946 do_test_seek (client, 30, 24);
948 do_test_seek (client, 3000, -1);
949 gst_hls_master_playlist_unref (master);
954 GST_START_TEST (test_alternate_audio_playlist)
956 GstM3U8Client *client;
960 master = load_playlist (ALTERNATE_AUDIO_PLAYLIST);
962 assert_equals_int (g_list_length (client->main->streams), 4);
963 assert_equals_int (g_hash_table_size (client->main->video_rendition_groups),
965 assert_equals_int (g_hash_table_size (client->main->audio_rendition_groups),
967 assert_equals_int (g_hash_table_size (client->
968 selected_stream->audio_alternates), 3);
969 assert_equals_int (g_hash_table_size (client->
970 selected_stream->video_alternates), 0);
973 g_hash_table_lookup (client->main->audio_rendition_groups, "aac");
974 assert_equals_int (alternates != NULL, TRUE);
975 media = GST_M3U8_MEDIA (g_list_nth_data (alternates, 0));
976 assert_equals_int (media->media_type, GST_M3U8_MEDIA_TYPE_AUDIO);
977 assert_equals_string (media->group_id, "aac");
978 assert_equals_string (media->name, "English");
979 assert_equals_string (media->language, "en");
980 assert_equals_string (media->uri, "http://localhost/main/english-audio.m3u8");
981 assert_equals_string (media->uri, GST_M3U8 (media->playlist)->uri);
982 assert_equals_int (media->is_default, TRUE);
983 assert_equals_int (media->autoselect, TRUE);
985 assert_equals_int (g_hash_table_size (client->
986 selected_stream->audio_alternates), 3);
987 /* Check the list of audio alternates */
988 alternates = gst_m3u8_client_get_alternates (client,
989 GST_M3U8_MEDIA_TYPE_AUDIO);
990 assert_equals_int (g_list_length (alternates), 3);
991 /* Default comes always first */
992 assert_equals_string (g_list_nth_data (alternates, 0), "English");
993 assert_equals_string (g_list_nth_data (alternates, 1), "Commentary");
994 assert_equals_string (g_list_nth_data (alternates, 2), "Deutsche");
996 gst_hls_master_playlist_unref (master);
1001 GST_START_TEST (test_subtitles_playlist)
1003 GstM3U8Client *client;
1004 GstM3U8Media *media;
1007 master = load_playlist (SUBTITLES_PLAYLIST);
1009 assert_equals_int (g_list_length (client->main->streams), 3);
1010 assert_equals_int (g_hash_table_size (client->main->video_rendition_groups),
1012 assert_equals_int (g_hash_table_size (client->main->audio_rendition_groups),
1014 assert_equals_int (g_hash_table_size (client->main->subtt_rendition_groups),
1016 assert_equals_int (g_hash_table_size (client->
1017 selected_stream->audio_alternates), 0);
1018 assert_equals_int (g_hash_table_size (client->
1019 selected_stream->video_alternates), 0);
1020 assert_equals_int (g_hash_table_size (client->
1021 selected_stream->subtt_alternates), 3);
1024 g_hash_table_lookup (client->main->subtt_rendition_groups, "subs");
1025 assert_equals_int (alternates != NULL, TRUE);
1026 media = GST_M3U8_MEDIA (g_list_nth_data (alternates, 0));
1027 assert_equals_int (media->media_type, GST_M3U8_MEDIA_TYPE_SUBTITLES);
1028 assert_equals_string (media->group_id, "subs");
1029 assert_equals_string (media->name, "English");
1030 assert_equals_string (media->language, "en");
1031 assert_equals_string (media->uri, "http://localhost/main/subs-en.m3u8");
1032 assert_equals_string (media->uri, GST_M3U8 (media->playlist)->uri);
1033 assert_equals_int (media->is_default, TRUE);
1034 assert_equals_int (media->autoselect, FALSE);
1036 /* Check the list of subtitles */
1037 alternates = gst_m3u8_client_get_alternates (client,
1038 GST_M3U8_MEDIA_TYPE_SUBTITLES);
1039 assert_equals_int (g_list_length (alternates), 3);
1040 assert_equals_string (g_list_nth_data (alternates, 0), "Deutsche");
1041 assert_equals_string (g_list_nth_data (alternates, 1), "Spanish");
1042 assert_equals_string (g_list_nth_data (alternates, 2), "English");
1044 gst_hls_master_playlist_unref (master);
1048 GST_START_TEST (test_select_subs_alternate)
1050 GstM3U8Client *client;
1051 const gchar *a_uri, *v_uri, *s_uri;
1054 /* Check with a playlist with alternative audio renditions where the video
1055 * stream is video-only and therefor we always have 2 playlists, one for
1056 * video and another one for audio */
1057 master = load_playlist (SUBTITLES_PLAYLIST);
1058 gst_m3u8_client_get_current_uri (client, &v_uri, &a_uri, &s_uri);
1059 assert_equals_int (a_uri == NULL, TRUE);
1060 assert_equals_int (s_uri != NULL, TRUE);
1061 assert_equals_string (s_uri, "http://localhost/main/subs-de.m3u8");
1062 assert_equals_int (v_uri != NULL, TRUE);
1063 assert_equals_string (v_uri, "http://localhost/low/video-audio.m3u8");
1066 gst_m3u8_client_set_alternate (client, GST_M3U8_MEDIA_TYPE_SUBTITLES,
1068 assert_equals_int (ret, TRUE);
1069 gst_m3u8_client_get_current_uri (client, &v_uri, &a_uri, &s_uri);
1070 assert_equals_int (a_uri == NULL, TRUE);
1071 assert_equals_int (v_uri != NULL, TRUE);
1072 assert_equals_string (v_uri, "http://localhost/low/video-audio.m3u8");
1073 assert_equals_int (s_uri != NULL, TRUE);
1074 assert_equals_string (s_uri, "http://localhost/main/subs-en.m3u8");
1077 gst_m3u8_client_set_alternate (client, GST_M3U8_MEDIA_TYPE_SUBTITLES,
1079 assert_equals_int (ret, TRUE);
1080 gst_m3u8_client_get_current_uri (client, &v_uri, &a_uri, &s_uri);
1081 assert_equals_int (a_uri == NULL, TRUE);
1082 assert_equals_int (v_uri != NULL, TRUE);
1083 assert_equals_string (v_uri, "http://localhost/low/video-audio.m3u8");
1084 assert_equals_int (s_uri != NULL, TRUE);
1085 assert_equals_string (s_uri, "http://localhost/main/subs-es.m3u8");
1088 gst_m3u8_client_set_alternate (client, GST_M3U8_MEDIA_TYPE_SUBTITLES,
1090 assert_equals_int (ret, TRUE);
1091 gst_m3u8_client_get_current_uri (client, &v_uri, &a_uri, &s_uri);
1092 assert_equals_int (a_uri == NULL, TRUE);
1093 assert_equals_int (v_uri != NULL, TRUE);
1094 assert_equals_string (v_uri, "http://localhost/low/video-audio.m3u8");
1095 assert_equals_int (s_uri == NULL, TRUE);
1097 gst_hls_master_playlist_unref (master);
1101 GST_START_TEST (test_select_alternate)
1103 GstM3U8Client *client;
1104 const gchar *a_uri, *v_uri, *s_uri;
1107 /* Check with a playlist with alternative audio renditions where the video
1108 * stream is video-only and therefor we always have 2 playlists, one for
1109 * video and another one for audio */
1110 master = load_playlist (ALTERNATE_AUDIO_PLAYLIST);
1111 gst_m3u8_client_get_current_uri (client, &v_uri, &a_uri, &s_uri);
1112 assert_equals_int (a_uri != NULL, TRUE);
1113 assert_equals_string (a_uri, "http://localhost/main/english-audio.m3u8");
1114 assert_equals_int (v_uri != NULL, TRUE);
1115 assert_equals_string (v_uri, "http://localhost/low/video-only.m3u8");
1116 assert_equals_int (s_uri == NULL, TRUE);
1119 gst_m3u8_client_set_alternate (client, GST_M3U8_MEDIA_TYPE_AUDIO,
1121 assert_equals_int (ret, TRUE);
1122 gst_m3u8_client_get_current_uri (client, &v_uri, &a_uri, &s_uri);
1123 assert_equals_int (a_uri != NULL, TRUE);
1124 assert_equals_string (a_uri, "http://localhost/main/german-audio.m3u8");
1125 assert_equals_int (v_uri != NULL, TRUE);
1126 assert_equals_string (v_uri, "http://localhost/low/video-only.m3u8");
1127 assert_equals_int (s_uri == NULL, TRUE);
1129 /* Check that selecting the audio-only fallback stream we only have the audio
1131 gst_m3u8_client_set_current (client,
1132 GST_M3U8_STREAM (client->main->streams->data));
1133 gst_m3u8_client_get_current_uri (client, &v_uri, &a_uri, &s_uri);
1134 assert_equals_int (a_uri != NULL, TRUE);
1135 assert_equals_string (a_uri, "http://localhost/main/german-audio.m3u8");
1136 assert_equals_int (v_uri == NULL, TRUE);
1137 assert_equals_int (s_uri == NULL, TRUE);
1139 gst_hls_master_playlist_unref (master);
1141 /* Now check with a playlist with alternative audio renditions where the
1142 * video * stream has the default audio rendition muxed and therefore we
1143 * only have 2 playlists when the audio alternative rendition is not the
1145 master = load_playlist (ALT_AUDIO_PLAYLIST_WITH_VIDEO_AUDIO);
1146 gst_m3u8_client_get_current_uri (client, &v_uri, &a_uri, &s_uri);
1147 assert_equals_int (a_uri == NULL, TRUE);
1148 assert_equals_int (v_uri != NULL, TRUE);
1149 assert_equals_string (v_uri, "http://localhost/low/video-audio.m3u8");
1150 assert_equals_int (s_uri == NULL, TRUE);
1152 /* Check that selecting the audio-only fallback stream we only have the audio
1154 gst_m3u8_client_set_current (client,
1155 GST_M3U8_STREAM (client->main->streams->data));
1156 gst_m3u8_client_get_current_uri (client, &v_uri, &a_uri, &s_uri);
1157 assert_equals_int (a_uri != NULL, TRUE);
1158 assert_equals_string (a_uri, "http://localhost/main/english-audio.m3u8");
1159 assert_equals_int (v_uri == NULL, TRUE);
1160 assert_equals_int (s_uri == NULL, TRUE);
1162 /* Get back to the audio-video stream */
1163 gst_m3u8_client_set_current (client,
1164 GST_M3U8_STREAM (client->main->streams->next->data));
1165 /* Now set a different audio and check that we have 2 playlists */
1167 gst_m3u8_client_set_alternate (client, GST_M3U8_MEDIA_TYPE_AUDIO,
1169 assert_equals_int (ret, TRUE);
1170 gst_m3u8_client_get_current_uri (client, &v_uri, &a_uri, &s_uri);
1171 assert_equals_int (a_uri != NULL, TRUE);
1172 assert_equals_string (a_uri, "http://localhost/main/german-audio.m3u8");
1173 assert_equals_int (v_uri != NULL, TRUE);
1174 assert_equals_string (v_uri, "http://localhost/low/video-audio.m3u8");
1175 assert_equals_int (s_uri == NULL, TRUE);
1177 gst_hls_master_playlist_unref (master);
1182 GST_START_TEST (test_simulation)
1184 GstM3U8Client *client;
1185 const gchar *a_uri, *v_uri, *s_uri;
1186 GstFragment *a_frag, *v_frag, *s_frag;
1189 master = load_playlist (ALTERNATE_AUDIO_PLAYLIST);
1190 /* The default selection should be audio-only, which only has audio and not
1192 gst_m3u8_client_get_current_uri (client, &v_uri, &a_uri, &s_uri);
1193 assert_equals_int (a_uri != NULL, TRUE);
1194 assert_equals_string (a_uri, "http://localhost/main/english-audio.m3u8");
1195 assert_equals_int (v_uri != NULL, TRUE);
1196 assert_equals_string (v_uri, "http://localhost/low/video-only.m3u8");
1197 assert_equals_int (s_uri == NULL, TRUE);
1199 /* Update the playlists */
1200 ret = gst_m3u8_update (client,
1201 g_strdup (ON_DEMAND_LOW_VIDEO_ONLY_PLAYLIST),
1202 g_strdup (ON_DEMAND_ENGLISH_PLAYLIST), NULL);
1203 assert_equals_int (ret, TRUE);
1204 assert_equals_int (g_list_length (client->selected_stream->selected_video->
1206 assert_equals_int (g_list_length (client->selected_stream->selected_audio->
1209 /* Get the first fragment */
1210 gst_m3u8_client_get_next_fragment (client, &v_frag, &a_frag, &s_frag);
1211 assert_equals_int (v_frag != NULL, TRUE);
1212 assert_equals_int (a_frag != NULL, TRUE);
1213 assert_equals_string (v_frag->name,
1214 "http://media.example.com/low/video-only-001.ts");
1215 assert_equals_string (a_frag->name,
1216 "http://media.example.com/audio/english-001.ts");
1217 g_object_unref (v_frag);
1218 g_object_unref (a_frag);
1220 /* Get the next fragment */
1221 gst_m3u8_client_get_next_fragment (client, &v_frag, &a_frag, &s_frag);
1222 assert_equals_int (v_frag != NULL, TRUE);
1223 assert_equals_int (a_frag != NULL, TRUE);
1224 assert_equals_string (v_frag->name,
1225 "http://media.example.com/low/video-only-002.ts");
1226 assert_equals_string (a_frag->name,
1227 "http://media.example.com/audio/english-002.ts");
1228 g_object_unref (v_frag);
1229 g_object_unref (a_frag);
1231 /* Switch to German audio */
1233 gst_m3u8_client_set_alternate (client, GST_M3U8_MEDIA_TYPE_AUDIO,
1235 assert_equals_int (ret, TRUE);
1236 /* Get the new uri's */
1237 gst_m3u8_client_get_current_uri (client, &v_uri, &a_uri, &s_uri);
1238 assert_equals_int (a_uri != NULL, TRUE);
1239 assert_equals_string (a_uri, "http://localhost/main/german-audio.m3u8");
1240 /* On demand so the uri does not need to be downloaded again */
1241 assert_equals_int (v_uri == NULL, TRUE);
1242 assert_equals_int (s_uri == NULL, TRUE);
1243 /* Update the new uri's */
1245 gst_m3u8_update (client,
1246 g_strdup (ON_DEMAND_LOW_VIDEO_ONLY_PLAYLIST),
1247 g_strdup (ON_DEMAND_GERMAN_PLAYLIST), NULL);
1248 assert_equals_int (ret, TRUE);
1249 gst_m3u8_client_get_next_fragment (client, &v_frag, &a_frag, &s_frag);
1250 assert_equals_int (s_frag == NULL, TRUE);
1251 assert_equals_int (v_frag != NULL, TRUE);
1252 assert_equals_int (a_frag != NULL, TRUE);
1253 assert_equals_string (a_frag->name,
1254 "http://media.example.com/audio/german-003.ts");
1255 assert_equals_string (v_frag->name,
1256 "http://media.example.com/low/video-only-003.ts");
1257 g_object_unref (v_frag);
1258 g_object_unref (a_frag);
1260 /* Switch to a higher bitrate */
1261 gst_m3u8_client_set_current (client,
1262 gst_m3u8_client_get_stream_for_bitrate (client, 260000));
1263 gst_m3u8_client_get_current_uri (client, &v_uri, &a_uri, &s_uri);
1264 assert_equals_int (a_uri != NULL, TRUE);
1265 assert_equals_string (a_uri, "http://localhost/main/german-audio.m3u8");
1266 assert_equals_int (v_uri != NULL, TRUE);
1267 assert_equals_string (v_uri, "http://localhost/mid/video-only.m3u8");
1268 assert_equals_int (s_uri == NULL, TRUE);
1270 gst_m3u8_update (client,
1271 g_strdup (ON_DEMAND_MID_VIDEO_ONLY_PLAYLIST),
1272 g_strdup (ON_DEMAND_GERMAN_PLAYLIST), NULL);
1273 assert_equals_int (ret, TRUE);
1274 gst_m3u8_client_get_next_fragment (client, &v_frag, &a_frag, &s_frag);
1275 assert_equals_int (s_frag == NULL, TRUE);
1276 assert_equals_int (a_frag != NULL, TRUE);
1277 assert_equals_int (v_frag != NULL, TRUE);
1278 assert_equals_string (a_frag->name,
1279 "http://media.example.com/audio/german-004.ts");
1280 assert_equals_string (v_frag->name,
1281 "http://media.example.com/mid/video-only-004.ts");
1282 g_object_unref (v_frag);
1283 g_object_unref (a_frag);
1285 /* Seek to the beginning */
1286 gst_m3u8_client_seek (client, 0);
1287 gst_m3u8_client_get_next_fragment (client, &v_frag, &a_frag, &s_frag);
1288 assert_equals_int (s_frag == NULL, TRUE);
1289 assert_equals_int (a_frag != NULL, TRUE);
1290 assert_equals_int (v_frag != NULL, TRUE);
1291 assert_equals_string (a_frag->name,
1292 "http://media.example.com/audio/german-001.ts");
1293 assert_equals_string (v_frag->name,
1294 "http://media.example.com/mid/video-only-001.ts");
1295 g_object_unref (v_frag);
1296 g_object_unref (a_frag);
1298 /* Select English audio again */
1300 gst_m3u8_client_set_alternate (client, GST_M3U8_MEDIA_TYPE_AUDIO,
1302 assert_equals_int (ret, TRUE);
1303 gst_m3u8_client_get_next_fragment (client, &v_frag, &a_frag, &s_frag);
1304 assert_equals_int (s_frag == NULL, TRUE);
1305 assert_equals_int (a_frag != NULL, TRUE);
1306 assert_equals_int (v_frag != NULL, TRUE);
1307 assert_equals_string (a_frag->name,
1308 "http://media.example.com/audio/english-002.ts");
1309 assert_equals_string (v_frag->name,
1310 "http://media.example.com/mid/video-only-002.ts");
1311 g_object_unref (v_frag);
1312 g_object_unref (a_frag);
1314 /* Go to the audio-only fallback */
1315 gst_m3u8_client_set_current (client,
1316 gst_m3u8_client_get_stream_for_bitrate (client, 20000));
1317 gst_m3u8_client_get_next_fragment (client, &v_frag, &a_frag, &s_frag);
1318 assert_equals_int (s_frag == NULL, TRUE);
1319 assert_equals_int (a_frag != NULL, TRUE);
1320 assert_equals_int (v_frag == NULL, TRUE);
1321 assert_equals_string (a_frag->name,
1322 "http://media.example.com/audio/english-003.ts");
1323 g_object_unref (a_frag);
1325 /* Go to mid again */
1326 gst_m3u8_client_set_current (client,
1327 gst_m3u8_client_get_stream_for_bitrate (client, 260000));
1328 gst_m3u8_client_get_next_fragment (client, &v_frag, &a_frag, &s_frag);
1329 assert_equals_int (s_frag == NULL, TRUE);
1330 assert_equals_int (a_frag != NULL, TRUE);
1331 assert_equals_int (v_frag != NULL, TRUE);
1332 assert_equals_string (a_frag->name,
1333 "http://media.example.com/audio/english-004.ts");
1334 assert_equals_string (v_frag->name,
1335 "http://media.example.com/mid/video-only-004.ts");
1336 g_object_unref (a_frag);
1337 g_object_unref (v_frag);
1340 ret = gst_m3u8_client_get_next_fragment (client, &v_frag, &a_frag, &s_frag);
1341 assert_equals_int (ret, FALSE);
1343 gst_hls_master_playlist_unref (master);
1349 GST_START_TEST (test_url_with_slash_query_param)
1351 static const gchar *MASTER_PLAYLIST = "#EXTM3U \n"
1352 "#EXT-X-VERSION:4\n"
1353 "#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=1251135, CODECS=\"avc1.42001f, mp4a.40.2\", RESOLUTION=640x352\n"
1354 "1251/media.m3u8?acl=/*1054559_h264_1500k.mp4\n";
1355 GstHLSMasterPlaylist *master;
1356 GstHLSVariantStream *stream;
1359 master = load_playlist (MASTER_PLAYLIST);
1361 assert_equals_int (g_list_length (master->variants), 1);
1362 stream = g_list_nth_data (master->variants, 0);
1363 media = stream->m3u8;
1365 assert_equals_string (media->uri,
1366 "http://localhost/1251/media.m3u8?acl=/*1054559_h264_1500k.mp4");
1367 gst_hls_master_playlist_unref (master);
1372 GST_START_TEST (test_stream_inf_tag)
1374 static const gchar *MASTER_PLAYLIST = "#EXTM3U \n"
1375 "#EXT-X-VERSION:4\n"
1376 "#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=1251135, CODECS=\"avc1.42001f, mp4a.40.2\", RESOLUTION=640x352\n"
1378 GstHLSMasterPlaylist *master;
1379 GstHLSVariantStream *stream;
1381 master = load_playlist (MASTER_PLAYLIST);
1383 assert_equals_int (g_list_length (master->variants), 1);
1384 stream = g_list_nth_data (master->variants, 0);
1386 assert_equals_int64 (stream->program_id, 1);
1387 assert_equals_int64 (stream->width, 640);
1388 assert_equals_int64 (stream->height, 352);
1389 assert_equals_int64 (stream->bandwidth, 1251135);
1390 assert_equals_string (stream->codecs, "avc1.42001f, mp4a.40.2");
1391 gst_hls_master_playlist_unref (master);
1397 hlsdemux_suite (void)
1399 Suite *s = suite_create ("hlsdemux_m3u8");
1400 TCase *tc_m3u8 = tcase_create ("m3u8client");
1402 GST_DEBUG_CATEGORY_INIT (hls_debug, "hlsdemux_m3u", 0, "hlsdemux m3u test");
1404 suite_add_tcase (s, tc_m3u8);
1405 tcase_add_test (tc_m3u8, test_load_main_playlist_invalid);
1406 tcase_add_test (tc_m3u8, test_load_main_playlist_rendition);
1407 tcase_add_test (tc_m3u8, test_load_main_playlist_variant);
1408 tcase_add_test (tc_m3u8, test_load_main_playlist_variant_with_missing_uri);
1409 tcase_add_test (tc_m3u8, test_load_windows_line_endings_variant_playlist);
1410 tcase_add_test (tc_m3u8, test_load_main_playlist_with_empty_lines);
1411 tcase_add_test (tc_m3u8, test_load_windows_main_playlist_with_empty_lines);
1412 tcase_add_test (tc_m3u8, test_on_demand_playlist);
1413 tcase_add_test (tc_m3u8, test_windows_line_endings_playlist);
1414 tcase_add_test (tc_m3u8, test_windows_empty_lines_playlist);
1415 tcase_add_test (tc_m3u8, test_empty_lines_playlist);
1416 tcase_add_test (tc_m3u8, test_live_playlist);
1417 tcase_add_test (tc_m3u8, test_live_playlist_rotated);
1418 tcase_add_test (tc_m3u8, test_playlist_with_doubles_duration);
1419 tcase_add_test (tc_m3u8, test_playlist_with_encryption);
1420 tcase_add_test (tc_m3u8, test_update_invalid_playlist);
1421 tcase_add_test (tc_m3u8, test_update_playlist);
1422 tcase_add_test (tc_m3u8, test_playlist_media_files);
1423 tcase_add_test (tc_m3u8, test_playlist_byte_range_media_files);
1424 tcase_add_test (tc_m3u8, test_get_next_fragment);
1425 tcase_add_test (tc_m3u8, test_get_duration);
1426 tcase_add_test (tc_m3u8, test_get_target_duration);
1427 tcase_add_test (tc_m3u8, test_get_stream_for_bitrate);
1429 tcase_add_test (tc_m3u8, test_seek);
1430 tcase_add_test (tc_m3u8, test_alternate_audio_playlist);
1431 tcase_add_test (tc_m3u8, test_subtitles_playlist);
1432 tcase_add_test (tc_m3u8, test_select_alternate);
1433 tcase_add_test (tc_m3u8, test_select_subs_alternate);
1434 tcase_add_test (tc_m3u8, test_simulation);
1436 tcase_add_test (tc_m3u8, test_url_with_slash_query_param);
1437 tcase_add_test (tc_m3u8, test_stream_inf_tag);
1441 GST_CHECK_MAIN (hlsdemux);