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