00001
00002
00003 #ifndef _PES_PACKET_H_
00004 #define _PES_PACKET_H_
00005
00006
00007
00008
00009
00010
00011 #include <vector>
00012 using namespace std;
00013
00014 #include "tspacket.h"
00015 #include "mythlogging.h"
00016
00017 unsigned char *pes_alloc(uint size);
00018 void pes_free(unsigned char *ptr);
00019
00025 class PESPacket
00026 {
00028 void InitPESPacket(TSPacket& tspacket)
00029 {
00030 if (tspacket.PayloadStart())
00031 _psiOffset = tspacket.AFCOffset() + tspacket.StartOfFieldPointer();
00032 else
00033 {
00034 LOG(VB_GENERAL, LOG_ERR, "Started PESPacket, but !payloadStart()");
00035 _psiOffset = tspacket.AFCOffset();
00036 }
00037 _pesdata = tspacket.data() + _psiOffset + 1;
00038
00039 _badPacket = true;
00040
00041
00042 if ((_pesdata - tspacket.data()) <= (188-3) &&
00043 (_pesdata + Length() - tspacket.data()) <= (188-3))
00044 {
00045 _badPacket = !VerifyCRC();
00046 }
00047 }
00048
00049 protected:
00050
00051 PESPacket(const TSPacket* tspacket, bool)
00052 : _pesdata(NULL), _fullbuffer(NULL),
00053 _ccLast(tspacket->ContinuityCounter()), _allocSize(0)
00054 {
00055 InitPESPacket(const_cast<TSPacket&>(*tspacket));
00056 _fullbuffer = const_cast<unsigned char*>(tspacket->data());
00057 _pesdataSize = TSPacket::kSize - (_pesdata - _fullbuffer);
00058 }
00059
00060 PESPacket(const unsigned char *pesdata, bool)
00061 : _pesdata(const_cast<unsigned char*>(pesdata)),
00062 _fullbuffer(const_cast<unsigned char*>(pesdata)),
00063 _psiOffset(0), _ccLast(255), _allocSize(0)
00064 {
00065 _badPacket = !VerifyCRC();
00066 _pesdataSize = max(((int)Length())-1 + (HasCRC() ? 4 : 0), (int)0);
00067 }
00068
00069 private:
00070
00071 PESPacket& operator=(const PESPacket& pkt);
00072
00073 public:
00074
00075 PESPacket(const PESPacket& pkt)
00076 : _pesdata(NULL),
00077 _psiOffset(pkt._psiOffset),
00078 _ccLast(pkt._ccLast),
00079 _pesdataSize(pkt._pesdataSize),
00080 _allocSize(pkt._allocSize),
00081 _badPacket(pkt._badPacket)
00082 {
00083 if (!_allocSize)
00084 _allocSize = pkt._pesdataSize + (pkt._pesdata - pkt._fullbuffer);
00085
00086 _fullbuffer = pes_alloc(_allocSize);
00087 memcpy(_fullbuffer, pkt._fullbuffer, _allocSize);
00088 _pesdata = _fullbuffer + (pkt._pesdata - pkt._fullbuffer);
00089 }
00090
00091
00092 PESPacket(const TSPacket& tspacket)
00093 : _ccLast(tspacket.ContinuityCounter()), _pesdataSize(188)
00094 {
00095 InitPESPacket(const_cast<TSPacket&>(tspacket));
00096
00097 int len = (4*1024) - 256;
00098 _allocSize = len + _psiOffset;
00099 _fullbuffer = pes_alloc(_allocSize);
00100 _pesdata = _fullbuffer + _psiOffset + 1;
00101 memcpy(_fullbuffer, tspacket.data(), TSPacket::kSize);
00102 }
00103
00104
00105
00106
00107
00108
00109
00110
00111 PESPacket(const TSPacket &tspacket,
00112 const unsigned char *pesdata, uint pes_size)
00113 : _ccLast(tspacket.ContinuityCounter()), _pesdataSize(pes_size)
00114 {
00115 InitPESPacket(const_cast<TSPacket&>(tspacket));
00116 int len = pes_size+4;
00117
00118 _allocSize = ((len+_psiOffset+187)/188)*188;
00119 _fullbuffer = pes_alloc(_allocSize);
00120 _pesdata = _fullbuffer + _psiOffset + 1;
00121 memcpy(_fullbuffer, tspacket.data(), 188);
00122 memcpy(_pesdata, pesdata, pes_size-1);
00123 }
00124
00125 virtual ~PESPacket()
00126 {
00127 if (IsClone())
00128 pes_free(_fullbuffer);
00129
00130 _fullbuffer = NULL;
00131 _pesdata = NULL;
00132 }
00133
00134 static const PESPacket View(const TSPacket& tspacket)
00135 { return PESPacket(&tspacket, false); }
00136
00137 static PESPacket View(TSPacket& tspacket)
00138 { return PESPacket(&tspacket, false); }
00139
00140 static const PESPacket ViewData(const unsigned char* pesdata)
00141 { return PESPacket(pesdata, false); }
00142
00143 bool IsClone() const { return bool(_allocSize); }
00144
00145
00146 bool AddTSPacket(const TSPacket* tspacket, bool &broken);
00147
00148 bool IsGood() const { return !_badPacket; }
00149
00150 const TSHeader* tsheader() const
00151 { return reinterpret_cast<const TSHeader*>(_fullbuffer); }
00152 TSHeader* tsheader()
00153 { return reinterpret_cast<TSHeader*>(_fullbuffer); }
00154
00155 void GetAsTSPackets(vector<TSPacket> &pkts, uint cc) const;
00156
00157
00158 uint StreamID() const { return _pesdata[0]; }
00159 uint Length() const
00160 { return (_pesdata[1] & 0x0f) << 8 | _pesdata[2]; }
00161
00162
00163 uint ScramblingControl() const
00164 { return (_pesdata[3] & 0x30) >> 4; }
00166 bool HighPriority() const { return (_pesdata[3] & 0x8) >> 3; }
00168 bool DataAligned() const { return (_pesdata[3] & 0x4) >> 2; }
00173 bool CopyRight() const { return (_pesdata[3] & 0x2) >> 1; }
00175 bool OriginalRecording() const { return _pesdata[3] & 0x1; }
00176
00178 bool HasPTS() const { return (_pesdata[4] & 0x80) >> 7; }
00180 bool HasDTS() const { return (_pesdata[4] & 0x40) >> 6; }
00182 bool HasESCR() const { return (_pesdata[4] & 0x20) >> 5; }
00184 bool HasESR() const { return (_pesdata[4] & 0x10) >> 4; }
00186 bool HasDSM() const { return (_pesdata[4] & 0x8) >> 3; }
00188 bool HasACI() const { return (_pesdata[4] & 0x4) >> 2; }
00190 virtual bool HasCRC() const { return (_pesdata[4] & 0x2) >> 1; }
00192 bool HasExtensionFlags() const { return _pesdata[4] & 0x1; }
00193
00195 uint64_t PTS(void) const
00196 {
00197 int i = 6;
00198 return
00199 (uint64_t(_pesdata[i+0] & 0x0e) << 29) |
00200 (uint64_t(_pesdata[i+1] ) << 22) |
00201 (uint64_t(_pesdata[i+2] & 0xfe) << 14) |
00202 (uint64_t(_pesdata[i+3] ) << 7) |
00203 (uint64_t(_pesdata[i+4] & 0xfe) >> 1);
00204 }
00206 uint64_t DTS(void) const
00207 {
00208 int i = 6+(HasPTS()?5:0);
00209 return
00210 (uint64_t(_pesdata[i+0] & 0x0e) << 29) |
00211 (uint64_t(_pesdata[i+1] ) << 22) |
00212 (uint64_t(_pesdata[i+2] & 0xfe) << 14) |
00213 (uint64_t(_pesdata[i+3] ) << 7) |
00214 (uint64_t(_pesdata[i+4] & 0xfe) >> 1);
00215 }
00216
00217
00218
00219
00220
00221 uint TSSizeInBuffer() const { return _pesdataSize; }
00222 uint PSIOffset() const { return _psiOffset; }
00223
00224 const unsigned char* pesdata() const { return _pesdata; }
00225 unsigned char* pesdata() { return _pesdata; }
00226
00227 const unsigned char* data() const { return _fullbuffer; }
00228 unsigned char* data() { return _fullbuffer; }
00229
00230 void SetStreamID(uint id) { _pesdata[0] = id; }
00231 void SetLength(uint len)
00232 {
00233 _pesdata[1] = (_pesdata[1] & 0xf0) | ((len>>8) & 0x0f);
00234 _pesdata[2] = len & 0xff;
00235 }
00236 void SetTotalLength(uint len)
00237 {
00238 len += 4 ;
00239 len -= 3 ;
00240 SetLength(len);
00241 }
00242
00243 void SetPSIOffset(uint offset)
00244 {
00245 _psiOffset = offset;
00246 _pesdata = _fullbuffer + _psiOffset + 1;
00247 }
00248
00249 uint CRC(void) const
00250 {
00251 if (!HasCRC() || (Length() < 1))
00252 return 0x0;
00253 uint offset = Length() - 1;
00254 return ((_pesdata[offset+0]<<24) |
00255 (_pesdata[offset+1]<<16) |
00256 (_pesdata[offset+2]<<8) |
00257 (_pesdata[offset+3]));
00258 }
00259
00260 void SetCRC(uint crc)
00261 {
00262 if (Length() < 1)
00263 return;
00264
00265 uint offset = Length() - 1;
00266 _pesdata[offset+0] = (crc & 0xff000000) >> 24;
00267 _pesdata[offset+1] = (crc & 0x00ff0000) >> 16;
00268 _pesdata[offset+2] = (crc & 0x0000ff00) >> 8;
00269 _pesdata[offset+3] = (crc & 0x000000ff);
00270 }
00271
00272 uint CalcCRC(void) const;
00273 bool VerifyCRC(void) const;
00274
00275 protected:
00276 void Finalize() { SetCRC(CalcCRC()); }
00277
00278 unsigned char *_pesdata;
00279 unsigned char *_fullbuffer;
00280
00281 uint _psiOffset;
00282 uint _ccLast;
00283 uint _pesdataSize;
00284 uint _allocSize;
00285 bool _badPacket;
00286 };
00287
00288 class SequenceHeader
00289 {
00290 public:
00291 uint width(void) const { return (data[0] <<4) | (data[1]>>4); }
00292 uint height(void) const { return ((data[1] & 0xf)<<8) | data[2]; }
00293 uint aspectNum(void) const { return data[3] >> 4; }
00294 uint fpsNum(void) const { return data[3] & 0xf; }
00295 float fps(void) const { return mpeg2_fps[fpsNum()]; }
00296 float aspect(bool mpeg1) const;
00297
00298 private:
00299 SequenceHeader() {;}
00300 ~SequenceHeader() {;}
00301
00302 unsigned char data[11];
00303 static const float mpeg1_aspect[16];
00304 static const float mpeg2_aspect[16];
00305 static const float mpeg2_fps[16];
00306 };
00307
00308 #endif // _PES_PACKET_H_