Пример #1
0
//	input parser: Parse a TS packet Documentation at iso13818-1.pdf
SSIZE_T TSDemuxer::parse( Buffer *buf, SSIZE_T parsed ) {
	BYTE *ptr	= (BYTE *)buf->buffer();
	SIZE_T size = buf->length();

	//printf( "[TSDemuxer] Begin parse: offset=%ld, bufLen=%ld, local=%d\n", parsed, size, (_local == buf) );			
	
	while (parsed < size) {
		{	//	Find TS SYNC byte
			SSIZE_T begin=parsed;
			while (ptr[parsed] != TS_SYNC && parsed < size) {
				parsed++;
			}
			if (parsed - begin) {
				Buffer show( buf->buffer()+begin, parsed+10, false );
				printf( "[TSDemuxer] Warning: Sync lost offset=%ld, size=%ld, count=%ld, isLocal=%d, data=%s\n",
					begin, size, parsed-begin, (_local == buf), show.asHexa().c_str() );
			}
		}

		//	is the begin of TS packet!
		if (parsed < size) {
			int len	 = size - parsed;
			BYTE *ts = ptr + parsed;

			//	is ths TS complete?
			if (len >= TS_PACKET_SIZE) {
				ID pid = TS_PID(ts);

				//	Check for Transport Error Indicator (TES), payload exist, and null packets!!
				if (!TS_HAS_ERROR(ts) && TS_HAS_PAYLOAD(ts) && pid != TS_PID_NULL) {
					int payloadOffset = TS_HEAD_SIZE;
					
					//	Adaptation field exists?
					if (TS_HAS_ADAPTATION(ts)) {
						//	Only calculate payload offset if adaptation field exist
						payloadOffset += TSA_LEN(ts);
					}

					//	Check payload offset
					if (payloadOffset < TS_PACKET_SIZE) {
						bool startFlag = TS_START(ts);
						
						//	Find filter (and check continuity bit)
						_mutex.lock();
						PSIFilter *filter = checkContinuity( pid, startFlag, TS_CONTINUITY(ts) );
						if (filter) {
							BYTE *tsPayload	 = ts+payloadOffset;
							int tsPayloadLen = TS_PACKET_SIZE-payloadOffset;

							//	Begin of a section?
							if (startFlag) {
								//	Get pointer field, skip them in payload and len
								BYTE pointerField = tsPayload[0];
								tsPayload++;
								tsPayloadLen--;
								
								//	Check pointer field
								if (!pointerField || pointerField < tsPayloadLen) {
									if (pointerField) {
										//	Append last block of a section
										filter->pushData( tsPayload, pointerField );

										//	Skip data marked via pointer field
										tsPayload	 += pointerField;
										tsPayloadLen -= pointerField;
									}
									//	TODO: Can start more than one section/pes packet

									//	Start a new section
									filter->startData( tsPayload, tsPayloadLen );
								}
								else {
									printf( "[TSDemuxer] Warning: Pointer field invalid pointer=%d, tsPayloadLen=%d\n", pointerField, tsPayloadLen );
								}
							}
							else {
								//	Add payload to current section
								filter->pushData( tsPayload, tsPayloadLen );
							}

							if (TS_PRIORITY(ts)) {	//	TODO: Priority not processed
								printf( "[TSDemuxer] Warning: Priority not processed\n" );
							}
						}
						_mutex.unlock();
					}
					else {
						printf( "[TSDemuxer] Warning: Transport stream payload not valid\n" );
					}
				}

				parsed += TS_PACKET_SIZE;				
			}
			else {
				//	break loop
				break;
			}
		}
	}

	//printf( "[TSDemuxer] End parse: parsed=%ld\n", parsed );
	
	return parsed;
}
Пример #2
0
/* sms1xxx_demux_write_section(): write a section to demux filter
   Return 0 if section handled (written or no buffer space left)
   Return 1 if section data is corrupt */
static int
sms1xxx_demux_write_section(struct sms1xxx_softc *sc, u8 *p,
    struct filter *f)
{
    u8 hlen, len, total, count;
    u8 *payload;
    if(!TS_HAS_PAYLOAD(p))
        return (1);

    hlen = TS_GET_HDR_LEN(p);
    if(hlen >= PACKET_SIZE) {
        sms1xxx_demux_sectbuf_reset(sc, f, 1, "corrupt packet");
        return (1);
    }

    payload = p + hlen;
    len = PACKET_SIZE - hlen;

    if(TS_HAS_PUSI(p)) {
        u8 off = TS_GET_SECT_OFF(payload);
        if((hlen + off + 3) > PACKET_SIZE) {
            sms1xxx_demux_sectbuf_reset(sc, f, 1, "corrupt packet");
            return (1);
        }
#ifdef SMS1XXX_DIAGNOSTIC
        /* XXX Check if the old section is finished */
        if(f->wtodo != 0) {
            WARN("pid: %hu section not finished but new pusi "
                "hlen %d off %d todo %d\n", f->pid,
                hlen, off, f->wtodo);
        }
#endif
        /* Section start */
        payload += off; len -= off;
        if((TS_GET_SECT_TBLID(payload) & f->mask) != f->value) {
            f->wtodo = 0;
            return (0);
        }
        f->wtodo = TS_GET_SECT_LEN(payload);
        TRACE(TRACE_SECT,"pid: %hu writing new section len: %d\n",
            f->pid, f->wtodo);
    }
    if(f->wtodo == 0)
        return (0);

    total = MIN(f->wtodo,len);
    if(total > f->wavail) {
#ifdef SMS1XXX_DIAGNOSTIC
        WARN("pid: %hu no section buffer space available\n",f->pid);
#endif
        sms1xxx_demux_sectbuf_reset(sc, f, 1, "no buffer space");
        return (0);
    }
    if(total > f->size) {
        ERR("total > f->size, this shouldn't happen! %d > %d\n",
            total,f->size);
        return (1);
    }

    TRACE(TRACE_SECT,"pid: %hu writing %d bytes to section\n",
        f->pid,total);
    count = MIN(total,f->size - f->woff);
    memcpy(f->buf + f->woff,payload,count);

    if(count < total) {
        f->woff = total - count;
        memcpy(f->buf,payload+count,f->woff);
    }
    else {
        f->woff += total;
    }
    if(f->woff == f->size)
        f->woff = 0;

    f->wtodo -= total;
    if(f->wtodo == 0) {
        mtx_lock(&sc->filterlock);
        f->wavail -= total;
        f->ravail += total;
        f->cnt++;
        f->state &= ~FILTER_OVERFLOW;
        mtx_unlock(&sc->filterlock);
        TRACE(TRACE_SECT,"pid: %hu writing section done cnt: %d\n"
            ,f->pid, f->cnt);

        /* Wake up readers ! */
        if(f->state & FILTER_SLEEP)
            wakeup(f);
        if(f->state & FILTER_POLL) {
            f->state &= ~FILTER_POLL;
            selwakeuppri(&f->rsel, PZERO);
        }
    }
    else {
        mtx_lock(&sc->filterlock);
        f->wavail -= total;
        f->ravail += total;
        mtx_unlock(&sc->filterlock);
    }
#ifdef SMS1XXX_DIAGNOSTIC
    if(total < len && TS_GET_SECT_TBLID(payload+total) != 0xFF)
        WARN("possible section(s) discarded\n");
#endif
    return (0);
}