1 /*
2 * This file is part of libbluray
3 * Copyright (C) 2010-2013 Petri Hintukainen <phintuka@users.sourceforge.net>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library. If not, see
17 * <http://www.gnu.org/licenses/>.
18 */
19
20 #if HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "graphics_processor.h"
25
26 #include "ig_decode.h"
27 #include "pg_decode.h"
28 #include "textst_decode.h"
29 #include "pes_buffer.h"
30 #include "m2ts_demux.h"
31
32 #include "util/macro.h"
33 #include "util/logging.h"
34 #include "util/bits.h"
35
36 #include <string.h>
37 #include <stdlib.h>
38 #include <inttypes.h>
39
40 #define GP_TRACE(...) do {} while (0)
41
42
43 /*
44 * segment types
45 */
46
47 typedef enum {
48 PGS_PALETTE = 0x14,
49 PGS_OBJECT = 0x15,
50 PGS_PG_COMPOSITION = 0x16,
51 PGS_WINDOW = 0x17,
52 PGS_IG_COMPOSITION = 0x18,
53 PGS_END_OF_DISPLAY = 0x80,
54 /* Text subtitles */
55 TGS_DIALOG_STYLE = 0x81,
56 TGS_DIALOG_PRESENTATION = 0x82,
57 } pgs_segment_type_e;
58
59 /*
60 * PG_DISPLAY_SET
61 */
62
_free_dialogs(PG_DISPLAY_SET * s)63 static void _free_dialogs(PG_DISPLAY_SET *s)
64 {
65 unsigned ii;
66
67 textst_free_dialog_style(&s->style);
68
69 for (ii = 0; ii < s->num_dialog; ii++) {
70 textst_clean_dialog_presentation(&s->dialog[ii]);
71 }
72 X_FREE(s->dialog);
73
74 s->num_dialog = 0;
75 s->total_dialog = 0;
76 }
77
pg_display_set_free(PG_DISPLAY_SET ** s)78 void pg_display_set_free(PG_DISPLAY_SET **s)
79 {
80 if (s && *s) {
81 unsigned ii;
82 for (ii = 0; ii < (*s)->num_object; ii++) {
83 pg_clean_object(&(*s)->object[ii]);
84 }
85 ig_free_interactive(&(*s)->ics);
86
87 X_FREE((*s)->window);
88 X_FREE((*s)->object);
89 X_FREE((*s)->palette);
90
91 _free_dialogs(*s);
92
93 X_FREE(*s);
94 }
95 }
96
97 /*
98 * segment handling
99 */
100
_find_segment_by_idv(PES_BUFFER * p,uint8_t seg_type,unsigned idv_pos,uint8_t * idv,unsigned idv_len)101 static PES_BUFFER *_find_segment_by_idv(PES_BUFFER *p,
102 uint8_t seg_type, unsigned idv_pos,
103 uint8_t *idv, unsigned idv_len)
104 {
105 while (p && (p->buf[0] != seg_type || memcmp(p->buf + idv_pos, idv, idv_len))) {
106 p = p->next;
107 }
108 return p;
109 }
110
_join_fragments(PES_BUFFER * p1,PES_BUFFER * p2,int data_pos)111 static void _join_fragments(PES_BUFFER *p1, PES_BUFFER *p2, int data_pos)
112 {
113 unsigned new_len = p1->len + p2->len - data_pos;
114
115 if (p1->size < new_len) {
116 uint8_t *tmp;
117 p1->size = new_len + 1;
118 tmp = realloc(p1->buf, p1->size);
119 if (!tmp) {
120 BD_DEBUG(DBG_DECODE | DBG_CRIT, "out of memory\n");
121 p1->size = 0;
122 p1->len = 0;
123 return;
124 }
125 p1->buf = tmp;
126 }
127
128 memcpy(p1->buf + p1->len, p2->buf + data_pos, p2->len - data_pos);
129 p1->len = new_len;
130 p2->len = 0;
131 }
132
133 /* return 1 if segment is ready for decoding, 0 if more data is needed */
_join_segment_fragments(struct pes_buffer_s * p)134 static int _join_segment_fragments(struct pes_buffer_s *p)
135 {
136 uint8_t type;
137 unsigned id_pos = 0, id_len = 3, sd_pos = 6, data_pos = 0;
138
139 if (p->len < 3) {
140 return 1;
141 }
142
143 /* check segment type */
144
145 type = p->buf[0];
146 if (type == PGS_OBJECT) {
147 id_pos = 3;
148 sd_pos = 6;
149 data_pos = 7;
150 }
151 else if (type == PGS_IG_COMPOSITION) {
152 id_pos = 8;
153 sd_pos = 11;
154 data_pos = 12;
155 }
156 else {
157 return 1;
158 }
159
160 /* check sequence descriptor - is segment complete ? */
161
162 BD_PG_SEQUENCE_DESCRIPTOR sd;
163 BITBUFFER bb;
164 bb_init(&bb, p->buf + sd_pos, 3);
165 pg_decode_sequence_descriptor(&bb, &sd);
166
167 if (sd.last_in_seq) {
168 return 1;
169 }
170 if (!sd.first_in_seq) {
171 return 1;
172 }
173
174 /* find next fragment(s) */
175
176 PES_BUFFER *next;
177 while (NULL != (next = _find_segment_by_idv(p->next, p->buf[0], id_pos, p->buf + id_pos, id_len))) {
178
179 bb_init(&bb, next->buf + sd_pos, 3);
180 pg_decode_sequence_descriptor(&bb, &sd);
181
182 _join_fragments(p, next, data_pos);
183
184 pes_buffer_remove(&p, next);
185
186 if (sd.last_in_seq) {
187 /* set first + last in sequence descriptor */
188 p->buf[sd_pos] = 0xff;
189 return 1;
190 }
191 }
192
193 /* do not delay decoding if there are other segments queued (missing fragment ?) */
194 return !!p->next;
195 }
196
197 /*
198 * segment decoding
199 */
200
_decode_wds(PG_DISPLAY_SET * s,BITBUFFER * bb,PES_BUFFER * p)201 static int _decode_wds(PG_DISPLAY_SET *s, BITBUFFER *bb, PES_BUFFER *p)
202 {
203 BD_PG_WINDOWS w;
204 memset(&w, 0, sizeof(w));
205
206 (void)p;
207
208 if (!s->decoding) {
209 BD_DEBUG(DBG_DECODE, "skipping orphan window definition segment\n");
210 return 0;
211 }
212
213 s->num_window = 0;
214
215 if (pg_decode_windows(bb, &w)) {
216 X_FREE(s->window);
217 s->window = w.window;
218 s->num_window = w.num_windows;
219 return 1;
220 }
221
222 pg_clean_windows(&w);
223
224 return 0;
225 }
226
_decode_ods(PG_DISPLAY_SET * s,BITBUFFER * bb,PES_BUFFER * p)227 static int _decode_ods(PG_DISPLAY_SET *s, BITBUFFER *bb, PES_BUFFER *p)
228 {
229 if (!s->decoding) {
230 BD_DEBUG(DBG_DECODE, "skipping orphan object definition segment\n");
231 return 0;
232 }
233
234 /* search for object to be updated */
235
236 if (s->object) {
237 BITBUFFER bb_tmp = *bb;
238 uint16_t id = bb_read(&bb_tmp, 16);
239 unsigned ii;
240
241 for (ii = 0; ii < s->num_object; ii++) {
242 if (s->object[ii].id == id) {
243 if (pg_decode_object(bb, &s->object[ii])) {
244 s->object[ii].pts = p->pts;
245 return 1;
246 }
247 pg_clean_object(&s->object[ii]);
248 return 0;
249 }
250 }
251 }
252
253 /* add and decode new object */
254
255 BD_PG_OBJECT *tmp = realloc(s->object, sizeof(s->object[0]) * (s->num_object + 1));
256 if (!tmp) {
257 BD_DEBUG(DBG_DECODE | DBG_CRIT, "out of memory\n");
258 return 0;
259 }
260 s->object = tmp;
261 memset(&s->object[s->num_object], 0, sizeof(s->object[0]));
262
263 if (pg_decode_object(bb, &s->object[s->num_object])) {
264 s->object[s->num_object].pts = p->pts;
265 s->num_object++;
266 return 1;
267 }
268
269 pg_clean_object(&s->object[s->num_object]);
270
271 return 0;
272 }
273
_decode_pds(PG_DISPLAY_SET * s,BITBUFFER * bb,PES_BUFFER * p)274 static int _decode_pds(PG_DISPLAY_SET *s, BITBUFFER *bb, PES_BUFFER *p)
275 {
276 if (!s->decoding) {
277 BD_DEBUG(DBG_DECODE, "skipping orphan palette definition segment\n");
278 return 0;
279 }
280
281 /* search for palette to be updated */
282
283 if (s->palette) {
284 BITBUFFER bb_tmp = *bb;
285 uint8_t id = bb_read(&bb_tmp, 8);
286 unsigned ii;
287
288 for (ii = 0; ii < s->num_palette; ii++) {
289 if (s->palette[ii].id == id) {
290 int rr;
291 if ( (s->ics && s->ics->composition_descriptor.state == 0) ||
292 (s->pcs && s->pcs->composition_descriptor.state == 0)) {
293 /* 8.8.3.1.1 */
294 rr = pg_decode_palette_update(bb, &s->palette[ii]);
295 } else {
296 rr = pg_decode_palette(bb, &s->palette[ii]);
297 }
298 if (rr) {
299 s->palette[ii].pts = p->pts;
300 return 1;
301 }
302 return 0;
303 }
304 }
305 }
306
307 /* add and decode new palette */
308
309 BD_PG_PALETTE *tmp = realloc(s->palette, sizeof(s->palette[0]) * (s->num_palette + 1));
310 if (!tmp) {
311 BD_DEBUG(DBG_DECODE | DBG_CRIT, "out of memory\n");
312 return 0;
313 }
314 s->palette = tmp;
315 memset(&s->palette[s->num_palette], 0, sizeof(s->palette[0]));
316
317 if (pg_decode_palette(bb, &s->palette[s->num_palette])) {
318 s->palette[s->num_palette].pts = p->pts;
319 s->num_palette++;
320 return 1;
321 }
322
323 return 0;
324 }
325
_check_epoch_start(PG_DISPLAY_SET * s)326 static void _check_epoch_start(PG_DISPLAY_SET *s)
327 {
328 if ((s->pcs && s->pcs->composition_descriptor.state == 2) ||
329 (s->ics && s->ics->composition_descriptor.state == 2)) {
330 /* epoch start, drop all cached data */
331
332 unsigned ii;
333 for (ii = 0; ii < s->num_object; ii++) {
334 pg_clean_object(&s->object[ii]);
335 }
336
337 s->num_palette = 0;
338 s->num_window = 0;
339 s->num_object = 0;
340
341 s->epoch_start = 1;
342
343 } else {
344 s->epoch_start = 0;
345 }
346 }
347
_decode_pcs(PG_DISPLAY_SET * s,BITBUFFER * bb,PES_BUFFER * p)348 static int _decode_pcs(PG_DISPLAY_SET *s, BITBUFFER *bb, PES_BUFFER *p)
349 {
350 if (s->complete) {
351 BD_DEBUG(DBG_DECODE | DBG_CRIT, "ERROR: updating complete (non-consumed) PG composition\n");
352 s->complete = 0;
353 }
354
355 pg_free_composition(&s->pcs);
356 s->pcs = calloc(1, sizeof(*s->pcs));
357 if (!s->pcs) {
358 BD_DEBUG(DBG_DECODE | DBG_CRIT, "out of memory\n");
359 return 0;
360 }
361
362 if (!pg_decode_composition(bb, s->pcs)) {
363 pg_free_composition(&s->pcs);
364 return 0;
365 }
366
367 s->pcs->pts = p->pts;
368 s->valid_pts = p->pts;
369
370 _check_epoch_start(s);
371
372 s->decoding = 1;
373
374 return 1;
375 }
376
_decode_ics(PG_DISPLAY_SET * s,BITBUFFER * bb,PES_BUFFER * p)377 static int _decode_ics(PG_DISPLAY_SET *s, BITBUFFER *bb, PES_BUFFER *p)
378 {
379 if (s->complete) {
380 BD_DEBUG(DBG_DECODE | DBG_CRIT, "ERROR: updating complete (non-consumed) IG composition\n");
381 s->complete = 0;
382 }
383
384 ig_free_interactive(&s->ics);
385 s->ics = calloc(1, sizeof(*s->ics));
386 if (!s->ics) {
387 BD_DEBUG(DBG_DECODE | DBG_CRIT, "out of memory\n");
388 return 0;
389 }
390
391 if (!ig_decode_interactive(bb, s->ics)) {
392 ig_free_interactive(&s->ics);
393 return 0;
394 }
395
396 s->ics->pts = p->pts;
397 s->valid_pts = p->pts;
398
399 _check_epoch_start(s);
400
401 s->decoding = 1;
402
403 return 1;
404 }
405
_decode_dialog_style(PG_DISPLAY_SET * s,BITBUFFER * bb)406 static int _decode_dialog_style(PG_DISPLAY_SET *s, BITBUFFER *bb)
407 {
408 _free_dialogs(s);
409
410 s->complete = 0;
411
412 s->style = calloc(1, sizeof(*s->style));
413 if (!s->style) {
414 BD_DEBUG(DBG_DECODE | DBG_CRIT, "out of memory\n");
415 return 0;
416 }
417
418 if (!textst_decode_dialog_style(bb, s->style)) {
419 textst_free_dialog_style(&s->style);
420 return 0;
421 }
422
423 if (bb->p != bb->p_end - 2 || bb->i_left != 8) {
424 BD_DEBUG(DBG_DECODE | DBG_CRIT, "_decode_dialog_style() failed: bytes in buffer %d\n", (int)(bb->p_end - bb->p));
425 textst_free_dialog_style(&s->style);
426 return 0;
427 }
428
429 s->total_dialog = bb_read(bb, 16);
430 if (s->total_dialog < 1) {
431 BD_DEBUG(DBG_DECODE | DBG_CRIT, "_decode_dialog_style(): no dialog segments\n");
432 textst_free_dialog_style(&s->style);
433 return 0;
434 }
435
436 s->dialog = calloc(s->total_dialog, sizeof(*s->dialog));
437 if (!s->dialog) {
438 BD_DEBUG(DBG_DECODE | DBG_CRIT, "out of memory\n");
439 s->total_dialog = 0;
440 return 0;
441 }
442
443 BD_DEBUG(DBG_DECODE, "_decode_dialog_style(): %d dialogs in stream\n", s->total_dialog);
444 return 1;
445 }
446
_decode_dialog_presentation(PG_DISPLAY_SET * s,BITBUFFER * bb)447 static int _decode_dialog_presentation(PG_DISPLAY_SET *s, BITBUFFER *bb)
448 {
449 if (!s->style || s->total_dialog < 1) {
450 BD_DEBUG(DBG_DECODE, "_decode_dialog_presentation() failed: style segment not decoded\n");
451 return 0;
452 }
453 if (s->num_dialog >= s->total_dialog) {
454 BD_DEBUG(DBG_DECODE | DBG_CRIT, "_decode_dialog_presentation(): unexpected dialog segment\n");
455 return 0;
456 }
457
458 if (!textst_decode_dialog_presentation(bb, &s->dialog[s->num_dialog])) {
459 textst_clean_dialog_presentation(&s->dialog[s->num_dialog]);
460 return 0;
461 }
462
463 s->num_dialog++;
464
465 if (s->num_dialog == s->total_dialog) {
466 s->complete = 1;
467 }
468
469 return 1;
470 }
471
_decode_segment(PG_DISPLAY_SET * s,PES_BUFFER * p)472 static int _decode_segment(PG_DISPLAY_SET *s, PES_BUFFER *p)
473 {
474 BITBUFFER bb;
475 bb_init(&bb, p->buf, p->len);
476
477 uint8_t type = bb_read(&bb, 8);
478 /*uint16_t len = */ bb_read(&bb, 16);
479 switch (type) {
480 case PGS_OBJECT:
481 return _decode_ods(s, &bb, p);
482
483 case PGS_PALETTE:
484 return _decode_pds(s, &bb, p);
485
486 case PGS_WINDOW:
487 return _decode_wds(s, &bb, p);
488
489 case PGS_PG_COMPOSITION:
490 return _decode_pcs(s, &bb, p);
491
492 case PGS_IG_COMPOSITION:
493 return _decode_ics(s, &bb, p);
494
495 case PGS_END_OF_DISPLAY:
496 if (!s->decoding) {
497 /* avoid duplicate initialization / presenataton */
498 BD_DEBUG(DBG_DECODE, "skipping orphan end of display segment\n");
499 return 0;
500 }
501 s->complete = 1;
502 s->decoding = 0;
503 return 1;
504
505 case TGS_DIALOG_STYLE:
506 return _decode_dialog_style(s, &bb);
507
508 case TGS_DIALOG_PRESENTATION:
509 return _decode_dialog_presentation(s, &bb);
510
511 default:
512 BD_DEBUG(DBG_DECODE | DBG_CRIT, "unknown segment type 0x%x\n", type);
513 break;
514 }
515
516 return 0;
517 }
518
519 /*
520 * mpeg-pes interface
521 */
522 #define MAX_STC_DTS_DIFF (INT64_C(90000 * 30)) /* 30 seconds */
graphics_processor_decode_pes(PG_DISPLAY_SET ** s,PES_BUFFER ** p,int64_t stc)523 static int graphics_processor_decode_pes(PG_DISPLAY_SET **s, PES_BUFFER **p, int64_t stc)
524 {
525 if (!s) {
526 return 0;
527 }
528
529 if (*s == NULL) {
530 *s = calloc(1, sizeof(PG_DISPLAY_SET));
531 if (!*s) {
532 BD_DEBUG(DBG_DECODE | DBG_CRIT, "out of memory\n");
533 return 0;
534 }
535 }
536
537 while (*p) {
538
539 /* time to decode next segment ? */
540 if (stc >= 0 && (*p)->dts > stc) {
541
542 /* filter out values that seem to be incorrect (if stc is not updated) */
543 int64_t diff = (*p)->dts - stc;
544 if (diff < MAX_STC_DTS_DIFF) {
545 GP_TRACE("Segment dts > stc (%" PRId64 " > %" PRId64 " ; diff %" PRId64 ")\n",
546 (*p)->dts, stc, diff);
547 return 0;
548 }
549 }
550
551 /* all fragments present ? */
552 if (!_join_segment_fragments(*p)) {
553 GP_TRACE("splitted segment not complete, waiting for next fragment\n");
554 return 0;
555 }
556
557 if ((*p)->len <= 2) {
558 BD_DEBUG(DBG_DECODE, "segment too short, skipping (%d bytes)\n", (*p)->len);
559 pes_buffer_next(p);
560 continue;
561 }
562
563 /* decode segment */
564
565 GP_TRACE("Decoding segment, dts %010" PRId64 " pts %010" PRId64 " len %d\n",
566 (*p)->dts, (*p)->pts, (*p)->len);
567
568 _decode_segment(*s, *p);
569
570 pes_buffer_next(p);
571
572 if ((*s)->complete) {
573 return 1;
574 }
575
576 }
577
578 return 0;
579 }
580
581 /*
582 * mpeg-ts interface
583 */
584
585 struct graphics_processor_s {
586 uint16_t pid;
587 M2TS_DEMUX *demux;
588 PES_BUFFER *queue;
589 };
590
graphics_processor_init(void)591 GRAPHICS_PROCESSOR *graphics_processor_init(void)
592 {
593 GRAPHICS_PROCESSOR *p = calloc(1, sizeof(*p));
594
595 return p;
596 }
597
graphics_processor_free(GRAPHICS_PROCESSOR ** p)598 void graphics_processor_free(GRAPHICS_PROCESSOR **p)
599 {
600 if (p && *p) {
601 m2ts_demux_free(&(*p)->demux);
602 pes_buffer_free(&(*p)->queue);
603
604 X_FREE(*p);
605 }
606 }
607
graphics_processor_decode_ts(GRAPHICS_PROCESSOR * p,PG_DISPLAY_SET ** s,uint16_t pid,uint8_t * unit,unsigned num_units,int64_t stc)608 int graphics_processor_decode_ts(GRAPHICS_PROCESSOR *p,
609 PG_DISPLAY_SET **s,
610 uint16_t pid, uint8_t *unit, unsigned num_units,
611 int64_t stc)
612 {
613 unsigned ii;
614 int result = 0;
615
616 if (pid != p->pid) {
617 m2ts_demux_free(&p->demux);
618 pes_buffer_free(&p->queue);
619 }
620 if (!p->demux) {
621 p->demux = m2ts_demux_init(pid);
622 if (!p->demux) {
623 return 0;
624 }
625 p->pid = pid;
626 }
627
628 for (ii = 0; ii < num_units; ii++) {
629 pes_buffer_append(&p->queue, m2ts_demux(p->demux, unit));
630 unit += 6144;
631 }
632
633 if (p->queue) {
634 result = graphics_processor_decode_pes(s, &p->queue, stc);
635 }
636
637 return result;
638 }
639