00001
00002
00003 #include "pespacket.h"
00004 #include "mpegtables.h"
00005 #include "mythcontext.h"
00006
00007 extern "C" {
00008 #include "mythconfig.h"
00009 #include "libavcodec/avcodec.h"
00010 #include "libavformat/avformat.h"
00011 #include "libavutil/crc.h"
00012 #include "libavutil/bswap.h"
00013 }
00014
00015 #include <vector>
00016 #include <map>
00017
00018 using namespace std;
00019
00020
00021 bool PESPacket::AddTSPacket(const TSPacket* packet, bool &broken)
00022 {
00023 broken = true;
00024 if (!tsheader()->PayloadStart())
00025 {
00026 VERBOSE(VB_RECORD, "Error: We started a PES packet, "
00027 "without a payloadStart!");
00028 return true;
00029 }
00030 else if (!IsClone())
00031 {
00032 VERBOSE(VB_RECORD, "Error: Must clone initially to use addPackets()");
00033 return false;
00034 }
00035
00036 const int cc = packet->ContinuityCounter();
00037 const int ccExp = (_ccLast + 1) & 0xf;
00038 uint payloadSize = TSPacket::PAYLOAD_SIZE;
00039 uint payloadStart = TSPacket::HEADER_SIZE;
00040
00041
00042
00043 if (packet->PayloadStart())
00044 {
00045 payloadSize--;
00046 payloadStart++;
00047 }
00048
00049 if (ccExp == cc)
00050 {
00051 if (_pesdataSize + payloadSize >= _allocSize)
00052 {
00053 uint sz = (((_allocSize * 2) + 4095) / 4096) * 4096;
00054 unsigned char *nbuf = pes_alloc(sz);
00055 memcpy(nbuf, _fullbuffer, _pesdataSize);
00056 pes_free(_fullbuffer);
00057 _fullbuffer = nbuf;
00058 _pesdata = _fullbuffer + _psiOffset + 1;
00059 _allocSize = sz;
00060 }
00061
00062 memcpy(_fullbuffer + _pesdataSize,
00063 packet->data() + payloadStart,
00064 payloadSize);
00065
00066 _ccLast = cc;
00067 _pesdataSize += payloadSize;
00068 }
00069 else if (int(_ccLast) == cc)
00070 {
00071
00072 }
00073 else
00074 {
00075 VERBOSE(VB_RECORD, "AddTSPacket: Out of sync!!! "
00076 "Need to wait for next payloadStart" +
00077 QString(" PID: 0x%1, continuity counter: %2 (expected %3).")
00078 .arg(packet->PID(),0,16).arg(cc).arg(ccExp));
00079 return true;
00080 }
00081
00082
00083 broken = false;
00084
00085 if ((_psiOffset + 1 + 3) <= _pesdataSize)
00086 {
00087
00088 uint tlen = Length() + (_pesdata - _fullbuffer) +3;
00089
00090 if (_pesdataSize >= tlen)
00091 {
00092 _badPacket = !VerifyCRC();
00093 return true;
00094 }
00095 }
00096
00097 return false;
00098 }
00099
00103 uint PESPacket::WriteAsTSPackets(unsigned char *buf, uint &cc) const
00104 {
00105 #define INCR_CC(_CC_) do { _CC_ = (_CC_ + 1) & 0xf; } while (0)
00106 uint last_byte_of_pesdata = Length() + 4 - 1;
00107 uint size = last_byte_of_pesdata + _pesdata - _fullbuffer;
00108
00109 if (_pesdata == _fullbuffer)
00110 {
00111 VERBOSE(VB_IMPORTANT, "WriteAsTSPackets _pesdata == _fullbuffer");
00112 return 0;
00113 }
00114
00115 memcpy(buf, _fullbuffer, TSPacket::SIZE);
00116 INCR_CC(cc); buf[3] = buf[3] & 0xf0 | cc;
00117 if (size <= TSPacket::SIZE)
00118 return TSPacket::SIZE;
00119
00120 TSHeader header;
00121 header.data()[1] = 0x00;
00122 header.data()[2] = 0x00;
00123 header.data()[3] = 0x10;
00124 header.SetPID(tsheader()->PID());
00125
00126 uint ret = TSPacket::SIZE;
00127 unsigned char *out = buf + TSPacket::SIZE;
00128 const unsigned char *data = _fullbuffer + TSPacket::SIZE;
00129 size -= TSPacket::SIZE;
00130 while (size > TSPacket::PAYLOAD_SIZE)
00131 {
00132 INCR_CC(cc);
00133 header.SetContinuityCounter(cc);
00134 memcpy(out, header.data(), TSPacket::HEADER_SIZE);
00135 memcpy(out + 4, data, TSPacket::PAYLOAD_SIZE);
00136 data += TSPacket::PAYLOAD_SIZE;
00137 size -= TSPacket::PAYLOAD_SIZE;
00138 out += TSPacket::SIZE;
00139 ret += TSPacket::SIZE;
00140 }
00141
00142 if (size)
00143 {
00144 INCR_CC(cc);
00145 header.SetContinuityCounter(cc);
00146 memcpy(out, header.data(), TSPacket::HEADER_SIZE);
00147 memcpy(out + 4, data, size);
00148 memset(out + 4 + size, 0xff, TSPacket::PAYLOAD_SIZE - size);
00149 ret += TSPacket::SIZE;
00150 }
00151
00152 return ret;
00153 #undef INCR_CC
00154 }
00155
00156 uint PESPacket::CalcCRC(void) const
00157 {
00158 if (Length() < 1)
00159 return 0xffffffff;
00160 return bswap_32(av_crc(av_crc04C11DB7, (uint32_t) -1,
00161 _pesdata, Length() - 1));
00162 }
00163
00164 bool PESPacket::VerifyCRC(void) const
00165 {
00166 bool ret = !HasCRC() || (CalcCRC() == CRC());
00167 if (!ret)
00168 {
00169 VERBOSE(VB_SIPARSER,
00170 QString("PESPacket: Failed CRC check 0x%1 != 0x%2 "
00171 "for StreamID = 0x%3")
00172 .arg(CRC(),0,16).arg(CalcCRC(),0,16).arg(StreamID(),0,16));
00173 }
00174 return ret;
00175 }
00176
00177
00178 const float SequenceHeader::mpeg1_aspect[16] =
00179 {
00180 0.0000f, 1.0000f, 0.6735f, 0.7031f,
00181 0.7615f, 0.8055f, 0.8437f, 0.8935f,
00182 0.9157f, 0.9815f, 1.0255f, 1.0695f,
00183 1.0950f, 1.1575f, 1.2015f, 0.0000f,
00184 };
00185
00188 const float SequenceHeader::mpeg2_aspect[16] =
00189 {
00190 0.0000f, 1.0000f, -3.0/4.0, -9.0/16.0,
00191 -1.0/2.21, 0.0000f, 0.0000f, 0.0000f,
00192 0.0000f, 0.0000f, 0.0000f, 0.0000f,
00193 0.0000f, 0.0000f, 0.0000f, 0.0000f,
00194 };
00195
00196 const float SequenceHeader::mpeg2_fps[16] =
00197 {
00198 0.0f, 24000/1001.0f, 24.0f, 25.0f,
00199 30000/1001.0f, 30.0f, 50.0f, 60000/1001.0f,
00200 60.0f, 1.0f, 1.0f, 1.0f,
00201 1.0f, 1.0f, 1.0f, 1.0f,
00202 };
00203
00205 float SequenceHeader::aspect(bool mpeg1) const
00206 {
00207 if (!height())
00208 return 1.0f;
00209
00210 uint index = aspectNum();
00211 float aspect = (mpeg1) ? mpeg1_aspect[index] : mpeg2_aspect[index];
00212
00213 float retval = 0.0f;
00214 retval = (aspect > 0.0f) ? width() / (aspect * height()) : retval;
00215 retval = (aspect < 0.0f) ? -1.0f / aspect : retval;
00216 retval = (retval <= 0.0f) ? width() * 1.0f / height() : retval;
00217 return retval;
00218 }
00219
00220
00221
00223
00225
00226 static vector<unsigned char*> mem188;
00227 static vector<unsigned char*> free188;
00228 static map<unsigned char*, bool> alloc188;
00229
00230 static vector<unsigned char*> mem4096;
00231 static vector<unsigned char*> free4096;
00232 static map<unsigned char*, bool> alloc4096;
00233
00234 #define BLOCKS188 512
00235 static unsigned char* get_188_block()
00236 {
00237 if (free188.empty())
00238 {
00239 mem188.push_back((unsigned char*) malloc(188 * BLOCKS188));
00240 free188.reserve(BLOCKS188);
00241 unsigned char* block_start = mem188.back();
00242 for (uint i = 0; i < BLOCKS188; ++i)
00243 free188.push_back(i*188 + block_start);
00244 }
00245
00246 unsigned char *ptr = free188.back();
00247 free188.pop_back();
00248 alloc188[ptr] = true;
00249 return ptr;
00250 }
00251 #undef BLOCKS188
00252
00253 static bool is_188_block(unsigned char* ptr)
00254 {
00255 return alloc188.find(ptr) != alloc188.end();
00256 }
00257
00258 static void return_188_block(unsigned char* ptr)
00259 {
00260 alloc188.erase(ptr);
00261 free188.push_back(ptr);
00262
00263 if (alloc188.empty() && mem188.size() > 1)
00264 {
00265 vector<unsigned char*>::iterator it;
00266 for (it = mem188.begin(); it != mem188.end(); ++it)
00267 free(*it);
00268 mem188.clear();
00269 free188.clear();
00270
00271 }
00272 }
00273
00274 #define BLOCKS4096 128
00275 static unsigned char* get_4096_block()
00276 {
00277 if (free4096.empty())
00278 {
00279 mem4096.push_back((unsigned char*) malloc(4096 * BLOCKS4096));
00280 free4096.reserve(BLOCKS4096);
00281 unsigned char* block_start = mem4096.back();
00282 for (uint i = 0; i < BLOCKS4096; ++i)
00283 free4096.push_back(i*4096 + block_start);
00284 }
00285
00286 unsigned char *ptr = free4096.back();
00287 free4096.pop_back();
00288 alloc4096[ptr] = true;
00289 return ptr;
00290 }
00291 #undef BLOCKS4096
00292
00293 static bool is_4096_block(unsigned char* ptr)
00294 {
00295 return alloc4096.find(ptr) != alloc4096.end();
00296 }
00297
00298 static void return_4096_block(unsigned char* ptr)
00299 {
00300 alloc4096.erase(ptr);
00301 free4096.push_back(ptr);
00302
00303 #if 0 // enable this to debug memory leaks
00304 cerr<<alloc4096.size()<<" 4096 blocks remain"<<endl;
00305 map<unsigned char*, bool>::iterator it;
00306 for (it = alloc4096.begin(); it != alloc4096.end(); ++it)
00307 {
00308 TSPacket *ts = (TSPacket*) it->first;
00309 cerr<<QString("PES Packet: pid(0x%1)").arg(ts->PID(),0,16);
00310 if (ts->PID() == 0x1ffb)
00311 {
00312 cerr<<QString(" tid(0x%1) ext(0x%2)")
00313 .arg(PSIPTable::View(*ts).TableID(),0,16)
00314 .arg(PSIPTable::View(*ts).TableIDExtension(),0,16);
00315 }
00316 cerr<<endl;
00317 }
00318 #endif
00319
00320
00321 if (alloc4096.empty() && mem4096.size() > 1)
00322 {
00323 vector<unsigned char*>::iterator it;
00324 for (it = mem4096.begin(); it != mem4096.end(); ++it)
00325 free(*it);
00326 mem4096.clear();
00327 free4096.clear();
00328
00329 }
00330 }
00331
00332 static QMutex pes_alloc_mutex;
00333
00334 unsigned char *pes_alloc(uint size)
00335 {
00336 #ifndef USING_VALGRIND
00337 QMutexLocker locker(&pes_alloc_mutex);
00338 if (size <= 188)
00339 return get_188_block();
00340 else if (size <= 4096)
00341 return get_4096_block();
00342 #endif
00343 return (unsigned char*) malloc(size);
00344 }
00345
00346 void pes_free(unsigned char *ptr)
00347 {
00348 #ifndef USING_VALGRIND
00349 QMutexLocker locker(&pes_alloc_mutex);
00350 if (is_188_block(ptr))
00351 return_188_block(ptr);
00352 else if (is_4096_block(ptr))
00353 return_4096_block(ptr);
00354 else
00355 #endif
00356 free(ptr);
00357 }