1 /* 2 * Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de> 3 * 4 * Permission is hereby granted, free of charge, to any person 5 * obtaining a copy of this software and associated documentation 6 * files (the "Software"), to deal in the Software without restriction, 7 * including without limitation the rights to use, copy, modify, 8 * merge, publish, distribute, sublicense, and/or sell copies of 9 * the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25 #include <stdio.h> 26 #include <fcntl.h> 27 #include <unistd.h> 28 #include <stdlib.h> 29 #include <string.h> 30 31 #include "TransportStreamDemux.h" 32 #include "Packet.h" 33 #include "PacketQueue.h" 34 35 #define TRACE_TS_DEMUX 36 #ifdef TRACE_TS_DEMUX 37 #define TRACE printf 38 #else 39 #define TRACE(a...) 40 #endif 41 42 #define CLOCK_TO_USEC(clck) (bigtime_t((clck) + 13) / 27) 43 #define USEC_TO_CLOCK(usec) (bigtime_t((usec) * 27)) 44 45 46 TransportStreamDemux::TransportStreamDemux( 47 PacketQueue *vid_queue, PacketQueue *aud_queue, 48 PacketQueue *vid_queue2, PacketQueue *aud_queue2, 49 PacketQueue *mpeg_ts_queue) 50 : fCount(0) 51 , fSystemTime(0) 52 , fPerformanceTime(0) 53 , fLastEndTime(0) 54 , fVidPid(-1) 55 , fAudPid(-1) 56 , fPcrPid(-1) 57 , fVidQueue(vid_queue) 58 , fVidQueue2(vid_queue2) 59 , fAudQueue(aud_queue) 60 , fAudQueue2(aud_queue2) 61 , fMpegTsQueue(mpeg_ts_queue) 62 , fVidPacket(new Packet) 63 , fAudPacket(new Packet) 64 , fVidPacketValid(false) 65 , fAudPacketValid(false) 66 { 67 } 68 69 70 TransportStreamDemux::~TransportStreamDemux() 71 { 72 delete fVidPacket; 73 delete fAudPacket; 74 } 75 76 77 void 78 TransportStreamDemux::SetPIDs(int vid_pid, int aud_pid, int pcr_pid) 79 { 80 fVidPacket->MakeEmpty(); 81 fAudPacket->MakeEmpty(); 82 fVidPacketValid = false; 83 fAudPacketValid = false; 84 fVidPid = vid_pid; 85 fAudPid = aud_pid; 86 fPcrPid = pcr_pid; 87 } 88 89 90 void 91 TransportStreamDemux::ProcessPacket(const mpeg_ts_packet *pkt, bigtime_t start_time) 92 { 93 fCount++; 94 95 // printf("ProcessPacket %lld\n", fCount); 96 97 if (pkt->SyncByte() != 0x47) { 98 // fCountInvalid++; 99 printf("packet %lld sync byte error " 100 "%02x %02x %02x %02x %02x %02x %02x %02x " 101 "%02x %02x %02x %02x %02x %02x %02x %02x\n", fCount, 102 pkt->header[0], pkt->header[1], pkt->header[2], pkt->header[3], 103 pkt->data[0], pkt->data[1], pkt->data[2], pkt->data[3], 104 pkt->data[4], pkt->data[5], pkt->data[6], pkt->data[7], 105 pkt->data[8], pkt->data[9], pkt->data[10], pkt->data[11]); 106 return; 107 } 108 109 // if (pkt->TransportError()) { 110 // fCountInvalid++; 111 // printf("invalid packet %lld (transport_error_indicator)\n", fCount); 112 // return; 113 // } 114 115 int pid = pkt->PID(); 116 117 if (pid == 0) { 118 ProcessPAT(pkt); 119 return; 120 } 121 122 if (pid == fPcrPid) { 123 ProcessPCR(pkt, start_time); 124 } 125 126 if (pid == fAudPid) { 127 ProcessAUD(pkt); 128 } 129 130 if (pid == fVidPid) { 131 ProcessVID(pkt); 132 } 133 } 134 135 136 void 137 TransportStreamDemux::ProcessPAT(const mpeg_ts_packet *pkt) 138 { 139 } 140 141 142 void 143 TransportStreamDemux::ProcessPCR(const mpeg_ts_packet *pkt, bigtime_t start_time) 144 { 145 if (!(pkt->AdaptationFieldControl() & 0x2)) // adaptation field present? 146 return; 147 if (pkt->data[0] < 7) // long enough? 148 return; 149 if (!(pkt->data[1] & 0x10)) // PCR present? 150 return; 151 int64 pcr; 152 pcr = (uint64(pkt->data[2]) << 25) 153 | (uint32(pkt->data[3]) << 17) 154 | (uint32(pkt->data[4]) << 9) 155 | (uint32(pkt->data[5]) << 1) 156 | (pkt->data[6] >> 7); 157 pcr *= 300; 158 pcr += (pkt->data[6] & 1) | pkt->data[7]; 159 // printf(" pcr = %lld\n", pcr); 160 161 // bigtime_t now = system_time(); 162 // printf("system_time %.3f, PCR-time %.3f, delta %.06f, PCR %lld\n", now / 1e6, CLOCK_TO_USEC(pcr) / 1e6, (CLOCK_TO_USEC(pcr) - now) / 1e6, pcr); 163 164 // atomic_set64(&fCurrentTime, CLOCK_TO_USEC(pcr)); 165 166 fTimeSourceLocker.Lock(); 167 fSystemTime = start_time; 168 fPerformanceTime = CLOCK_TO_USEC(pcr); 169 fTimeSourceLocker.Unlock(); 170 } 171 172 173 void 174 TransportStreamDemux::ProcessAUD(const mpeg_ts_packet *pkt) 175 { 176 // flush old packet 177 if (pkt->PayloadUnitStart()) { 178 if (fAudPacketValid) { 179 Packet *clone = new Packet(*fAudPacket); 180 status_t err = fAudQueue->Insert(fAudPacket); 181 if (err != B_OK) { 182 delete fAudPacket; 183 if (err == B_WOULD_BLOCK) { 184 printf("fAudQueue->Insert failed (would block)\n"); 185 } 186 } 187 err = fAudQueue2->Insert(clone); 188 if (err != B_OK) { 189 delete clone; 190 if (err == B_WOULD_BLOCK) { 191 printf("fAudQueue2->Insert failed (would block)\n"); 192 } 193 } 194 fAudPacket = new Packet; 195 } else { 196 fAudPacket->MakeEmpty(); 197 fAudPacketValid = true; 198 } 199 } 200 201 int skip; 202 switch (pkt->AdaptationFieldControl()) { 203 case 0: // illegal 204 skip = 184; 205 break; 206 case 1: // payload only 207 skip = 0; 208 break; 209 case 2: // adaptation field only 210 skip = 184; 211 break; 212 case 3: // adaptation field followed by payload 213 skip = pkt->data[0] + 1; 214 if (skip > 184) 215 skip = 184; 216 break; 217 default: 218 skip = 0; // stupid compiler, impossible case 219 } 220 221 const uint8 *data = pkt->data + skip; 222 int size = 184 - skip; 223 224 // if (skip != 0) 225 // printf("aud skip %d\n", skip); 226 227 if (pkt->PayloadUnitStart()) { 228 229 if (pkt->TransportError()) { 230 printf("error in audio packet %02x %02x %02x %02x\n", data[0], data[1], data[2], data[3]); 231 fAudPacketValid = false; 232 return; 233 } 234 235 if (data[0] || data[1] || data[2] != 0x01 || data[3] <= 0xbf || data[3] >= 0xf0) { 236 printf("invalid audio packet %02x %02x %02x %02x\n", data[0], data[1], data[2], data[3]); 237 fAudPacketValid = false; 238 return; 239 } 240 241 if (data[7] & 0x80) { // PTS 242 int64 pts; 243 int64 dts; 244 245 pts = (uint64((data[9] >> 1) & 0x7) << 30) 246 | (data[10] << 22) | ((data[11] >> 1) << 15) 247 | (data[12] << 7) | (data[13] >> 1); 248 pts *= 300; 249 250 // printf("vid pts = %lld\n", pts); 251 252 if (data[7] & 0x40) { // DTS 253 254 dts = (uint64((data[14] >> 1) & 0x7) << 30) 255 | (data[15] << 22) | ((data[16] >> 1) << 15) 256 | (data[17] << 7) | (data[18] >> 1); 257 dts *= 300; 258 259 // printf("aud dts = %lld\n", dts); 260 } else { 261 dts = pts; 262 } 263 264 fAudPacket->SetTimeStamp(CLOCK_TO_USEC(dts)); 265 } 266 267 268 // printf("aud %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", 269 // data[0], data[1], data[2], data[3], data[4], 270 // data[5], data[6], data[7], data[8], data[9]); 271 } 272 273 fAudPacket->AddData(data, size); 274 } 275 276 277 void 278 TransportStreamDemux::ProcessVID(const mpeg_ts_packet *pkt) 279 { 280 // flush old packet 281 // if (pkt->PayloadUnitStart() || pkt->TransportError()) { 282 if (pkt->PayloadUnitStart()) { 283 if (fVidPacketValid) { 284 Packet *clone = new Packet(*fVidPacket); 285 status_t err = fVidQueue->Insert(fVidPacket); 286 if (err != B_OK) { 287 delete fVidPacket; 288 if (err == B_WOULD_BLOCK) { 289 printf("fVidQueue->Insert failed (would block)\n"); 290 } 291 } 292 err = fVidQueue2->Insert(clone); 293 if (err != B_OK) { 294 delete clone; 295 if (err == B_WOULD_BLOCK) { 296 printf("fVidQueue2->Insert failed (would block)\n"); 297 } 298 } 299 fVidPacket = new Packet; 300 } else { 301 fVidPacket->MakeEmpty(); 302 fVidPacketValid = true; 303 } 304 } 305 306 // if (pkt->TransportError()) { 307 // printf("transport error\n"); 308 // fVidPacketValid = false; 309 // return; 310 // } 311 312 int skip; 313 switch (pkt->AdaptationFieldControl()) { 314 case 0: // illegal 315 skip = 184; 316 break; 317 case 1: // payload only 318 skip = 0; 319 break; 320 case 2: // adaptation field only 321 skip = 184; 322 break; 323 case 3: // adaptation field followed by payload 324 skip = pkt->data[0] + 1; 325 if (skip > 184) 326 skip = 184; 327 break; 328 default: 329 skip = 0; // stupid compiler, impossible case 330 } 331 332 const uint8 *data = pkt->data + skip; 333 int size = 184 - skip; 334 335 // if (skip != 0) 336 // printf("vid skip %d\n", skip); 337 338 if (pkt->PayloadUnitStart()) { 339 340 if (pkt->TransportError()) { 341 printf("error in video packet %02x %02x %02x %02x\n", data[0], data[1], data[2], data[3]); 342 fVidPacketValid = false; 343 return; 344 } 345 346 if (data[0] || data[1] || data[2] != 0x01 || data[3] <= 0xbf || data[3] >= 0xf0) { 347 printf("invalid video packet %02x %02x %02x %02x\n", data[0], data[1], data[2], data[3]); 348 fVidPacketValid = false; 349 return; 350 } 351 352 if (data[7] & 0x80) { // PTS 353 int64 pts; 354 int64 dts; 355 356 pts = (uint64((data[9] >> 1) & 0x7) << 30) 357 | (data[10] << 22) | ((data[11] >> 1) << 15) 358 | (data[12] << 7) | (data[13] >> 1); 359 pts *= 300; 360 361 // printf("vid pts = %lld\n", pts); 362 363 if (data[7] & 0x40) { // DTS 364 365 dts = (uint64((data[14] >> 1) & 0x7) << 30) 366 | (data[15] << 22) | ((data[16] >> 1) << 15) 367 | (data[17] << 7) | (data[18] >> 1); 368 dts *= 300; 369 370 // printf("vid dts = %lld\n", dts); 371 // printf("dts = %lld, pts = %lld, delta %lld ### dts = %lld, pts = %lld, delta %lld\n", 372 // dts, pts, pts - dts, CLOCK_TO_USEC(dts), CLOCK_TO_USEC(pts), CLOCK_TO_USEC(pts - dts)); 373 } else { 374 dts = pts; 375 } 376 377 // printf("clocks: dts = %14Ld, pts = %14Ld, delta %8Ld ### usec: dts = %14Ld, pts = %14Ld, delta %8Ld\n", 378 // dts, pts, pts - dts, CLOCK_TO_USEC(dts), CLOCK_TO_USEC(pts), CLOCK_TO_USEC(pts - dts)); 379 380 fVidPacket->SetTimeStamp(CLOCK_TO_USEC(dts)); 381 } 382 383 // printf("vid %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", 384 // data[0], data[1], data[2], data[3], data[4], 385 // data[5], data[6], data[7], data[8], data[9]); 386 } 387 388 fVidPacket->AddData(data, size); 389 } 390 391 392 inline void 393 TransportStreamDemux::ProcessData(const void *data, int size, bigtime_t start_time, bigtime_t delta) 394 { 395 const uint8 *d = (const uint8 *)data; 396 if (d[0] != 0x47 && size > 376 && d[188] != 0x47 && d[376] != 0x47) { 397 printf("TransportStreamDemux::ProcessData: input sync error: " 398 "%02x %02x %02x %02x %02x %02x %02x %02x " 399 "%02x %02x %02x %02x %02x %02x %02x %02x\n", 400 d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], 401 d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); 402 return; 403 } 404 405 const mpeg_ts_packet *pkt = (const mpeg_ts_packet *)data; 406 int count = size / 188; 407 for (int i = 0; i < count; i++) { 408 ProcessPacket(pkt++, start_time + (i * delta) / count); 409 } 410 } 411 412 413 void 414 TransportStreamDemux::AddData(Packet *packet) 415 { 416 bigtime_t end_time = packet->TimeStamp(); 417 418 if (fLastEndTime == 0) { 419 #define DEFAULT_DELTA 36270 420 // need something at the start, 36270 usec is the packet length 421 // in Germany, and should be ok for other countries, too 422 fLastEndTime = end_time - DEFAULT_DELTA; 423 } 424 425 bigtime_t delta = end_time - fLastEndTime; 426 427 // sanity check 428 if (delta > (3 * DEFAULT_DELTA)) { 429 printf("TransportStreamDemux::ProcessData: delta %.6f is too large\n", delta / 1E6); 430 fLastEndTime = end_time - DEFAULT_DELTA; 431 delta = DEFAULT_DELTA; 432 } 433 434 ProcessData(packet->Data(), packet->Size(), fLastEndTime, delta); 435 436 packet->SetTimeStamp(fLastEndTime); 437 438 fLastEndTime = end_time; 439 440 status_t err = fMpegTsQueue->Insert(packet); 441 if (err != B_OK) { 442 delete packet; 443 if (err == B_WOULD_BLOCK) { 444 printf("fMpegTsQueue->Insert failed (would block)\n"); 445 } 446 } 447 } 448 449