7dd398ce2f06822b9598ddffc4f1b40f4d4902df
[platform/upstream/gstreamer.git] / tests / check / elements / hlsdemux_m3u8.c
1 /* GStreamer
2  *
3  * unit test for hlsdemux
4  *
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>
8  *
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.
13  *
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.
18  *
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.
23  */
24
25 #include <gst/check/gstcheck.h>
26
27 #undef GST_CAT_DEFAULT
28 #include "m3u8.h"
29 #include "m3u8.c"
30
31 GST_DEBUG_CATEGORY (hls_debug);
32
33 static const gchar *INVALID_PLAYLIST = "#EXTM3 UINVALID";
34
35 static const gchar *ON_DEMAND_PLAYLIST = "#EXTM3U \n\
36 #EXT-X-TARGETDURATION:10\n\
37 #EXTINF:10,Test\n\
38 http://media.example.com/001.ts\n\
39 #EXTINF:10,Test\n\
40 http://media.example.com/002.ts\n\
41 #EXTINF:10,Test\n\
42 http://media.example.com/003.ts\n\
43 #EXTINF:10,Test\n\
44 http://media.example.com/004.ts\n\
45 #EXT-X-ENDLIST";
46
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\
55 #EXTINF:9.92,Test\n\
56 http://media.example.com/004.ts\n\
57 #EXT-X-ENDLIST";
58
59 static const gchar *LIVE_PLAYLIST = "#EXTM3U\n\
60 #EXT-X-TARGETDURATION:8\n\
61 #EXT-X-MEDIA-SEQUENCE:2680\n\
62 \n\
63 #EXTINF:8,\n\
64 https://priv.example.com/fileSequence2680.ts\n\
65 #EXTINF:8,\n\
66 https://priv.example.com/fileSequence2681.ts\n\
67 #EXTINF:8,\n\
68 https://priv.example.com/fileSequence2682.ts\n\
69 #EXTINF:8,\n\
70 https://priv.example.com/fileSequence2683.ts";
71
72 static const gchar *LIVE_ROTATED_PLAYLIST = "#EXTM3U\n\
73 #EXT-X-TARGETDURATION:8\n\
74 #EXT-X-MEDIA-SEQUENCE:3001\n\
75 \n\
76 #EXTINF:8,\n\
77 https://priv.example.com/fileSequence3001.ts\n\
78 #EXTINF:8,\n\
79 https://priv.example.com/fileSequence3002.ts\n\
80 #EXTINF:8,\n\
81 https://priv.example.com/fileSequence3003.ts\n\
82 #EXTINF:8,\n\
83 https://priv.example.com/fileSequence3004.ts";
84
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";
94
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\
99 \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";
104
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";
114
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";
124
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\
129 #EXTINF:10,Test\n\n\
130 http://media.example.com/002.ts\n\n\
131 #EXTINF:10,Test\n\n\
132 http://media.example.com/003.ts\n\n\
133 #EXTINF:10,Test\n\n\
134 http://media.example.com/004.ts\n\n\
135 #EXT-X-ENDLIST";
136
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\
147 #EXT-X-ENDLIST";
148
149 static const gchar *BYTE_RANGES_PLAYLIST = "#EXTM3U \n\
150 #EXT-X-TARGETDURATION:40\n\
151 #EXTINF:10,Test\n\
152 #EXT-X-BYTERANGE:1000@100\n\
153 http://media.example.com/all.ts\n\
154 #EXTINF:10,Test\n\
155 #EXT-X-BYTERANGE:1000@1000\n\
156 http://media.example.com/all.ts\n\
157 #EXTINF:10,Test\n\
158 #EXT-X-BYTERANGE:1000@2000\n\
159 http://media.example.com/all.ts\n\
160 #EXTINF:10,Test\n\
161 #EXT-X-BYTERANGE:1000@3000\n\
162 http://media.example.com/all.ts\n\
163 #EXT-X-ENDLIST";
164
165 static const gchar *BYTE_RANGES_ACC_OFFSET_PLAYLIST = "#EXTM3U \n\
166 #EXT-X-TARGETDURATION:40\n\
167 #EXTINF:10,Test\n\
168 #EXT-X-BYTERANGE:1000\n\
169 http://media.example.com/all.ts\n\
170 #EXTINF:10,Test\n\
171 #EXT-X-BYTERANGE:1000\n\
172 http://media.example.com/all.ts\n\
173 #EXTINF:10,Test\n\
174 #EXT-X-BYTERANGE:1000\n\
175 http://media.example.com/all.ts\n\
176 #EXTINF:10,Test\n\
177 #EXT-X-BYTERANGE:1000\n\
178 http://media.example.com/all.ts\n\
179 #EXT-X-ENDLIST";
180
181 #if 0
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";
199
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";
217
218 static const gchar *ON_DEMAND_LOW_VIDEO_ONLY_PLAYLIST = "#EXTM3U \n\
219 #EXT-X-TARGETDURATION:10\n\
220 #EXTINF:10,Test\n\
221 http://media.example.com/low/video-only-001.ts\n\
222 #EXTINF:10,Test\n\
223 http://media.example.com/low/video-only-002.ts\n\
224 #EXTINF:10,Test\n\
225 http://media.example.com/low/video-only-003.ts\n\
226 #EXTINF:10,Test\n\
227 http://media.example.com/low/video-only-004.ts\n\
228 #EXT-X-ENDLIST";
229
230 static const gchar *ON_DEMAND_MID_VIDEO_ONLY_PLAYLIST = "#EXTM3U \n\
231 #EXT-X-TARGETDURATION:10\n\
232 #EXTINF:10,Test\n\
233 http://media.example.com/mid/video-only-001.ts\n\
234 #EXTINF:10,Test\n\
235 http://media.example.com/mid/video-only-002.ts\n\
236 #EXTINF:10,Test\n\
237 http://media.example.com/mid/video-only-003.ts\n\
238 #EXTINF:10,Test\n\
239 http://media.example.com/mid/video-only-004.ts\n\
240 #EXT-X-ENDLIST";
241
242 static const gchar *ON_DEMAND_ENGLISH_PLAYLIST = "#EXTM3U \n\
243 #EXT-X-TARGETDURATION:10\n\
244 #EXTINF:10,Test\n\
245 http://media.example.com/audio/english-001.ts\n\
246 #EXTINF:10,Test\n\
247 http://media.example.com/audio/english-002.ts\n\
248 #EXTINF:10,Test\n\
249 http://media.example.com/audio/english-003.ts\n\
250 #EXTINF:10,Test\n\
251 http://media.example.com/audio/english-004.ts\n\
252 #EXT-X-ENDLIST";
253
254 static const gchar *ON_DEMAND_GERMAN_PLAYLIST = "#EXTM3U \n\
255 #EXT-X-TARGETDURATION:10\n\
256 #EXTINF:10,Test\n\
257 http://media.example.com/audio/german-001.ts\n\
258 #EXTINF:10,Test\n\
259 http://media.example.com/audio/german-002.ts\n\
260 #EXTINF:10,Test\n\
261 http://media.example.com/audio/german-003.ts\n\
262 #EXTINF:10,Test\n\
263 http://media.example.com/audio/german-004.ts\n\
264 #EXT-X-ENDLIST";
265
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";
282 #endif
283
284 static const gchar *AES_128_ENCRYPTED_PLAYLIST = "#EXTM3U \n\
285 #EXT-X-TARGETDURATION:10\n\
286 #EXTINF:10,Test\n\
287 http://media.example.com/mid/video-only-001.ts\n\
288 #EXT-X-KEY:METHOD=NONE\n\
289 #EXTINF:10,Test\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\
292 #EXTINF:10,Test\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\
295 #EXTINF:10,Test\n\
296 http://media.example.com/mid/video-only-004.ts\n\
297 #EXTINF:10,Test\n\
298 http://media.example.com/mid/video-only-005.ts\n\
299 #EXT-X-ENDLIST";
300
301 static const gchar *WINDOWS_LINE_ENDINGS_PLAYLIST = "#EXTM3U \r\n\
302 #EXT-X-TARGETDURATION:10\r\n\
303 #EXTINF:10,Test\r\n\
304 http://media.example.com/001.ts\r\n\
305 #EXTINF:10,Test\r\n\
306 http://media.example.com/002.ts\r\n\
307 #EXTINF:10,Test\r\n\
308 http://media.example.com/003.ts\r\n\
309 #EXTINF:10,Test\r\n\
310 http://media.example.com/004.ts\r\n\
311 #EXT-X-ENDLIST";
312
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";
322
323 static const gchar *MAP_TAG_PLAYLIST = "#EXTM3U \n\
324 #EXT-X-VERSION:7\n\
325 #EXT-X-MAP:URI=\"init1.mp4\",BYTERANGE=\"50@50\"\n\
326 #EXTINF:6.00000,\n\
327 #EXT-X-BYTERANGE:100@50\n\
328 main.mp4\n\
329 #EXTINF:6.00000,\n\
330 #EXT-X-BYTERANGE:100@150\n\
331 main.mp4\n\
332 #EXT-X-MAP:URI=\"init2.mp4\"\n\
333 #EXTINF:6.00000,\n\
334 #EXT-X-BYTERANGE:100@300\n\
335 main.mp4\n\
336 #EXT-X-ENDLIST";
337
338 static GstHLSMasterPlaylist *
339 load_playlist (const gchar * data)
340 {
341   GstHLSMasterPlaylist *master;
342
343   master = gst_hls_master_playlist_new_from_data (g_strdup (data),
344       "http://localhost/test.m3u8");
345   fail_unless (master != NULL);
346
347   return master;
348 }
349
350 GST_START_TEST (test_load_main_playlist_invalid)
351 {
352   GstHLSMasterPlaylist *master;
353
354   master =
355       gst_hls_master_playlist_new_from_data (g_strdup (INVALID_PLAYLIST), NULL);
356   fail_unless (master == NULL);
357 }
358
359 GST_END_TEST;
360
361 GST_START_TEST (test_load_main_playlist_rendition)
362 {
363   GstHLSMasterPlaylist *master;
364   GstHLSVariantStream *variant;
365
366   master = load_playlist (ON_DEMAND_PLAYLIST);
367   variant = master->default_variant;
368
369   assert_equals_int (g_list_length (variant->m3u8->files), 4);
370   assert_equals_int (master->version, 0);
371
372   gst_hls_master_playlist_unref (master);
373 }
374
375 GST_END_TEST;
376
377 static void
378 do_test_load_main_playlist_variant (const gchar * playlist)
379 {
380   GstHLSMasterPlaylist *master;
381   GstHLSVariantStream *stream;
382   GList *tmp;
383
384   master = gst_hls_master_playlist_new_from_data (g_strdup (playlist), NULL);
385   fail_unless (master != NULL);
386
387   assert_equals_int (g_list_length (master->variants), 4);
388
389   /* Audio-Only */
390   tmp = g_list_first (master->variants);
391   stream = tmp->data;
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");
396
397   /* Low */
398   tmp = g_list_next (tmp);
399   stream = tmp->data;
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");
403
404   /* Mid */
405   tmp = g_list_next (tmp);
406   stream = tmp->data;
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");
410
411   /* High */
412   tmp = g_list_next (tmp);
413   stream = tmp->data;
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");
417
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);
421
422   gst_hls_master_playlist_unref (master);
423 }
424
425 GST_START_TEST (test_load_main_playlist_variant)
426 {
427   do_test_load_main_playlist_variant (VARIANT_PLAYLIST);
428 }
429
430 GST_END_TEST;
431
432 GST_START_TEST (test_load_main_playlist_variant_with_missing_uri)
433 {
434   GstHLSMasterPlaylist *master;
435
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);
439 }
440
441 GST_END_TEST;
442
443 GST_START_TEST (test_load_windows_line_endings_variant_playlist)
444 {
445   do_test_load_main_playlist_variant (WINDOWS_LINE_ENDINGS_VARIANT_PLAYLIST);
446 }
447
448 GST_END_TEST;
449
450 GST_START_TEST (test_load_main_playlist_with_empty_lines)
451 {
452   do_test_load_main_playlist_variant (EMPTY_LINES_VARIANT_PLAYLIST);
453 }
454
455 GST_END_TEST;
456
457 GST_START_TEST (test_load_windows_main_playlist_with_empty_lines)
458 {
459   do_test_load_main_playlist_variant (WINDOWS_EMPTY_LINES_VARIANT_PLAYLIST);
460 }
461
462 GST_END_TEST;
463
464 static void
465 check_on_demand_playlist (const gchar * data)
466 {
467   GstHLSMasterPlaylist *master;
468   GstM3U8 *pl;
469   GstM3U8MediaFile *file;
470
471   master = load_playlist (data);
472   pl = master->default_variant->m3u8;
473
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);
488
489   gst_hls_master_playlist_unref (master);
490 }
491
492 GST_START_TEST (test_on_demand_playlist)
493 {
494   check_on_demand_playlist (ON_DEMAND_PLAYLIST);
495 }
496
497 GST_END_TEST;
498
499 GST_START_TEST (test_windows_line_endings_playlist)
500 {
501   check_on_demand_playlist (WINDOWS_LINE_ENDINGS_PLAYLIST);
502 }
503
504 GST_END_TEST;
505
506 GST_START_TEST (test_empty_lines_playlist)
507 {
508   check_on_demand_playlist (EMPTY_LINES_PLAYLIST);
509 }
510
511 GST_END_TEST;
512
513 GST_START_TEST (test_windows_empty_lines_playlist)
514 {
515   check_on_demand_playlist (WINDOWS_EMPTY_LINES_PLAYLIST);
516 }
517
518 GST_END_TEST;
519
520 GST_START_TEST (test_live_playlist)
521 {
522   GstHLSMasterPlaylist *master;
523   GstM3U8 *pl;
524   GstM3U8MediaFile *file;
525   gint64 start = -1;
526   gint64 stop = -1;
527
528   master = load_playlist (LIVE_PLAYLIST);
529
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);
549
550   gst_hls_master_playlist_unref (master);
551 }
552
553 GST_END_TEST;
554
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)
559 {
560   GstHLSMasterPlaylist *master;
561   GstM3U8 *pl;
562   GstM3U8MediaFile *file;
563   gboolean ret;
564
565   master = load_playlist (LIVE_PLAYLIST);
566   pl = master->default_variant->m3u8;
567
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);
572
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);
578
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);
584
585   gst_hls_master_playlist_unref (master);
586 }
587
588 GST_END_TEST;
589
590 GST_START_TEST (test_playlist_with_doubles_duration)
591 {
592   GstHLSMasterPlaylist *master;
593   GstM3U8 *pl;
594   GstM3U8MediaFile *file;
595   gint64 start = -1;
596   gint64 stop = -1;
597
598   master = load_playlist (DOUBLES_PLAYLIST);
599   pl = master->default_variant->m3u8;
600
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);
614
615   gst_hls_master_playlist_unref (master);
616 }
617
618 GST_END_TEST;
619
620 GST_START_TEST (test_playlist_with_encryption)
621 {
622   GstHLSMasterPlaylist *master;
623   GstM3U8 *pl;
624   GstM3U8MediaFile *file;
625   guint8 iv1[16] = { 0, };
626   guint8 iv2[16] = { 0, };
627
628   iv1[15] = 1;
629   iv2[15] = 2;
630
631   master = load_playlist (AES_128_ENCRYPTED_PLAYLIST);
632   pl = master->default_variant->m3u8;
633
634   assert_equals_int (g_list_length (pl->files), 5);
635
636   /* Check all media segments */
637   file = GST_M3U8_MEDIA_FILE (g_list_nth_data (pl->files, 0));
638   fail_unless (file->key == NULL);
639
640   file = GST_M3U8_MEDIA_FILE (g_list_nth_data (pl->files, 1));
641   fail_unless (file->key == NULL);
642
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);
647
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);
652
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);
657
658   gst_hls_master_playlist_unref (master);
659 }
660
661 GST_END_TEST;
662
663
664 GST_START_TEST (test_update_invalid_playlist)
665 {
666   GstHLSMasterPlaylist *master;
667   GstM3U8 *pl;
668   gboolean ret;
669
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);
676
677   gst_hls_master_playlist_unref (master);
678 }
679
680 GST_END_TEST;
681
682 GST_START_TEST (test_update_playlist)
683 {
684   GstHLSMasterPlaylist *master;
685   GstM3U8 *pl;
686   gchar *live_pl;
687   gboolean ret;
688
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);
697
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);
713 }
714
715 GST_END_TEST;
716
717 GST_START_TEST (test_playlist_media_files)
718 {
719   GstHLSMasterPlaylist *master;
720   GstM3U8 *pl;
721   GstM3U8MediaFile *file;
722
723   master = load_playlist (ON_DEMAND_PLAYLIST);
724   pl = master->default_variant->m3u8;
725
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");
736
737   gst_hls_master_playlist_unref (master);
738 }
739
740 GST_END_TEST;
741
742 GST_START_TEST (test_playlist_byte_range_media_files)
743 {
744   GstHLSMasterPlaylist *master;
745   GstM3U8 *pl;
746   GstM3U8MediaFile *file;
747
748   master = load_playlist (BYTE_RANGES_PLAYLIST);
749   pl = master->default_variant->m3u8;
750
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);
767
768   gst_hls_master_playlist_unref (master);
769
770
771   master = load_playlist (BYTE_RANGES_ACC_OFFSET_PLAYLIST);
772   pl = master->default_variant->m3u8;
773
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);
790
791   gst_hls_master_playlist_unref (master);
792 }
793
794 GST_END_TEST;
795
796 GST_START_TEST (test_get_next_fragment)
797 {
798   GstHLSMasterPlaylist *master;
799   GstM3U8 *pl;
800   GstM3U8MediaFile *mf;
801   gboolean discontinous;
802   GstClockTime timestamp;
803
804   master = load_playlist (BYTE_RANGES_PLAYLIST);
805   pl = master->default_variant->m3u8;
806
807   /* Check the next fragment */
808   mf = gst_m3u8_get_next_fragment (pl, TRUE, &timestamp, &discontinous);
809   fail_unless (mf != NULL);
810   assert_equals_int (discontinous, 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);
817
818   gst_m3u8_advance_fragment (pl, TRUE);
819
820   /* Check next media segments */
821   mf = gst_m3u8_get_next_fragment (pl, TRUE, &timestamp, &discontinous);
822   fail_unless (mf != NULL);
823   assert_equals_int (discontinous, 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);
830
831   gst_m3u8_advance_fragment (pl, TRUE);
832
833   /* Check next media segments */
834   mf = gst_m3u8_get_next_fragment (pl, TRUE, &timestamp, &discontinous);
835   assert_equals_int (discontinous, 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);
842
843   gst_hls_master_playlist_unref (master);
844 }
845
846 GST_END_TEST;
847
848 GST_START_TEST (test_get_duration)
849 {
850   GstHLSMasterPlaylist *master;
851   GstM3U8 *pl;
852
853   /* Test duration for on-demand playlists */
854   master = load_playlist (ON_DEMAND_PLAYLIST);
855   pl = master->default_variant->m3u8;
856
857   assert_equals_uint64 (gst_m3u8_get_duration (pl), 40 * GST_SECOND);
858   gst_hls_master_playlist_unref (master);
859
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);
864
865   gst_hls_master_playlist_unref (master);
866 }
867
868 GST_END_TEST;
869
870 GST_START_TEST (test_get_target_duration)
871 {
872   GstHLSMasterPlaylist *master;
873   GstM3U8 *pl;
874
875   master = load_playlist (ON_DEMAND_PLAYLIST);
876   pl = master->default_variant->m3u8;
877
878   assert_equals_uint64 (gst_m3u8_get_target_duration (pl), 10 * GST_SECOND);
879
880   gst_hls_master_playlist_unref (master);
881 }
882
883 GST_END_TEST;
884
885
886 GST_START_TEST (test_get_stream_for_bitrate)
887 {
888   GstHLSMasterPlaylist *master;
889   GstHLSVariantStream *stream;
890
891   master = load_playlist (VARIANT_PLAYLIST);
892   stream = gst_hls_master_playlist_get_variant_for_bitrate (master, NULL, 0);
893
894   assert_equals_int (stream->bandwidth, 65000);
895
896   stream =
897       gst_hls_master_playlist_get_variant_for_bitrate (master, NULL,
898       G_MAXINT32);
899   assert_equals_int (stream->bandwidth, 768000);
900   stream =
901       gst_hls_master_playlist_get_variant_for_bitrate (master, NULL, 300000);
902   assert_equals_int (stream->bandwidth, 256000);
903   stream =
904       gst_hls_master_playlist_get_variant_for_bitrate (master, NULL, 500000);
905   assert_equals_int (stream->bandwidth, 256000);
906   stream =
907       gst_hls_master_playlist_get_variant_for_bitrate (master, NULL, 255000);
908   assert_equals_int (stream->bandwidth, 128000);
909
910   gst_hls_master_playlist_unref (master);
911 }
912
913 GST_END_TEST;
914
915 #if 0
916 static void
917 do_test_seek (GstM3U8Client * client, guint seek_pos, gint pos)
918 {
919   GstClockTime cur_pos;
920   gboolean ret;
921
922   ret = gst_m3u8_client_seek (client, seek_pos * GST_SECOND);
923   if (pos == -1) {
924     assert_equals_int (ret, FALSE);
925     return;
926   }
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);
930 }
931
932 GST_START_TEST (test_seek)
933 {
934   GstM3U8Client *client;
935
936   master = load_playlist (ON_DEMAND_PLAYLIST);
937
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);
943
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);
949
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);
954
955   /* Test seeks on a live playlist */
956   master = load_playlist (LIVE_PLAYLIST);
957   do_test_seek (client, 0, 0);
958
959   do_test_seek (client, 8, 8);
960   do_test_seek (client, 20, 16);
961   do_test_seek (client, 30, 24);
962
963   do_test_seek (client, 3000, -1);
964   gst_hls_master_playlist_unref (master);
965 }
966
967 GST_END_TEST;
968
969 GST_START_TEST (test_alternate_audio_playlist)
970 {
971   GstM3U8Client *client;
972   GstM3U8Media *media;
973   GList *alternates;
974
975   master = load_playlist (ALTERNATE_AUDIO_PLAYLIST);
976
977   assert_equals_int (g_list_length (client->main->streams), 4);
978   assert_equals_int (g_hash_table_size (client->main->video_rendition_groups),
979       0);
980   assert_equals_int (g_hash_table_size (client->main->audio_rendition_groups),
981       1);
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);
986
987   alternates =
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);
999
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");
1010
1011   gst_hls_master_playlist_unref (master);
1012 }
1013
1014 GST_END_TEST;
1015
1016 GST_START_TEST (test_subtitles_playlist)
1017 {
1018   GstM3U8Client *client;
1019   GstM3U8Media *media;
1020   GList *alternates;
1021
1022   master = load_playlist (SUBTITLES_PLAYLIST);
1023
1024   assert_equals_int (g_list_length (client->main->streams), 3);
1025   assert_equals_int (g_hash_table_size (client->main->video_rendition_groups),
1026       0);
1027   assert_equals_int (g_hash_table_size (client->main->audio_rendition_groups),
1028       0);
1029   assert_equals_int (g_hash_table_size (client->main->subtt_rendition_groups),
1030       1);
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);
1037
1038   alternates =
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);
1050
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");
1058
1059   gst_hls_master_playlist_unref (master);
1060 }
1061
1062 GST_END_TEST;
1063 GST_START_TEST (test_select_subs_alternate)
1064 {
1065   GstM3U8Client *client;
1066   const gchar *a_uri, *v_uri, *s_uri;
1067   gboolean ret;
1068
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");
1079
1080   ret =
1081       gst_m3u8_client_set_alternate (client, GST_M3U8_MEDIA_TYPE_SUBTITLES,
1082       "English");
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");
1090
1091   ret =
1092       gst_m3u8_client_set_alternate (client, GST_M3U8_MEDIA_TYPE_SUBTITLES,
1093       "Spanish");
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");
1101
1102   ret =
1103       gst_m3u8_client_set_alternate (client, GST_M3U8_MEDIA_TYPE_SUBTITLES,
1104       NULL);
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);
1111
1112   gst_hls_master_playlist_unref (master);
1113 }
1114
1115 GST_END_TEST;
1116 GST_START_TEST (test_select_alternate)
1117 {
1118   GstM3U8Client *client;
1119   const gchar *a_uri, *v_uri, *s_uri;
1120   gboolean ret;
1121
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);
1132
1133   ret =
1134       gst_m3u8_client_set_alternate (client, GST_M3U8_MEDIA_TYPE_AUDIO,
1135       "Deutsche");
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);
1143
1144   /* Check that selecting the audio-only fallback stream we only have the audio
1145    * uri */
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);
1153
1154   gst_hls_master_playlist_unref (master);
1155
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
1159    * default one */
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);
1166
1167   /* Check that selecting the audio-only fallback stream we only have the audio
1168    * uri */
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);
1176
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 */
1181   ret =
1182       gst_m3u8_client_set_alternate (client, GST_M3U8_MEDIA_TYPE_AUDIO,
1183       "Deutsche");
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);
1191
1192   gst_hls_master_playlist_unref (master);
1193 }
1194
1195 GST_END_TEST;
1196
1197 GST_START_TEST (test_simulation)
1198 {
1199   GstM3U8Client *client;
1200   const gchar *a_uri, *v_uri, *s_uri;
1201   GstFragment *a_frag, *v_frag, *s_frag;
1202   gboolean ret;
1203
1204   master = load_playlist (ALTERNATE_AUDIO_PLAYLIST);
1205   /* The default selection should be audio-only, which only has audio and not
1206    * video */
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);
1213
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->
1220           files), 4);
1221   assert_equals_int (g_list_length (client->selected_stream->selected_audio->
1222           files), 4);
1223
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);
1234
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);
1245
1246   /* Switch to German audio */
1247   ret =
1248       gst_m3u8_client_set_alternate (client, GST_M3U8_MEDIA_TYPE_AUDIO,
1249       "Deutsche");
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 */
1259   ret =
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);
1274
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);
1284   ret =
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);
1299
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);
1312
1313   /* Select English audio again */
1314   ret =
1315       gst_m3u8_client_set_alternate (client, GST_M3U8_MEDIA_TYPE_AUDIO,
1316       "English");
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);
1328
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);
1339
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);
1353
1354   /* End of stream */
1355   ret = gst_m3u8_client_get_next_fragment (client, &v_frag, &a_frag, &s_frag);
1356   assert_equals_int (ret, FALSE);
1357
1358   gst_hls_master_playlist_unref (master);
1359 }
1360
1361 GST_END_TEST;
1362 #endif
1363
1364 GST_START_TEST (test_url_with_slash_query_param)
1365 {
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;
1372   GstM3U8 *media;
1373
1374   master = load_playlist (MASTER_PLAYLIST);
1375
1376   assert_equals_int (g_list_length (master->variants), 1);
1377   stream = g_list_nth_data (master->variants, 0);
1378   media = stream->m3u8;
1379
1380   assert_equals_string (media->uri,
1381       "http://localhost/1251/media.m3u8?acl=/*1054559_h264_1500k.mp4");
1382   gst_hls_master_playlist_unref (master);
1383 }
1384
1385 GST_END_TEST;
1386
1387 GST_START_TEST (test_stream_inf_tag)
1388 {
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"
1392       "media.m3u8\n";
1393   GstHLSMasterPlaylist *master;
1394   GstHLSVariantStream *stream;
1395
1396   master = load_playlist (MASTER_PLAYLIST);
1397
1398   assert_equals_int (g_list_length (master->variants), 1);
1399   stream = g_list_nth_data (master->variants, 0);
1400
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);
1407 }
1408
1409 GST_END_TEST;
1410
1411 GST_START_TEST (test_map_tag)
1412 {
1413   GstHLSMasterPlaylist *master;
1414   GstHLSVariantStream *stream;
1415   GstM3U8 *m3u8;
1416   GList *files, *walk;
1417   GstM3U8MediaFile *seg1, *seg2, *seg3;
1418   GstM3U8InitFile *init1, *init2;
1419
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
1424    */
1425
1426   master = load_playlist (MAP_TAG_PLAYLIST);
1427
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);
1431
1432   m3u8 = stream->m3u8;
1433   fail_unless (m3u8 != NULL);
1434
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;
1440
1441     GstM3U8InitFile *init_file = file->init_file;
1442     fail_unless (init_file != NULL);
1443     fail_unless (init_file->uri != NULL);
1444   }
1445
1446   seg1 = g_list_nth_data (files, 0);
1447   seg2 = g_list_nth_data (files, 1);
1448   seg3 = g_list_nth_data (files, 2);
1449
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);
1453
1454   fail_unless (seg2->init_file != seg3->init_file);
1455   assert_equals_int (seg3->init_file->ref_count, 1);
1456
1457   init1 = seg1->init_file;
1458   init2 = seg3->init_file;
1459
1460   fail_unless (g_strcmp0 (init1->uri, init2->uri));
1461   assert_equals_int (init1->offset, 50);
1462   assert_equals_int (init1->size, 50);
1463
1464   assert_equals_int (init2->offset, 0);
1465   assert_equals_int (init2->size, -1);
1466
1467   gst_hls_master_playlist_unref (master);
1468 }
1469
1470 GST_END_TEST;
1471
1472 static Suite *
1473 hlsdemux_suite (void)
1474 {
1475   Suite *s = suite_create ("hlsdemux_m3u8");
1476   TCase *tc_m3u8 = tcase_create ("m3u8client");
1477
1478   GST_DEBUG_CATEGORY_INIT (hls_debug, "hlsdemux_m3u", 0, "hlsdemux m3u test");
1479
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);
1504 #if 0
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);
1511 #endif
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);
1515   return s;
1516 }
1517
1518 GST_CHECK_MAIN (hlsdemux);