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