00001 // -*- Mode: c++ -*- 00002 // Copyright (c) 2003-2004, Daniel Thor Kristjansson 00003 #ifndef _TS_PACKET_H_ 00004 #define _TS_PACKET_H_ 00005 00006 #include <cstdlib> 00007 #include "mythcontext.h" 00008 using namespace std; 00009 00010 // n.b. these PID relationships are only a recommendation from ATSC, 00011 // but seem to be universal 00012 #define VIDEO_PID(bp) ((bp)+1) 00013 #define AUDIO_PID(bp) ((bp)+4) 00014 #define SYNC_BYTE 0x0047 00015 00023 class TSHeader { 00024 public: 00025 TSHeader() { _tsdata[0] = SYNC_BYTE; } 00026 TSHeader(int cc) { 00027 _tsdata[0] = SYNC_BYTE; 00028 SetContinuityCounter(cc); 00029 } 00030 void InitHeader(const unsigned char* header) { 00031 if (header) 00032 { 00033 _tsdata[0]=header[0]; 00034 _tsdata[1]=header[1]; 00035 _tsdata[2]=header[2]; 00036 _tsdata[3]=header[3]; 00037 } 00038 } 00039 00040 // Decode the link header (bytes 0-4): 00041 // gets 00042 00043 //0.0 8 bits SYNC_BYTE 00044 bool HasSync() const { return SYNC_BYTE == _tsdata[0]; } 00045 //1.0 1 bit transport_packet_error (if set discard immediately: 00046 // modem error) 00047 bool TransportError() const { return bool(_tsdata[1]&0x80); } 00048 //1.1 1 bit payload_unit_start_indicator 00049 // (if set this packet starts a section, and has pointerField) 00050 bool PayloadStart() const { return bool(_tsdata[1]&0x40); } 00051 //1.2 1 bit transport_priority (ignore) 00052 bool Priority() const { return bool(_tsdata[1]&0x20); } 00053 //1.3 13 bit PID (packet ID, which transport stream) 00054 inline unsigned int PID() const { 00055 return ((_tsdata[1] << 8) + _tsdata[2]) & 0x1fff; 00056 } 00057 //3.0 2 bit transport_scrambling_control (00,01 OK; 10,11 scrambled) 00058 unsigned int ScramplingControl() const { return (_tsdata[3] >> 6) & 0x3; } 00059 //3.2 2 bit adaptation_field_control 00060 // (01-no adptation field,payload only 00061 // 10-adaptation field only,no payload 00062 // 11-adaptation field followed by payload 00063 // 00-reserved) 00064 unsigned int AdaptationFieldControl() const { 00065 return (_tsdata[3] >> 4) & 0x3; 00066 } 00067 //3.4 4 bit continuity counter (should cycle 0->15 in sequence 00068 // for each PID; if skip, we lost a packet; if dup, we can 00069 // ignore packet) 00070 unsigned int ContinuityCounter() const { return _tsdata[3] & 0xf; } 00071 00072 // shortcuts 00073 bool Scrampled() const { return bool(_tsdata[3]&0x80); } 00074 bool HasAdaptationField() const { return bool(_tsdata[3] & 0x20); } 00075 bool HasPayload() const { return bool(_tsdata[3] & 0x10); } 00076 00077 unsigned int AFCOffset() const { // only works if AFC fits in TSPacket 00078 return HasAdaptationField() ? _tsdata[4]+1+4 : 4; 00079 } 00080 00081 void SetTransportError(bool err) { 00082 if (err) _tsdata[1] |= 0x80; else _tsdata[1] &= (0xff-(0x80)); 00083 } 00084 void SetPayloadStart(bool start) { 00085 if (start) _tsdata[1] |= 0x40; else _tsdata[1] &= (0xff-0x40); 00086 } 00087 void SetPriority(bool priority) { 00088 if (priority) _tsdata[1] |= 0x20; else _tsdata[1] &= (0xff-0x20); 00089 } 00090 void SetPID(unsigned int pid) { 00091 _tsdata[1] = ((pid >> 8) & 0x1F) | (_tsdata[1] & 0xE0); 00092 _tsdata[2] = (pid & 0xFF); 00093 } 00094 void SetScrambled(unsigned int scr) { 00095 _tsdata[3] = (_tsdata[3] & (0xff-(0x3<<6))) | (scr<<6); 00096 } 00097 void SetAdaptationFieldControl(unsigned int afc) { 00098 _tsdata[3] = (_tsdata[3] & 0xcf) | (afc&0x3)<<4; 00099 } 00100 void SetContinuityCounter(unsigned int cc) { 00101 _tsdata[3] = (_tsdata[3] & 0xf0) | (cc & 0xf); 00102 } 00103 00104 const unsigned char* data() const { return _tsdata; } 00105 unsigned char* data() { return _tsdata; } 00106 00107 static const unsigned int HEADER_SIZE; 00108 static const unsigned char PAYLOAD_ONLY_HEADER[4]; 00109 private: 00110 unsigned char _tsdata[4]; 00111 }; 00112 00118 class TSPacket : public TSHeader 00119 { 00120 friend class PESPacket; 00121 public: 00122 TSPacket() : TSHeader() {} 00123 static TSPacket* CreatePayloadOnlyPacket() 00124 { 00125 TSPacket *pkt = new TSPacket(); 00126 pkt->InitHeader(PAYLOAD_ONLY_HEADER); 00127 memset(pkt->_tspayload, 0xFF, PAYLOAD_SIZE); 00128 pkt->SetStartOfFieldPointer(0); 00129 return pkt; 00130 } 00131 00132 inline TSPacket* CreateClone() const { 00133 TSPacket *pkt = new TSPacket(); 00134 memcpy(pkt, this, SIZE); 00135 return pkt; 00136 } 00137 00138 void InitPayload(const unsigned char* payload) 00139 { 00140 if (payload) 00141 memcpy(_tspayload, payload, PAYLOAD_SIZE); 00142 } 00143 00144 //4.0 8 bits, iff payloadStart(), points to start of field 00145 unsigned int StartOfFieldPointer() const { return data()[AFCOffset()]; } 00146 void SetStartOfFieldPointer(uint sof) { data()[AFCOffset()] = sof; } 00147 00148 QString toString() const; 00149 00150 static const unsigned int SIZE; 00151 static const unsigned int PAYLOAD_SIZE; 00152 static const TSPacket *NULL_PACKET; 00153 private: 00154 unsigned char _tspayload[184]; 00155 }; 00156 00157 #endif
1.5.5