/*
 * 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;
}
Beispiel #2
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;
}
Beispiel #3
0
/* 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;
}