BOOL parse_TS(BYTE *ts_stream) { uint8_t tsph.sync = TS_SYNC_BYTE(ts_stream); if(tsph.sync != 0x47){ debuglog("sync bytes missed!"); return FALSE; } tsph.transport_error_indicator = TS_ERROR(ts_stream); tsph.payload_uint_start_indicator = TS_PAYLOAD_START(ts_stream); tsph.transport_priority = TS_PRIORITY(ts_stream); tsph.PID = TS_PID(ts_stream); tsph.transport_scrambling = TS_SCRAMBLING(ts_stream); tsph.adaptation_field_control = TS_ADAPT_CTL(ts_stream); tsph.continuity_counter = TS_CONT_COUNT(ts_stream); debuglog("ts:transport_error_indicator:%d\n payload_uint_start_indicator:%d\n transport_priority:%d\n PID:%d\n transport_scrambling:%d\n continuity_counter:%d\n", tsph.transport_error_indicator, tsph.payload_uint_start_indicator, tsph.transport_priority, tsph.PID, tsph.transport_scrambling, tsph.continuity_counter); if(!tsph.transport_error_indicator) { int len = 0; len += 4; if(is_psi(tsph.PID)) { if(tsph.payload_uint_start_indicator == 1) { tsph.pointer_field = TS_POINTER_FIELD(ts_stream + len); len = len + tsph.pointer_field + 1; } else { /*TS包的净荷不带有PSI/SI包数据的第一个字节,没有pointer_field *psi/si信息跨越两个ts包,不解析 */ debuglog("此ts包是另一个psi/si表未完部分,暂为解析"); return FALSE; } switch(tsph.adaptation_field_control) { case 0x03: /* 有adaptation,也有净荷 */ tsph.adaptation_fields = (tsadaptation_filed *)malloc(sizeof(tsadaptation_filed)); if(!tsph.adaptation_fields) { debuglog("malloc tsph.adaptation_field failed"); return FALSE; } tsph.adaptation_fields->adapt_field_len = TS_ADAPT_LEN(ts_stream); len = len + tsph.adaptation_fields->adapt_field_len + 1; /* adapt_field_len表示在它后面的数据的长度 */ break; case 0x01:/* 只有净荷数据 */ case 0x02:/* 只有adaptation */ case 0x00:/* 保留 */ default: break; } BYTE* sec_start = ts_stream + len; /* psi/si表起始位置 */ switch(tsph.PID) { /* todo:对不同的错误可以给一个错误号 */ case 0x0000: if(!parse_PAT(sec_start)) { debuglog("parse pat failed!check log..."); return FALSE; } break; case 0x0001: if(!parse_CAT(sec_start)) { debuglog("parse cat failed!check log..."); return FALSE; } break; case 0x0010: if(!parse_NIT(sec_start)) { debuglog("parse nit failed!check log..."); return FALSE; } break; case 0x0011: if(!parse_SDT(sec_start)) { debuglog("parse sdt failed!check log..."); return FALSE; } break; case 0x0012: if(!parse_EIT(sec_start)) { debuglog("parse eit failed!check log..."); return FALSE; } break; case 0x0014: // parse_TDT(); // parse_TOD(); break; default: if(is_pmt_pid(tsph.PID)) { parse_PMT(sec_start); } break; } } else { if(is_es_pid(tsph.PID)) { /*parse_ES()*/ } else { /*parse_Others() */ } } } else { debuglog("transport error!"); return FALSE; } free(tsph.adaptation_fields); tsph.adaptation_fields = NULL; return TRUE; }
// 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; }