1 /*
2 * Copyright (C) 2009-2017 the xine project
3 *
4 * This file is part of xine, a free video player.
5 *
6 * xine is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * xine is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19 *
20 * demultiplexer for matroska streams: chapter handling
21 *
22 * TODO:
23 * - nested chapters
24 *
25 * Authors:
26 * Nicos Gollan <gtdev@spearhead.de>
27 */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #define LOG_MODULE "demux_matroska_chapters"
34 #define LOG_VERBOSE
35 /*
36 #define LOG
37 */
38
39 #include <xine/xine_internal.h>
40 #include <xine/xineutils.h>
41 #include <xine/demux.h>
42
43 #include "ebml.h"
44 #include "matroska.h"
45 #include "demux_matroska.h"
46
47 /* TODO: this only handles one single (title, language, country) tuple.
48 * See the header for information. */
parse_chapter_display(demux_matroska_t * this,matroska_chapter_t * chap,int level)49 static int parse_chapter_display(demux_matroska_t *this, matroska_chapter_t *chap, int level) {
50 ebml_parser_t *ebml = this->ebml;
51 int next_level = level+1;
52 char* tmp_name = NULL;
53 char* tmp_lang = NULL;
54 char* tmp_country = NULL;
55
56 while (next_level == level+1) {
57 ebml_elem_t elem;
58
59 if (!ebml_read_elem_head(ebml, &elem))
60 return 0;
61
62 switch (elem.id) {
63
64 case MATROSKA_ID_CH_STRING:
65 tmp_name = ebml_alloc_read_ascii(ebml, &elem);
66 break;
67
68 case MATROSKA_ID_CH_LANGUAGE:
69 tmp_lang = ebml_alloc_read_ascii(ebml, &elem);
70 break;
71
72 case MATROSKA_ID_CH_COUNTRY:
73 tmp_country = ebml_alloc_read_ascii(ebml, &elem);
74 break;
75
76 default:
77 lprintf("Unhandled ID (inside ChapterDisplay): 0x%x\n", elem.id);
78 if (!ebml_skip(ebml, &elem))
79 return 0;
80 }
81
82 next_level = ebml_get_next_level(ebml, &elem);
83 }
84
85 if (NULL != chap->title) {
86 chap->title = tmp_name;
87
88 free(chap->language);
89 chap->language = tmp_lang;
90
91 free(chap->country);
92 chap->country = tmp_country;
93 } else if (tmp_lang != NULL && !strcmp("eng", tmp_lang) && (chap->language == NULL || strcmp("eng", chap->language))) {
94 free(chap->title);
95 chap->title = tmp_name;
96
97 free(chap->language);
98 chap->language = tmp_lang;
99
100 free(chap->country);
101 chap->country = tmp_country;
102 } else {
103 free(tmp_name);
104 free(tmp_lang);
105 free(tmp_country);
106 }
107
108 return 1;
109 }
110
parse_chapter_atom(demux_matroska_t * this,matroska_chapter_t * chap,int level)111 static int parse_chapter_atom(demux_matroska_t *this, matroska_chapter_t *chap, int level) {
112 ebml_parser_t *ebml = this->ebml;
113 int next_level = level+1;
114 uint64_t num;
115
116 chap->time_start = 0;
117 chap->time_end = 0;
118 chap->hidden = 0;
119 chap->enabled = 1;
120
121 while (next_level == level+1) {
122 ebml_elem_t elem;
123
124 if (!ebml_read_elem_head(ebml, &elem)) {
125 lprintf("invalid head\n");
126 return 0;
127 }
128
129 switch (elem.id) {
130 case MATROSKA_ID_CH_UID:
131 if (!ebml_read_uint(ebml, &elem, &chap->uid)) {
132 lprintf("invalid UID\n");
133 return 0;
134 }
135 break;
136
137 case MATROSKA_ID_CH_TIMESTART:
138 if (!ebml_read_uint(ebml, &elem, &chap->time_start)) {
139 lprintf("invalid start time\n");
140 return 0;
141 }
142 /* convert to xine timing: Matroska timestamps are in nanoseconds,
143 * xine's PTS are in 1/90,000s */
144 chap->time_start /= 100000;
145 chap->time_start *= 9;
146 break;
147
148 case MATROSKA_ID_CH_TIMEEND:
149 if (!ebml_read_uint(ebml, &elem, &chap->time_end)) {
150 lprintf("invalid end time\n");
151 return 0;
152 }
153 /* convert to xine timing */
154 chap->time_end /= 100000;
155 chap->time_end *= 9;
156 break;
157
158 case MATROSKA_ID_CH_DISPLAY:
159 if (!ebml_read_master(ebml, &elem))
160 return 0;
161
162 lprintf("ChapterDisplay\n");
163 if(!parse_chapter_display(this, chap, level+1)) {
164 lprintf("invalid display information\n");
165 return 0;
166 }
167 break;
168
169 case MATROSKA_ID_CH_HIDDEN:
170 if (!ebml_read_uint(ebml, &elem, &num))
171 return 0;
172 chap->hidden = (int)num;
173 break;
174
175 case MATROSKA_ID_CH_ENABLED:
176 if (!ebml_read_uint(ebml, &elem, &num))
177 return 0;
178 chap->enabled = (int)num;
179 break;
180
181 case MATROSKA_ID_CH_ATOM: /* TODO */
182 xprintf(this->stream->xine, XINE_VERBOSITY_NONE,
183 LOG_MODULE ": Warning: Nested chapters are not supported, playback may suffer!\n");
184 if (!ebml_skip(ebml, &elem))
185 return 0;
186 break;
187
188 case MATROSKA_ID_CH_TRACK: /* TODO */
189 xprintf(this->stream->xine, XINE_VERBOSITY_NONE,
190 LOG_MODULE ": Warning: Specific track information in chapters is not supported, playback may suffer!\n");
191 if (!ebml_skip(ebml, &elem))
192 return 0;
193 break;
194
195 default:
196 lprintf("Unhandled ID (inside ChapterAtom): 0x%x\n", elem.id);
197 if (!ebml_skip(ebml, &elem))
198 return 0;
199 }
200
201 next_level = ebml_get_next_level(ebml, &elem);
202 }
203
204 /* fallback information */
205 /* FIXME: check allocations! */
206 if (NULL == chap->title) {
207 chap->title = strdup("No title");
208 }
209
210 if (NULL == chap->language) {
211 chap->language = strdup("unk");
212 }
213
214 if (NULL == chap->country) {
215 chap->country = strdup("XX");
216 }
217
218 lprintf( "Chapter 0x%" PRIx64 ": %" PRIu64 "-%" PRIu64 "(pts), %s (%s). %shidden, %senabled.\n",
219 chap->uid, chap->time_start, chap->time_end,
220 chap->title, chap->language,
221 (chap->hidden ? "" : "not "),
222 (chap->enabled ? "" : "not "));
223
224 return 1;
225 }
226
free_chapter(matroska_chapter_t * chap)227 static void free_chapter(matroska_chapter_t *chap) {
228 free(chap->title);
229 free(chap->language);
230 free(chap->country);
231
232 free(chap);
233 }
234
parse_edition_entry(demux_matroska_t * this,matroska_edition_t * ed)235 static int parse_edition_entry(demux_matroska_t *this, matroska_edition_t *ed) {
236 ebml_parser_t *ebml = this->ebml;
237 int next_level = 3;
238 uint64_t num;
239 int i;
240
241 ed->hidden = 0;
242 ed->is_default = 0;
243 ed->ordered = 0;
244
245 while (next_level == 3) {
246 ebml_elem_t elem;
247
248 if (!ebml_read_elem_head(ebml, &elem))
249 return 0;
250
251 switch (elem.id) {
252 case MATROSKA_ID_CH_ED_UID:
253 if (!ebml_read_uint(ebml, &elem, &ed->uid))
254 return 0;
255 break;
256
257 case MATROSKA_ID_CH_ED_HIDDEN:
258 if (!ebml_read_uint(ebml, &elem, &num))
259 return 0;
260 ed->hidden = (int)num;
261 break;
262
263 case MATROSKA_ID_CH_ED_DEFAULT:
264 if (!ebml_read_uint(ebml, &elem, &num))
265 return 0;
266 ed->is_default = (int)num;
267 break;
268
269 case MATROSKA_ID_CH_ED_ORDERED:
270 if (!ebml_read_uint(ebml, &elem, &num))
271 return 0;
272 ed->ordered = (int)num;
273 break;
274
275 case MATROSKA_ID_CH_ATOM:
276 {
277 matroska_chapter_t *chapter = calloc(1, sizeof(matroska_chapter_t));
278 if (NULL == chapter)
279 return 0;
280
281 lprintf("ChapterAtom\n");
282 if (!ebml_read_master(ebml, &elem)) {
283 free_chapter(chapter);
284 return 0;
285 }
286
287 if (!parse_chapter_atom(this, chapter, next_level)) {
288 free_chapter(chapter);
289 return 0;
290 }
291
292 /* resize chapters array if necessary */
293 if (ed->num_chapters >= ed->cap_chapters) {
294 matroska_chapter_t** old_chapters = ed->chapters;
295 ed->cap_chapters += 10;
296 ed->chapters = realloc(ed->chapters, ed->cap_chapters * sizeof(matroska_chapter_t*));
297
298 if (NULL == ed->chapters) {
299 ed->chapters = old_chapters;
300 ed->cap_chapters -= 10;
301 free_chapter(chapter);
302 return 0;
303 }
304 }
305
306 ed->chapters[ed->num_chapters] = chapter;
307 ++ed->num_chapters;
308
309 break;
310 }
311
312 default:
313 lprintf("Unhandled ID (inside EditionEntry): 0x%x\n", elem.id);
314 if (!ebml_skip(ebml, &elem))
315 return 0;
316 }
317
318 next_level = ebml_get_next_level(ebml, &elem);
319 }
320
321 xprintf( this->stream->xine, XINE_VERBOSITY_LOG,
322 LOG_MODULE ": Edition 0x%" PRIx64 ": %shidden, %sdefault, %sordered. %d chapters:\n",
323 ed->uid,
324 (ed->hidden ? "" : "not "),
325 (ed->is_default ? "" : "not "),
326 (ed->ordered ? "" : "not "),
327 ed->num_chapters );
328
329 for (i=0; i<ed->num_chapters; ++i) {
330 matroska_chapter_t* chap = ed->chapters[i];
331 xprintf( this->stream->xine, XINE_VERBOSITY_LOG,
332 LOG_MODULE ": Chapter %d: %" PRIu64 "-%" PRIu64 "(pts), %s (%s). %shidden, %senabled.\n",
333 i+1, chap->time_start, chap->time_end,
334 chap->title, chap->language,
335 (chap->hidden ? "" : "not "),
336 (chap->enabled ? "" : "not "));
337 }
338
339 return 1;
340 }
341
free_edition(matroska_edition_t * ed)342 static void free_edition(matroska_edition_t *ed) {
343 int i;
344
345 for(i=0; i<ed->num_chapters; ++i) {
346 free_chapter(ed->chapters[i]);
347 }
348 free(ed->chapters);
349 free(ed);
350 }
351
matroska_parse_chapters(demux_matroska_t * this)352 int matroska_parse_chapters(demux_matroska_t *this) {
353 ebml_parser_t *ebml = this->ebml;
354 int next_level = 2;
355
356 while (next_level == 2) {
357 ebml_elem_t elem;
358
359 if (!ebml_read_elem_head(ebml, &elem))
360 return 0;
361
362 switch (elem.id) {
363 case MATROSKA_ID_CH_EDITIONENTRY:
364 {
365 matroska_edition_t *edition = calloc(1, sizeof(matroska_edition_t));
366 if (NULL == edition)
367 return 0;
368
369 lprintf("EditionEntry\n");
370 if (!ebml_read_master(ebml, &elem)) {
371 free_edition(edition);
372 return 0;
373 }
374
375 if (!parse_edition_entry(this, edition)) {
376 free_edition(edition);
377 return 0;
378 }
379
380 /* resize editions array if necessary */
381 if (this->num_editions >= this->cap_editions) {
382 matroska_edition_t** old_editions = this->editions;
383 this->cap_editions += 10;
384 this->editions = realloc(this->editions, this->cap_editions * sizeof(matroska_edition_t*));
385
386 if (NULL == this->editions) {
387 this->editions = old_editions;
388 this->cap_editions -= 10;
389 free_edition(edition);
390 return 0;
391 }
392 }
393
394 this->editions[this->num_editions] = edition;
395 ++this->num_editions;
396
397 break;
398 }
399
400 default:
401 lprintf("Unhandled ID: 0x%x\n", elem.id);
402 if (!ebml_skip(ebml, &elem))
403 return 0;
404 }
405
406 next_level = ebml_get_next_level(ebml, &elem);
407 }
408
409 return 1;
410 }
411
matroska_free_editions(demux_matroska_t * this)412 void matroska_free_editions(demux_matroska_t *this) {
413 int i;
414
415 for(i=0; i<this->num_editions; ++i) {
416 free_edition(this->editions[i]);
417 }
418 free(this->editions);
419 this->num_editions = 0;
420 this->cap_editions = 0;
421 }
422
matroska_get_chapter(demux_matroska_t * this,uint64_t tc,matroska_edition_t ** ed)423 int matroska_get_chapter(demux_matroska_t *this, uint64_t tc, matroska_edition_t** ed) {
424 uint64_t block_pts = (tc * this->timecode_scale) / 100000 * 9;
425 int chapter_idx = 0;
426
427 if (this->num_editions < 1)
428 return -1;
429
430 while (chapter_idx < (*ed)->num_chapters && block_pts > (*ed)->chapters[chapter_idx]->time_start)
431 ++chapter_idx;
432
433 if (chapter_idx > 0)
434 --chapter_idx;
435
436 return chapter_idx;
437 }
438