00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "graphics_processor.h"
00021
00022 #include "ig_decode.h"
00023 #include "pg_decode.h"
00024 #include "pes_buffer.h"
00025 #include "m2ts_demux.h"
00026
00027 #include "util/macro.h"
00028 #include "util/logging.h"
00029 #include "util/bits.h"
00030
00031 #include <string.h>
00032 #include <stdlib.h>
00033 #include <inttypes.h>
00034
00035 #define GP_TRACE(...) do {} while (0)
00036
00037
00038
00039
00040
00041
00042 typedef enum {
00043 PGS_PALETTE = 0x14,
00044 PGS_OBJECT = 0x15,
00045 PGS_PG_COMPOSITION = 0x16,
00046 PGS_WINDOW = 0x17,
00047 PGS_IG_COMPOSITION = 0x18,
00048 PGS_END_OF_DISPLAY = 0x80,
00049 } pgs_segment_type_e;
00050
00051
00052
00053
00054
00055 void pg_display_set_free(PG_DISPLAY_SET **s)
00056 {
00057 if (s && *s) {
00058 unsigned ii;
00059 for (ii = 0; ii < (*s)->num_object; ii++) {
00060 pg_clean_object(&(*s)->object[ii]);
00061 }
00062 ig_free_interactive(&(*s)->ics);
00063
00064 X_FREE((*s)->window);
00065 X_FREE((*s)->object);
00066 X_FREE((*s)->palette);
00067
00068 X_FREE(*s);
00069 }
00070 }
00071
00072
00073
00074
00075
00076 static PES_BUFFER *_find_segment_by_idv(PES_BUFFER *p,
00077 uint8_t seg_type, unsigned idv_pos,
00078 uint8_t *idv, unsigned idv_len)
00079 {
00080 while (p && (p->buf[0] != seg_type || memcmp(p->buf + idv_pos, idv, idv_len))) {
00081 p = p->next;
00082 }
00083 return p;
00084 }
00085
00086 static void _join_fragments(PES_BUFFER *p1, PES_BUFFER *p2, int data_pos)
00087 {
00088 unsigned new_len = p1->len + p2->len - data_pos;
00089
00090 if (p1->size < new_len) {
00091 p1->size = new_len + 1;
00092 p1->buf = realloc(p1->buf, p1->size);
00093 }
00094
00095 memcpy(p1->buf + p1->len, p2->buf + data_pos, p2->len - data_pos);
00096 p1->len = new_len;
00097 p2->len = 0;
00098 }
00099
00100
00101 static int _join_segment_fragments(struct pes_buffer_s *p)
00102 {
00103 uint8_t type = p->buf[0];
00104 unsigned id_pos = 0, id_len = 3, sd_pos = 6, data_pos = 0;
00105
00106 if (p->len < 3) {
00107 return 1;
00108 }
00109
00110
00111
00112 if (type == PGS_OBJECT) {
00113 id_pos = 3;
00114 sd_pos = 6;
00115 data_pos = 7;
00116 }
00117 else if (type == PGS_IG_COMPOSITION) {
00118 id_pos = 8;
00119 sd_pos = 11;
00120 data_pos = 12;
00121 }
00122 else {
00123 return 1;
00124 }
00125
00126
00127
00128 BD_PG_SEQUENCE_DESCRIPTOR sd;
00129 BITBUFFER bb;
00130 bb_init(&bb, p->buf + sd_pos, 3);
00131 pg_decode_sequence_descriptor(&bb, &sd);
00132
00133 if (sd.last_in_seq) {
00134 return 1;
00135 }
00136 if (!sd.first_in_seq) {
00137 return 1;
00138 }
00139
00140
00141
00142 PES_BUFFER *next;
00143 while (NULL != (next = _find_segment_by_idv(p->next, p->buf[0], id_pos, p->buf + id_pos, id_len))) {
00144
00145 bb_init(&bb, next->buf + sd_pos, 3);
00146 pg_decode_sequence_descriptor(&bb, &sd);
00147
00148 _join_fragments(p, next, data_pos);
00149
00150 pes_buffer_remove(&p, next);
00151
00152 if (sd.last_in_seq) {
00153
00154 p->buf[sd_pos] = 0xff;
00155 return 1;
00156 }
00157 }
00158
00159
00160 return !!p->next;
00161 }
00162
00163
00164
00165
00166
00167 static int _decode_wds(PG_DISPLAY_SET *s, BITBUFFER *bb, PES_BUFFER *p)
00168 {
00169 (void)s;
00170 (void)bb;
00171 (void)p;
00172
00173 BD_DEBUG(DBG_DECODE | DBG_CRIT, "unhandled segment type (PGS_WINDOW)\n");
00174 return 0;
00175 }
00176
00177 static int _decode_ods(PG_DISPLAY_SET *s, BITBUFFER *bb, PES_BUFFER *p)
00178 {
00179
00180
00181 if (s->object) {
00182 BITBUFFER bb_tmp = *bb;
00183 uint16_t id = bb_read(&bb_tmp, 16);
00184 unsigned ii;
00185
00186 for (ii = 0; ii < s->num_object; ii++) {
00187 if (s->object[ii].id == id) {
00188 if (pg_decode_object(bb, &s->object[ii])) {
00189 s->object[ii].pts = p->pts;
00190 return 1;
00191 }
00192 return 0;
00193 }
00194 }
00195 }
00196
00197
00198
00199 s->object = realloc(s->object, sizeof(s->object[0]) * (s->num_object + 1));
00200 memset(&s->object[s->num_object], 0, sizeof(s->object[0]));
00201
00202 if (pg_decode_object(bb, &s->object[s->num_object])) {
00203 s->object[s->num_object].pts = p->pts;
00204 s->num_object++;
00205 return 1;
00206 }
00207
00208 return 0;
00209 }
00210
00211 static int _decode_pds(PG_DISPLAY_SET *s, BITBUFFER *bb, PES_BUFFER *p)
00212 {
00213
00214
00215 if (s->palette) {
00216 BITBUFFER bb_tmp = *bb;
00217 uint8_t id = bb_read(&bb_tmp, 8);
00218 unsigned ii;
00219
00220 for (ii = 0; ii < s->num_palette; ii++) {
00221 if (s->palette[ii].id == id) {
00222 int rr;
00223 if ( (s->ics && s->ics->composition_descriptor.state == 0) ||
00224 (s->pcs && s->pcs->composition_descriptor.state == 0)) {
00225
00226 rr = pg_decode_palette_update(bb, &s->palette[ii]);
00227 } else {
00228 rr = pg_decode_palette(bb, &s->palette[ii]);
00229 }
00230 if (rr) {
00231 s->palette[ii].pts = p->pts;
00232 return 1;
00233 }
00234 return 0;
00235 }
00236 }
00237 }
00238
00239
00240
00241 s->palette = realloc(s->palette, sizeof(s->palette[0]) * (s->num_palette + 1));
00242 memset(&s->palette[s->num_palette], 0, sizeof(s->palette[0]));
00243
00244 if (pg_decode_palette(bb, &s->palette[s->num_palette])) {
00245 s->palette[s->num_palette].pts = p->pts;
00246 s->num_palette++;
00247 return 1;
00248 }
00249
00250 return 0;
00251 }
00252
00253 static void _check_epoch_start(PG_DISPLAY_SET *s)
00254 {
00255 if ((s->pcs && s->pcs->composition_descriptor.state == 2) ||
00256 (s->ics && s->ics->composition_descriptor.state == 2)) {
00257
00258
00259 unsigned ii;
00260 for (ii = 0; ii < s->num_object; ii++) {
00261 pg_clean_object(&s->object[ii]);
00262 }
00263
00264 s->num_palette = 0;
00265 s->num_window = 0;
00266 s->num_object = 0;
00267
00268 s->epoch_start = 1;
00269
00270 } else {
00271 s->epoch_start = 0;
00272 }
00273 }
00274
00275 static int _decode_pcs(PG_DISPLAY_SET *s, BITBUFFER *bb, PES_BUFFER *p)
00276 {
00277 pg_free_composition(&s->pcs);
00278 s->pcs = calloc(1, sizeof(*s->pcs));
00279
00280 if (!pg_decode_composition(bb, s->pcs)) {
00281 pg_free_composition(&s->pcs);
00282 return 0;
00283 }
00284
00285 s->pcs->pts = p->pts;
00286 s->valid_pts = p->pts;
00287
00288 _check_epoch_start(s);
00289
00290 return 1;
00291 }
00292
00293 static int _decode_ics(PG_DISPLAY_SET *s, BITBUFFER *bb, PES_BUFFER *p)
00294 {
00295 ig_free_interactive(&s->ics);
00296 s->ics = calloc(1, sizeof(*s->ics));
00297
00298 if (!ig_decode_interactive(bb, s->ics)) {
00299 ig_free_interactive(&s->ics);
00300 return 0;
00301 }
00302
00303 s->ics->pts = p->pts;
00304 s->valid_pts = p->pts;
00305
00306 _check_epoch_start(s);
00307
00308 return 1;
00309 }
00310
00311 static int _decode_segment(PG_DISPLAY_SET *s, PES_BUFFER *p)
00312 {
00313 BITBUFFER bb;
00314 bb_init(&bb, p->buf, p->len);
00315
00316 uint8_t type = bb_read(&bb, 8);
00317 bb_read(&bb, 16);
00318
00319 switch (type) {
00320 case PGS_OBJECT:
00321 return _decode_ods(s, &bb, p);
00322
00323 case PGS_PALETTE:
00324 return _decode_pds(s, &bb, p);
00325
00326 case PGS_WINDOW:
00327 return _decode_wds(s, &bb, p);
00328
00329 case PGS_PG_COMPOSITION:
00330 return _decode_pcs(s, &bb, p);
00331
00332 case PGS_IG_COMPOSITION:
00333 return _decode_ics(s, &bb, p);
00334
00335 case PGS_END_OF_DISPLAY:
00336 s->complete = 1;
00337 return 1;
00338
00339 default:
00340 BD_DEBUG(DBG_DECODE | DBG_CRIT, "unknown segment type 0x%x\n", type);
00341 break;
00342 }
00343
00344 return 0;
00345 }
00346
00347
00348
00349
00350
00351 int graphics_processor_decode_pes(PG_DISPLAY_SET **s, PES_BUFFER **p, int64_t stc)
00352 {
00353 if (!s) {
00354 return 0;
00355 }
00356
00357 if (*s == NULL) {
00358 *s = calloc(1, sizeof(PG_DISPLAY_SET));
00359 }
00360
00361 while (*p) {
00362
00363
00364 if (stc >= 0 && (*p)->dts > stc) {
00365 GP_TRACE("Segment dts > stc (%"PRId64" > %"PRId64" ; diff %"PRId64")\n",
00366 (*p)->dts, stc, (*p)->dts - stc);
00367 return 0;
00368 }
00369
00370
00371 if (!_join_segment_fragments(*p)) {
00372 GP_TRACE("splitted segment not complete, waiting for next fragment\n");
00373 return 0;
00374 }
00375
00376 if ((*p)->len <= 2) {
00377 BD_DEBUG(DBG_DECODE, "segment too short, skipping (%d bytes)\n", (*p)->len);
00378 pes_buffer_remove(p, *p);
00379 continue;
00380 }
00381
00382
00383
00384 GP_TRACE("Decoding segment, dts %010"PRId64" pts %010"PRId64" len %d\n",
00385 (*p)->dts, (*p)->pts, (*p)->len);
00386
00387 (*s)->complete = 0;
00388
00389 _decode_segment(*s, *p);
00390
00391 pes_buffer_remove(p, *p);
00392
00393 if ((*s)->complete) {
00394 return 1;
00395 }
00396
00397 }
00398
00399 return 0;
00400 }
00401
00402
00403
00404
00405
00406 struct graphics_processor_s {
00407 uint16_t pid;
00408 M2TS_DEMUX *demux;
00409 PES_BUFFER *queue;
00410 };
00411
00412 GRAPHICS_PROCESSOR *graphics_processor_init(void)
00413 {
00414 GRAPHICS_PROCESSOR *p = calloc(1, sizeof(*p));
00415
00416 return p;
00417 }
00418
00419 void graphics_processor_free(GRAPHICS_PROCESSOR **p)
00420 {
00421 if (p && *p) {
00422 m2ts_demux_free(&(*p)->demux);
00423 pes_buffer_free(&(*p)->queue);
00424
00425 X_FREE(*p);
00426 }
00427 }
00428
00429 int graphics_processor_decode_ts(GRAPHICS_PROCESSOR *p,
00430 PG_DISPLAY_SET **s,
00431 uint16_t pid, uint8_t *unit, unsigned num_units,
00432 int64_t stc)
00433 {
00434 unsigned ii;
00435
00436 if (pid != p->pid) {
00437 m2ts_demux_free(&p->demux);
00438 pes_buffer_free(&p->queue);
00439 }
00440 if (!p->demux) {
00441 p->demux = m2ts_demux_init(pid);
00442 p->pid = pid;
00443 }
00444
00445 for (ii = 0; ii < num_units; ii++) {
00446 pes_buffer_append(&p->queue, m2ts_demux(p->demux, unit));
00447 unit += 6144;
00448 }
00449
00450 if (p->queue) {
00451 return graphics_processor_decode_pes(s, &p->queue, stc);
00452 }
00453
00454 return 0;
00455 }