00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "MPEG2TransportStreamMultiplexor.hh"
00023
00024 #define TRANSPORT_PACKET_SIZE 188
00025
00026 #define PAT_FREQUENCY 100 // # of packets between Program Association Tables
00027 #define PMT_FREQUENCY 500 // # of packets between Program Map Tables
00028
00029 #define PID_TABLE_SIZE 256
00030
00031 MPEG2TransportStreamMultiplexor
00032 ::MPEG2TransportStreamMultiplexor(UsageEnvironment& env)
00033 : FramedSource(env),
00034 fHaveVideoStreams(True),
00035 fOutgoingPacketCounter(0), fProgramMapVersion(0),
00036 fPreviousInputProgramMapVersion(0xFF), fCurrentInputProgramMapVersion(0xFF),
00037 fPCR_PID(0), fCurrentPID(0),
00038 fInputBuffer(NULL), fInputBufferSize(0), fInputBufferBytesUsed(0) {
00039 for (unsigned i = 0; i < PID_TABLE_SIZE; ++i) {
00040 fPIDState[i].counter = 0;
00041 fPIDState[i].streamType = 0;
00042 }
00043 }
00044
00045 MPEG2TransportStreamMultiplexor::~MPEG2TransportStreamMultiplexor() {
00046 }
00047
00048 void MPEG2TransportStreamMultiplexor::doGetNextFrame() {
00049 if (fInputBufferBytesUsed >= fInputBufferSize) {
00050
00051
00052 awaitNewBuffer(fInputBuffer);
00053 return;
00054 }
00055
00056 do {
00057
00058 if (fOutgoingPacketCounter++ % PAT_FREQUENCY == 0) {
00059 deliverPATPacket();
00060 break;
00061 }
00062
00063
00064 Boolean programMapHasChanged = fPIDState[fCurrentPID].counter == 0
00065 || fCurrentInputProgramMapVersion != fPreviousInputProgramMapVersion;
00066 if (fOutgoingPacketCounter % PMT_FREQUENCY == 0 || programMapHasChanged) {
00067 if (programMapHasChanged) {
00068 fPIDState[fCurrentPID].counter = 1;
00069 fPreviousInputProgramMapVersion = fCurrentInputProgramMapVersion;
00070 }
00071 deliverPMTPacket(programMapHasChanged);
00072 break;
00073 }
00074
00075
00076 deliverDataToClient(fCurrentPID, fInputBuffer, fInputBufferSize,
00077 fInputBufferBytesUsed);
00078 } while (0);
00079
00080
00081
00082 afterGetting(this);
00083 }
00084
00085 void MPEG2TransportStreamMultiplexor
00086 ::handleNewBuffer(unsigned char* buffer, unsigned bufferSize,
00087 int mpegVersion, MPEG1or2Demux::SCR scr) {
00088 if (bufferSize < 4) return;
00089 fInputBuffer = buffer;
00090 fInputBufferSize = bufferSize;
00091 fInputBufferBytesUsed = 0;
00092
00093 u_int8_t stream_id = fInputBuffer[3];
00094
00095
00096 if (stream_id == 0xBE) {
00097 fInputBufferSize = 0;
00098 } else if (stream_id == 0xBC) {
00099 setProgramStreamMap(fInputBufferSize);
00100 fInputBufferSize = 0;
00101 } else {
00102 fCurrentPID = stream_id;
00103
00104
00105 u_int8_t& streamType = fPIDState[fCurrentPID].streamType;
00106
00107 if (streamType == 0) {
00108
00109
00110 if ((stream_id&0xF0) == 0xE0) {
00111 streamType = mpegVersion == 1 ? 1 : 2;
00112 if (fPCR_PID == 0) fPCR_PID = fCurrentPID;
00113 } else if ((stream_id&0xE0) == 0xC0) {
00114 streamType = mpegVersion == 1 ? 3 : 4;
00115 if (!fHaveVideoStreams && fPCR_PID == 0) fPCR_PID = fCurrentPID;
00116 } else if (stream_id == 0xBD) {
00117 streamType = 0x06;
00118 } else {
00119 streamType = 0x81;
00120 }
00121 }
00122
00123 if (fCurrentPID == fPCR_PID) {
00124
00125 fPCR = scr;
00126 }
00127 }
00128
00129
00130 doGetNextFrame();
00131 }
00132
00133 void MPEG2TransportStreamMultiplexor
00134 ::deliverDataToClient(u_int8_t pid, unsigned char* buffer, unsigned bufferSize,
00135 unsigned& startPositionInBuffer) {
00136
00137 if (fMaxSize < TRANSPORT_PACKET_SIZE) {
00138 fFrameSize = 0;
00139 fNumTruncatedBytes = TRANSPORT_PACKET_SIZE;
00140 } else {
00141 fFrameSize = TRANSPORT_PACKET_SIZE;
00142 Boolean willAddPCR = pid == fPCR_PID && startPositionInBuffer == 0
00143 && !(fPCR.highBit == 0 && fPCR.remainingBits == 0 && fPCR.extension == 0);
00144 unsigned const numBytesAvailable = bufferSize - startPositionInBuffer;
00145 unsigned numHeaderBytes = 4;
00146 unsigned numPCRBytes = 0;
00147 unsigned numPaddingBytes = 0;
00148 unsigned numDataBytes;
00149 u_int8_t adaptation_field_control;
00150 if (willAddPCR) {
00151 adaptation_field_control = 0x30;
00152 numHeaderBytes += 2;
00153 numPCRBytes = 6;
00154 if (numBytesAvailable >= TRANSPORT_PACKET_SIZE - numHeaderBytes - numPCRBytes) {
00155 numDataBytes = TRANSPORT_PACKET_SIZE - numHeaderBytes - numPCRBytes;
00156 } else {
00157 numDataBytes = numBytesAvailable;
00158 numPaddingBytes
00159 = TRANSPORT_PACKET_SIZE - numHeaderBytes - numPCRBytes - numDataBytes;
00160 }
00161 } else if (numBytesAvailable >= TRANSPORT_PACKET_SIZE - numHeaderBytes) {
00162
00163 adaptation_field_control = 0x10;
00164 numDataBytes = TRANSPORT_PACKET_SIZE - numHeaderBytes;
00165 } else {
00166 adaptation_field_control = 0x30;
00167 ++numHeaderBytes;
00168
00169 numDataBytes = numBytesAvailable;
00170 if (numDataBytes < TRANSPORT_PACKET_SIZE - numHeaderBytes) {
00171 ++numHeaderBytes;
00172 numPaddingBytes = TRANSPORT_PACKET_SIZE - numHeaderBytes - numDataBytes;
00173 }
00174 }
00175
00176
00177
00178
00179 unsigned char* header = fTo;
00180 *header++ = 0x47;
00181 *header++ = (startPositionInBuffer == 0) ? 0x40 : 0x00;
00182
00183
00184 *header++ = pid;
00185
00186 unsigned& continuity_counter = fPIDState[pid].counter;
00187 *header++ = adaptation_field_control|(continuity_counter&0x0F);
00188
00189 ++continuity_counter;
00190 if (adaptation_field_control == 0x30) {
00191
00192 u_int8_t adaptation_field_length
00193 = (numHeaderBytes == 5) ? 0 : 1 + numPCRBytes + numPaddingBytes;
00194 *header++ = adaptation_field_length;
00195 if (numHeaderBytes > 5) {
00196 *header++ = willAddPCR ? 0x10 : 0x00;
00197 if (willAddPCR) {
00198 u_int32_t pcrHigh32Bits = (fPCR.highBit<<31) | (fPCR.remainingBits>>1);
00199 u_int8_t pcrLowBit = fPCR.remainingBits&1;
00200 u_int8_t extHighBit = (fPCR.extension&0x100)>>8;
00201 *header++ = pcrHigh32Bits>>24;
00202 *header++ = pcrHigh32Bits>>16;
00203 *header++ = pcrHigh32Bits>>8;
00204 *header++ = pcrHigh32Bits;
00205 *header++ = (pcrLowBit<<7)|0x7E|extHighBit;
00206 *header++ = (u_int8_t)fPCR.extension;
00207 }
00208 }
00209 }
00210
00211
00212 for (unsigned i = 0; i < numPaddingBytes; ++i) *header++ = 0xFF;
00213
00214
00215 memmove(header, &buffer[startPositionInBuffer], numDataBytes);
00216 startPositionInBuffer += numDataBytes;
00217 }
00218 }
00219
00220 static u_int32_t calculateCRC(u_int8_t* data, unsigned dataLength);
00221
00222 #define PAT_PID 0
00223 #define OUR_PROGRAM_NUMBER 1
00224 #define OUR_PROGRAM_MAP_PID 0x10
00225
00226 void MPEG2TransportStreamMultiplexor::deliverPATPacket() {
00227
00228 unsigned const patSize = TRANSPORT_PACKET_SIZE - 4;
00229 unsigned char* patBuffer = new unsigned char[patSize];
00230
00231
00232 unsigned char* pat = patBuffer;
00233 *pat++ = 0;
00234 *pat++ = 0;
00235 *pat++ = 0xB0;
00236 *pat++ = 13;
00237 *pat++ = 0; *pat++ = 1;
00238 *pat++ = 0xC3;
00239 *pat++ = 0;
00240 *pat++ = 0;
00241 *pat++ = OUR_PROGRAM_NUMBER>>8; *pat++ = OUR_PROGRAM_NUMBER;
00242 *pat++ = 0xE0|(OUR_PROGRAM_MAP_PID>>8);
00243 *pat++ = OUR_PROGRAM_MAP_PID;
00244
00245
00246 u_int32_t crc = calculateCRC(patBuffer+1, pat - (patBuffer+1));
00247 *pat++ = crc>>24; *pat++ = crc>>16; *pat++ = crc>>8; *pat++ = crc;
00248
00249
00250 while (pat < &patBuffer[patSize]) *pat++ = 0xFF;
00251
00252
00253 unsigned startPosition = 0;
00254 deliverDataToClient(PAT_PID, patBuffer, patSize, startPosition);
00255
00256
00257 delete[] patBuffer;
00258 }
00259
00260 void MPEG2TransportStreamMultiplexor::deliverPMTPacket(Boolean hasChanged) {
00261 if (hasChanged) ++fProgramMapVersion;
00262
00263
00264 unsigned const pmtSize = TRANSPORT_PACKET_SIZE - 4;
00265 unsigned char* pmtBuffer = new unsigned char[pmtSize];
00266
00267
00268 unsigned char* pmt = pmtBuffer;
00269 *pmt++ = 0;
00270 *pmt++ = 2;
00271 *pmt++ = 0xB0;
00272 unsigned char* section_lengthPtr = pmt;
00273 *pmt++ = 0;
00274 *pmt++ = OUR_PROGRAM_NUMBER>>8; *pmt++ = OUR_PROGRAM_NUMBER;
00275 *pmt++ = 0xC1|((fProgramMapVersion&0x1F)<<1);
00276 *pmt++ = 0;
00277 *pmt++ = 0;
00278 *pmt++ = 0xE0;
00279 *pmt++ = fPCR_PID;
00280 *pmt++ = 0xF0;
00281 *pmt++ = 0;
00282 for (int pid = 0; pid < PID_TABLE_SIZE; ++pid) {
00283 if (fPIDState[pid].streamType != 0) {
00284
00285 *pmt++ = fPIDState[pid].streamType;
00286 *pmt++ = 0xE0;
00287 *pmt++ = pid;
00288 *pmt++ = 0xF0;
00289 *pmt++ = 0;
00290 }
00291 }
00292 unsigned section_length = pmt - (section_lengthPtr+1) + 4 ;
00293 *section_lengthPtr = section_length;
00294
00295
00296 u_int32_t crc = calculateCRC(pmtBuffer+1, pmt - (pmtBuffer+1));
00297 *pmt++ = crc>>24; *pmt++ = crc>>16; *pmt++ = crc>>8; *pmt++ = crc;
00298
00299
00300 while (pmt < &pmtBuffer[pmtSize]) *pmt++ = 0xFF;
00301
00302
00303 unsigned startPosition = 0;
00304 deliverDataToClient(OUR_PROGRAM_MAP_PID, pmtBuffer, pmtSize, startPosition);
00305
00306
00307 delete[] pmtBuffer;
00308 }
00309
00310 void MPEG2TransportStreamMultiplexor::setProgramStreamMap(unsigned frameSize) {
00311 if (frameSize <= 16) return;
00312 if (frameSize > 0xFF) return;
00313
00314 u_int16_t program_stream_map_length = (fInputBuffer[4]<<8) | fInputBuffer[5];
00315 if ((u_int16_t)frameSize > 6+program_stream_map_length) {
00316 frameSize = 6+program_stream_map_length;
00317 }
00318
00319 u_int8_t versionByte = fInputBuffer[6];
00320 if ((versionByte&0x80) == 0) return;
00321 fCurrentInputProgramMapVersion = versionByte&0x1F;
00322
00323 u_int16_t program_stream_info_length = (fInputBuffer[8]<<8) | fInputBuffer[9];
00324 unsigned offset = 10 + program_stream_info_length;
00325
00326 u_int16_t elementary_stream_map_length
00327 = (fInputBuffer[offset]<<8) | fInputBuffer[offset+1];
00328 offset += 2;
00329 frameSize -= 4;
00330 if (frameSize > offset + elementary_stream_map_length) {
00331 frameSize = offset + elementary_stream_map_length;
00332 }
00333
00334 while (offset + 4 <= frameSize) {
00335 u_int8_t stream_type = fInputBuffer[offset];
00336 u_int8_t elementary_stream_id = fInputBuffer[offset+1];
00337
00338 fPIDState[elementary_stream_id].streamType = stream_type;
00339
00340 u_int16_t elementary_stream_info_length
00341 = (fInputBuffer[offset+2]<<8) | fInputBuffer[offset+3];
00342 offset += 4 + elementary_stream_info_length;
00343 }
00344 }
00345
00346 static u_int32_t CRC32[256] = {
00347 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
00348 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
00349 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
00350 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
00351 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
00352 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
00353 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
00354 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
00355 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
00356 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
00357 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
00358 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
00359 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
00360 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
00361 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
00362 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
00363 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
00364 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
00365 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
00366 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
00367 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
00368 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
00369 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
00370 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
00371 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
00372 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
00373 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
00374 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
00375 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
00376 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
00377 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
00378 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
00379 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
00380 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
00381 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
00382 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
00383 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
00384 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
00385 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
00386 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
00387 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
00388 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
00389 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
00390 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
00391 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
00392 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
00393 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
00394 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
00395 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
00396 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
00397 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
00398 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
00399 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
00400 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
00401 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
00402 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
00403 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
00404 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
00405 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
00406 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
00407 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
00408 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
00409 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
00410 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
00411 };
00412
00413 static u_int32_t calculateCRC(u_int8_t* data, unsigned dataLength) {
00414 u_int32_t crc = 0xFFFFFFFF;
00415
00416 while (dataLength-- > 0) {
00417 crc = (crc<<8) ^ CRC32[(crc>>24) ^ (u_int32_t)(*data++)];
00418 }
00419
00420 return crc;
00421 }