/* * mpeg-pes interface */ #define MAX_STC_DTS_DIFF (INT64_C(90000 * 30)) /* 30 seconds */ static int graphics_processor_decode_pes(PG_DISPLAY_SET **s, PES_BUFFER **p, int64_t stc) { if (!s) { return 0; } if (*s == NULL) { *s = calloc(1, sizeof(PG_DISPLAY_SET)); } while (*p) { /* time to decode next segment ? */ if (stc >= 0 && (*p)->dts > stc) { /* filter out values that seem to be incorrect (if stc is not updated) */ int64_t diff = (*p)->dts - stc; if (diff < MAX_STC_DTS_DIFF) { GP_TRACE("Segment dts > stc (%"PRId64" > %"PRId64" ; diff %"PRId64")\n", (*p)->dts, stc, diff); return 0; } } /* all fragments present ? */ if (!_join_segment_fragments(*p)) { GP_TRACE("splitted segment not complete, waiting for next fragment\n"); return 0; } if ((*p)->len <= 2) { BD_DEBUG(DBG_DECODE, "segment too short, skipping (%d bytes)\n", (*p)->len); pes_buffer_remove(p, *p); continue; } /* decode segment */ GP_TRACE("Decoding segment, dts %010"PRId64" pts %010"PRId64" len %d\n", (*p)->dts, (*p)->pts, (*p)->len); (*s)->complete = 0; _decode_segment(*s, *p); pes_buffer_remove(p, *p); if ((*s)->complete) { return 1; } } return 0; }
int graphics_processor_decode_pes(PG_DISPLAY_SET **s, PES_BUFFER **p, int64_t stc) { if (!s) { return 0; } if (*s == NULL) { *s = calloc(1, sizeof(PG_DISPLAY_SET)); } (*s)->complete = 0; while (*p && !(*s)->complete) { /* time to decode next segment ? */ if (stc >= 0 && (*p)->dts > stc) { GP_TRACE("Segment dts > stc (%"PRId64" > %"PRId64" ; diff %"PRId64")\n", (*p)->dts, stc, (*p)->dts - stc); return 0; } /* all fragments present ? */ if (!_join_segment_fragments(*p)) { GP_TRACE("splitted segment not complete, waiting for next fragment\n"); return 0; } GP_TRACE("Decoding segment, dts %010"PRId64" pts %010"PRId64" len %d\n", (*p)->dts, (*p)->pts, (*p)->len); /* decode segment */ if ((*p)->len > 2) { _decode_segment(*s, *p); } pes_buffer_remove(p, *p); } return (*s)->complete; }
/* return 1 if segment is ready for decoding, 0 if more data is needed */ static int _join_segment_fragments(struct pes_buffer_s *p) { uint8_t type = p->buf[0]; unsigned id_pos = 0, id_len = 3, sd_pos = 6, data_pos = 0; if (p->len < 3) { return 1; } /* check segment type */ if (type == PGS_OBJECT) { id_pos = 3; sd_pos = 6; data_pos = 7; } else if (type == PGS_IG_COMPOSITION) { id_pos = 8; sd_pos = 11; data_pos = 12; } else { return 1; } /* check sequence descriptor - is segment complete ? */ BD_PG_SEQUENCE_DESCRIPTOR sd; BITBUFFER bb; bb_init(&bb, p->buf + sd_pos, 3); pg_decode_sequence_descriptor(&bb, &sd); if (sd.last_in_seq) { return 1; } if (!sd.first_in_seq) { return 1; } /* find next fragment(s) */ PES_BUFFER *next; while (NULL != (next = _find_segment_by_idv(p->next, p->buf[0], id_pos, p->buf + id_pos, id_len))) { bb_init(&bb, next->buf + sd_pos, 3); pg_decode_sequence_descriptor(&bb, &sd); _join_fragments(p, next, data_pos); pes_buffer_remove(&p, next); if (sd.last_in_seq) { /* set first + last in sequence descriptor */ p->buf[sd_pos] = 0xff; return 1; } } /* do not delay decoding if there are other segments queued (missing fragment ?) */ return !!p->next; }