MPEG2TSWriter.cpp revision 0da4dab0a45a2bc1d95cbc6ef6a4850ed2569584
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17//#define LOG_NDEBUG 0 18#define LOG_TAG "MPEG2TSWriter" 19#include <media/stagefright/foundation/ADebug.h> 20 21#include <media/stagefright/foundation/hexdump.h> 22#include <media/stagefright/foundation/ABuffer.h> 23#include <media/stagefright/foundation/AMessage.h> 24#include <media/stagefright/MPEG2TSWriter.h> 25#include <media/stagefright/MediaBuffer.h> 26#include <media/stagefright/MediaDefs.h> 27#include <media/stagefright/MediaErrors.h> 28#include <media/stagefright/MediaSource.h> 29#include <media/stagefright/MetaData.h> 30#include <media/stagefright/Utils.h> 31 32#include "include/ESDS.h" 33 34namespace android { 35 36struct MPEG2TSWriter::SourceInfo : public AHandler { 37 SourceInfo(const sp<MediaSource> &source); 38 39 void start(const sp<AMessage> ¬ify); 40 void stop(); 41 42 unsigned streamType() const; 43 unsigned incrementContinuityCounter(); 44 45 enum { 46 kNotifyStartFailed, 47 kNotifyBuffer, 48 kNotifyReachedEOS, 49 }; 50 51protected: 52 virtual void onMessageReceived(const sp<AMessage> &msg); 53 54 virtual ~SourceInfo(); 55 56private: 57 enum { 58 kWhatStart = 'strt', 59 kWhatRead = 'read', 60 }; 61 62 sp<MediaSource> mSource; 63 sp<ALooper> mLooper; 64 sp<AMessage> mNotify; 65 66 sp<ABuffer> mAACBuffer; 67 68 unsigned mStreamType; 69 unsigned mContinuityCounter; 70 71 void extractCodecSpecificData(); 72 73 void appendAACFrames(MediaBuffer *buffer); 74 void flushAACFrames(); 75 76 void postAVCFrame(MediaBuffer *buffer); 77 78 DISALLOW_EVIL_CONSTRUCTORS(SourceInfo); 79}; 80 81MPEG2TSWriter::SourceInfo::SourceInfo(const sp<MediaSource> &source) 82 : mSource(source), 83 mLooper(new ALooper), 84 mStreamType(0), 85 mContinuityCounter(0) { 86 mLooper->setName("MPEG2TSWriter source"); 87 88 sp<MetaData> meta = mSource->getFormat(); 89 const char *mime; 90 CHECK(meta->findCString(kKeyMIMEType, &mime)); 91 92 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 93 mStreamType = 0x0f; 94 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 95 mStreamType = 0x1b; 96 } else { 97 TRESPASS(); 98 } 99} 100 101MPEG2TSWriter::SourceInfo::~SourceInfo() { 102} 103 104unsigned MPEG2TSWriter::SourceInfo::streamType() const { 105 return mStreamType; 106} 107 108unsigned MPEG2TSWriter::SourceInfo::incrementContinuityCounter() { 109 if (++mContinuityCounter == 16) { 110 mContinuityCounter = 0; 111 } 112 113 return mContinuityCounter; 114} 115 116void MPEG2TSWriter::SourceInfo::start(const sp<AMessage> ¬ify) { 117 mLooper->registerHandler(this); 118 mLooper->start(); 119 120 mNotify = notify; 121 122 (new AMessage(kWhatStart, id()))->post(); 123} 124 125void MPEG2TSWriter::SourceInfo::stop() { 126 mLooper->unregisterHandler(id()); 127 mLooper->stop(); 128} 129 130void MPEG2TSWriter::SourceInfo::extractCodecSpecificData() { 131 sp<MetaData> meta = mSource->getFormat(); 132 133 const char *mime; 134 CHECK(meta->findCString(kKeyMIMEType, &mime)); 135 136 if (strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 137 return; 138 } 139 140 sp<ABuffer> out = new ABuffer(1024); 141 out->setRange(0, 0); 142 143 uint32_t type; 144 const void *data; 145 size_t size; 146 CHECK(meta->findData(kKeyAVCC, &type, &data, &size)); 147 148 const uint8_t *ptr = (const uint8_t *)data; 149 150 size_t numSeqParameterSets = ptr[5] & 31; 151 152 ptr += 6; 153 size -= 6; 154 155 for (size_t i = 0; i < numSeqParameterSets; ++i) { 156 CHECK(size >= 2); 157 size_t length = U16_AT(ptr); 158 159 ptr += 2; 160 size -= 2; 161 162 CHECK(size >= length); 163 164 CHECK_LE(out->size() + 4 + length, out->capacity()); 165 memcpy(out->data() + out->size(), "\x00\x00\x00\x01", 4); 166 memcpy(out->data() + out->size() + 4, ptr, length); 167 out->setRange(0, out->size() + length + 4); 168 169 ptr += length; 170 size -= length; 171 } 172 173 CHECK(size >= 1); 174 size_t numPictureParameterSets = *ptr; 175 ++ptr; 176 --size; 177 178 for (size_t i = 0; i < numPictureParameterSets; ++i) { 179 CHECK(size >= 2); 180 size_t length = U16_AT(ptr); 181 182 ptr += 2; 183 size -= 2; 184 185 CHECK(size >= length); 186 187 CHECK_LE(out->size() + 4 + length, out->capacity()); 188 memcpy(out->data() + out->size(), "\x00\x00\x00\x01", 4); 189 memcpy(out->data() + out->size() + 4, ptr, length); 190 out->setRange(0, out->size() + length + 4); 191 192 ptr += length; 193 size -= length; 194 } 195 196 out->meta()->setInt64("timeUs", 0ll); 197 198 sp<AMessage> notify = mNotify->dup(); 199 notify->setInt32("what", kNotifyBuffer); 200 notify->setObject("buffer", out); 201 notify->post(); 202} 203 204void MPEG2TSWriter::SourceInfo::postAVCFrame(MediaBuffer *buffer) { 205 sp<AMessage> notify = mNotify->dup(); 206 notify->setInt32("what", kNotifyBuffer); 207 208 sp<ABuffer> copy = 209 new ABuffer(buffer->range_length()); 210 memcpy(copy->data(), 211 (const uint8_t *)buffer->data() 212 + buffer->range_offset(), 213 buffer->range_length()); 214 215 int64_t timeUs; 216 CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs)); 217 copy->meta()->setInt64("timeUs", timeUs); 218 219 int32_t isSync; 220 if (buffer->meta_data()->findInt32(kKeyIsSyncFrame, &isSync) 221 && isSync != 0) { 222 copy->meta()->setInt32("isSync", true); 223 } 224 225 notify->setObject("buffer", copy); 226 notify->post(); 227} 228 229void MPEG2TSWriter::SourceInfo::appendAACFrames(MediaBuffer *buffer) { 230 if (mAACBuffer != NULL 231 && mAACBuffer->size() + 7 + buffer->range_length() 232 > mAACBuffer->capacity()) { 233 flushAACFrames(); 234 } 235 236 if (mAACBuffer == NULL) { 237 size_t alloc = 4096; 238 if (buffer->range_length() + 7 > alloc) { 239 alloc = 7 + buffer->range_length(); 240 } 241 242 mAACBuffer = new ABuffer(alloc); 243 244 int64_t timeUs; 245 CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs)); 246 247 mAACBuffer->meta()->setInt64("timeUs", timeUs); 248 mAACBuffer->meta()->setInt32("isSync", true); 249 250 mAACBuffer->setRange(0, 0); 251 } 252 253 sp<MetaData> meta = mSource->getFormat(); 254 uint32_t type; 255 const void *data; 256 size_t size; 257 CHECK(meta->findData(kKeyESDS, &type, &data, &size)); 258 259 ESDS esds((const char *)data, size); 260 CHECK_EQ(esds.InitCheck(), (status_t)OK); 261 262 const uint8_t *codec_specific_data; 263 size_t codec_specific_data_size; 264 esds.getCodecSpecificInfo( 265 (const void **)&codec_specific_data, &codec_specific_data_size); 266 267 CHECK_GE(codec_specific_data_size, 2u); 268 269 unsigned profile = (codec_specific_data[0] >> 3) - 1; 270 271 unsigned sampling_freq_index = 272 ((codec_specific_data[0] & 7) << 1) 273 | (codec_specific_data[1] >> 7); 274 275 unsigned channel_configuration = 276 (codec_specific_data[1] >> 3) & 0x0f; 277 278 uint8_t *ptr = mAACBuffer->data() + mAACBuffer->size(); 279 280 const uint32_t aac_frame_length = buffer->range_length() + 7; 281 282 *ptr++ = 0xff; 283 *ptr++ = 0xf1; // b11110001, ID=0, layer=0, protection_absent=1 284 285 *ptr++ = 286 profile << 6 287 | sampling_freq_index << 2 288 | ((channel_configuration >> 2) & 1); // private_bit=0 289 290 // original_copy=0, home=0, copyright_id_bit=0, copyright_id_start=0 291 *ptr++ = 292 (channel_configuration & 3) << 6 293 | aac_frame_length >> 11; 294 *ptr++ = (aac_frame_length >> 3) & 0xff; 295 *ptr++ = (aac_frame_length & 7) << 5; 296 297 // adts_buffer_fullness=0, number_of_raw_data_blocks_in_frame=0 298 *ptr++ = 0; 299 300 memcpy(ptr, 301 (const uint8_t *)buffer->data() + buffer->range_offset(), 302 buffer->range_length()); 303 304 ptr += buffer->range_length(); 305 306 mAACBuffer->setRange(0, ptr - mAACBuffer->data()); 307} 308 309void MPEG2TSWriter::SourceInfo::flushAACFrames() { 310 if (mAACBuffer == NULL) { 311 return; 312 } 313 314 sp<AMessage> notify = mNotify->dup(); 315 notify->setInt32("what", kNotifyBuffer); 316 notify->setObject("buffer", mAACBuffer); 317 notify->post(); 318 319 mAACBuffer.clear(); 320} 321 322void MPEG2TSWriter::SourceInfo::onMessageReceived(const sp<AMessage> &msg) { 323 switch (msg->what()) { 324 case kWhatStart: 325 { 326 status_t err = mSource->start(); 327 if (err != OK) { 328 sp<AMessage> notify = mNotify->dup(); 329 notify->setInt32("what", kNotifyStartFailed); 330 notify->post(); 331 break; 332 } 333 334 extractCodecSpecificData(); 335 336 (new AMessage(kWhatRead, id()))->post(); 337 break; 338 } 339 340 case kWhatRead: 341 { 342 MediaBuffer *buffer; 343 status_t err = mSource->read(&buffer); 344 345 if (err != OK && err != INFO_FORMAT_CHANGED) { 346 if (mStreamType == 0x0f) { 347 flushAACFrames(); 348 } 349 350 sp<AMessage> notify = mNotify->dup(); 351 notify->setInt32("what", kNotifyReachedEOS); 352 notify->setInt32("status", err); 353 notify->post(); 354 break; 355 } 356 357 if (err == OK) { 358 if (buffer->range_length() > 0) { 359 if (mStreamType == 0x0f) { 360 appendAACFrames(buffer); 361 } else { 362 postAVCFrame(buffer); 363 } 364 } 365 366 buffer->release(); 367 buffer = NULL; 368 } 369 370 msg->post(); 371 break; 372 } 373 374 default: 375 TRESPASS(); 376 } 377} 378 379//////////////////////////////////////////////////////////////////////////////// 380 381MPEG2TSWriter::MPEG2TSWriter(const char *filename) 382 : mFile(fopen(filename, "wb")), 383 mStarted(false), 384 mNumSourcesDone(0), 385 mNumTSPacketsWritten(0), 386 mNumTSPacketsBeforeMeta(0) { 387 CHECK(mFile != NULL); 388 389 mLooper = new ALooper; 390 mLooper->setName("MPEG2TSWriter"); 391 392 mReflector = new AHandlerReflector<MPEG2TSWriter>(this); 393 394 mLooper->registerHandler(mReflector); 395 mLooper->start(); 396} 397 398MPEG2TSWriter::~MPEG2TSWriter() { 399 mLooper->unregisterHandler(mReflector->id()); 400 mLooper->stop(); 401 402 fclose(mFile); 403 mFile = NULL; 404} 405 406status_t MPEG2TSWriter::addSource(const sp<MediaSource> &source) { 407 CHECK(!mStarted); 408 409 sp<MetaData> meta = source->getFormat(); 410 const char *mime; 411 CHECK(meta->findCString(kKeyMIMEType, &mime)); 412 413 if (strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC) 414 && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 415 return ERROR_UNSUPPORTED; 416 } 417 418 sp<SourceInfo> info = new SourceInfo(source); 419 420 mSources.push(info); 421 422 return OK; 423} 424 425status_t MPEG2TSWriter::start(MetaData *param) { 426 CHECK(!mStarted); 427 428 mStarted = true; 429 mNumSourcesDone = 0; 430 mNumTSPacketsWritten = 0; 431 mNumTSPacketsBeforeMeta = 0; 432 433 for (size_t i = 0; i < mSources.size(); ++i) { 434 sp<AMessage> notify = 435 new AMessage(kWhatSourceNotify, mReflector->id()); 436 437 notify->setInt32("source-index", i); 438 439 mSources.editItemAt(i)->start(notify); 440 } 441 442 return OK; 443} 444 445status_t MPEG2TSWriter::stop() { 446 CHECK(mStarted); 447 448 for (size_t i = 0; i < mSources.size(); ++i) { 449 mSources.editItemAt(i)->stop(); 450 } 451 mStarted = false; 452 453 return OK; 454} 455 456status_t MPEG2TSWriter::pause() { 457 CHECK(mStarted); 458 459 return OK; 460} 461 462bool MPEG2TSWriter::reachedEOS() { 463 return !mStarted || (mNumSourcesDone == mSources.size() ? true : false); 464} 465 466status_t MPEG2TSWriter::dump(int fd, const Vector<String16> &args) { 467 return OK; 468} 469 470void MPEG2TSWriter::onMessageReceived(const sp<AMessage> &msg) { 471 switch (msg->what()) { 472 case kWhatSourceNotify: 473 { 474 int32_t sourceIndex; 475 CHECK(msg->findInt32("source-index", &sourceIndex)); 476 477 int32_t what; 478 CHECK(msg->findInt32("what", &what)); 479 480 if (what == SourceInfo::kNotifyReachedEOS 481 || what == SourceInfo::kNotifyStartFailed) { 482 ++mNumSourcesDone; 483 } else if (what == SourceInfo::kNotifyBuffer) { 484 sp<RefBase> obj; 485 CHECK(msg->findObject("buffer", &obj)); 486 487 writeTS(); 488 489 sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get()); 490 writeAccessUnit(sourceIndex, buffer); 491 } 492 break; 493 } 494 495 default: 496 TRESPASS(); 497 } 498} 499 500void MPEG2TSWriter::writeProgramAssociationTable() { 501 // 0x47 502 // transport_error_indicator = b0 503 // payload_unit_start_indicator = b1 504 // transport_priority = b0 505 // PID = b0000000000000 (13 bits) 506 // transport_scrambling_control = b00 507 // adaptation_field_control = b01 (no adaptation field, payload only) 508 // continuity_counter = b???? 509 // skip = 0x00 510 // --- payload follows 511 // table_id = 0x00 512 // section_syntax_indicator = b1 513 // must_be_zero = b0 514 // reserved = b11 515 // section_length = 0x00d 516 // transport_stream_id = 0x0000 517 // reserved = b11 518 // version_number = b00001 519 // current_next_indicator = b1 520 // section_number = 0x00 521 // last_section_number = 0x00 522 // one program follows: 523 // program_number = 0x0001 524 // reserved = b111 525 // program_map_PID = 0x01e0 (13 bits!) 526 // CRC = 0x???????? 527 528 static const uint8_t kData[] = { 529 0x47, 530 0x40, 0x00, 0x10, 0x00, // b0100 0000 0000 0000 0001 ???? 0000 0000 531 0x00, 0xb0, 0x0d, 0x00, // b0000 0000 1011 0000 0000 1101 0000 0000 532 0x00, 0xc3, 0x00, 0x00, // b0000 0000 1100 0011 0000 0000 0000 0000 533 0x00, 0x01, 0xe1, 0xe0, // b0000 0000 0000 0001 1110 0001 1110 0000 534 0x00, 0x00, 0x00, 0x00 // b???? ???? ???? ???? ???? ???? ???? ???? 535 }; 536 537 sp<ABuffer> buffer = new ABuffer(188); 538 memset(buffer->data(), 0, buffer->size()); 539 memcpy(buffer->data(), kData, sizeof(kData)); 540 541 static const unsigned kContinuityCounter = 5; 542 buffer->data()[3] |= kContinuityCounter; 543 544 CHECK_EQ(fwrite(buffer->data(), 1, buffer->size(), mFile), buffer->size()); 545} 546 547void MPEG2TSWriter::writeProgramMap() { 548 // 0x47 549 // transport_error_indicator = b0 550 // payload_unit_start_indicator = b1 551 // transport_priority = b0 552 // PID = b0 0001 1110 0000 (13 bits) [0x1e0] 553 // transport_scrambling_control = b00 554 // adaptation_field_control = b01 (no adaptation field, payload only) 555 // continuity_counter = b???? 556 // skip = 0x00 557 // -- payload follows 558 // table_id = 0x02 559 // section_syntax_indicator = b1 560 // must_be_zero = b0 561 // reserved = b11 562 // section_length = 0x??? 563 // program_number = 0x0001 564 // reserved = b11 565 // version_number = b00001 566 // current_next_indicator = b1 567 // section_number = 0x00 568 // last_section_number = 0x00 569 // reserved = b111 570 // PCR_PID = b? ???? ???? ???? (13 bits) 571 // reserved = b1111 572 // program_info_length = 0x000 573 // one or more elementary stream descriptions follow: 574 // stream_type = 0x?? 575 // reserved = b111 576 // elementary_PID = b? ???? ???? ???? (13 bits) 577 // reserved = b1111 578 // ES_info_length = 0x000 579 // CRC = 0x???????? 580 581 static const uint8_t kData[] = { 582 0x47, 583 0x41, 0xe0, 0x10, 0x00, // b0100 0001 1110 0000 0001 ???? 0000 0000 584 0x02, 0xb0, 0x00, 0x00, // b0000 0010 1011 ???? ???? ???? 0000 0000 585 0x01, 0xc3, 0x00, 0x00, // b0000 0001 1100 0011 0000 0000 0000 0000 586 0xe0, 0x00, 0xf0, 0x00 // b111? ???? ???? ???? 1111 0000 0000 0000 587 }; 588 589 sp<ABuffer> buffer = new ABuffer(188); 590 memset(buffer->data(), 0, buffer->size()); 591 memcpy(buffer->data(), kData, sizeof(kData)); 592 593 static const unsigned kContinuityCounter = 5; 594 buffer->data()[3] |= kContinuityCounter; 595 596 size_t section_length = 5 * mSources.size() + 4 + 9; 597 buffer->data()[6] |= section_length >> 8; 598 buffer->data()[7] = section_length & 0xff; 599 600 static const unsigned kPCR_PID = 0x1e1; 601 buffer->data()[13] |= (kPCR_PID >> 8) & 0x1f; 602 buffer->data()[14] = kPCR_PID & 0xff; 603 604 uint8_t *ptr = &buffer->data()[sizeof(kData)]; 605 for (size_t i = 0; i < mSources.size(); ++i) { 606 *ptr++ = mSources.editItemAt(i)->streamType(); 607 608 const unsigned ES_PID = 0x1e0 + i + 1; 609 *ptr++ = 0xe0 | (ES_PID >> 8); 610 *ptr++ = ES_PID & 0xff; 611 *ptr++ = 0xf0; 612 *ptr++ = 0x00; 613 } 614 615 *ptr++ = 0x00; 616 *ptr++ = 0x00; 617 *ptr++ = 0x00; 618 *ptr++ = 0x00; 619 620 CHECK_EQ(fwrite(buffer->data(), 1, buffer->size(), mFile), buffer->size()); 621} 622 623void MPEG2TSWriter::writeAccessUnit( 624 int32_t sourceIndex, const sp<ABuffer> &accessUnit) { 625 // 0x47 626 // transport_error_indicator = b0 627 // payload_unit_start_indicator = b1 628 // transport_priority = b0 629 // PID = b0 0001 1110 ???? (13 bits) [0x1e0 + 1 + sourceIndex] 630 // transport_scrambling_control = b00 631 // adaptation_field_control = b01 (no adaptation field, payload only) 632 // continuity_counter = b???? 633 // -- payload follows 634 // packet_startcode_prefix = 0x000001 635 // stream_id = 0x?? (0xe0 for avc video, 0xc0 for aac audio) 636 // PES_packet_length = 0x???? 637 // reserved = b10 638 // PES_scrambling_control = b00 639 // PES_priority = b0 640 // data_alignment_indicator = b1 641 // copyright = b0 642 // original_or_copy = b0 643 // PTS_DTS_flags = b10 (PTS only) 644 // ESCR_flag = b0 645 // ES_rate_flag = b0 646 // DSM_trick_mode_flag = b0 647 // additional_copy_info_flag = b0 648 // PES_CRC_flag = b0 649 // PES_extension_flag = b0 650 // PES_header_data_length = 0x05 651 // reserved = b0010 (PTS) 652 // PTS[32..30] = b??? 653 // reserved = b1 654 // PTS[29..15] = b??? ???? ???? ???? (15 bits) 655 // reserved = b1 656 // PTS[14..0] = b??? ???? ???? ???? (15 bits) 657 // reserved = b1 658 // the first fragment of "buffer" follows 659 660 sp<ABuffer> buffer = new ABuffer(188); 661 memset(buffer->data(), 0, buffer->size()); 662 663 const unsigned PID = 0x1e0 + sourceIndex + 1; 664 665 const unsigned continuity_counter = 666 mSources.editItemAt(sourceIndex)->incrementContinuityCounter(); 667 668 // XXX if there are multiple streams of a kind (more than 1 audio or 669 // more than 1 video) they need distinct stream_ids. 670 const unsigned stream_id = 671 mSources.editItemAt(sourceIndex)->streamType() == 0x0f ? 0xc0 : 0xe0; 672 673 int64_t timeUs; 674 CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs)); 675 676 uint32_t PTS = (timeUs * 9ll) / 100ll; 677 678 size_t PES_packet_length = accessUnit->size() + 8; 679 680 uint8_t *ptr = buffer->data(); 681 *ptr++ = 0x47; 682 *ptr++ = 0x40 | (PID >> 8); 683 *ptr++ = PID & 0xff; 684 *ptr++ = 0x10 | continuity_counter; 685 *ptr++ = 0x00; 686 *ptr++ = 0x00; 687 *ptr++ = 0x01; 688 *ptr++ = stream_id; 689 *ptr++ = PES_packet_length >> 8; 690 *ptr++ = PES_packet_length & 0xff; 691 *ptr++ = 0x84; 692 *ptr++ = 0x80; 693 *ptr++ = 0x05; 694 *ptr++ = 0x20 | (((PTS >> 30) & 7) << 1) | 1; 695 *ptr++ = (PTS >> 22) & 0xff; 696 *ptr++ = (((PTS >> 15) & 0x7f) << 1) | 1; 697 *ptr++ = (PTS >> 7) & 0xff; 698 *ptr++ = ((PTS & 0x7f) << 1) | 1; 699 700 size_t sizeLeft = buffer->data() + buffer->size() - ptr; 701 size_t copy = accessUnit->size(); 702 if (copy > sizeLeft) { 703 copy = sizeLeft; 704 } 705 706 memcpy(ptr, accessUnit->data(), copy); 707 708 CHECK_EQ(fwrite(buffer->data(), 1, buffer->size(), mFile), buffer->size()); 709 710 size_t offset = copy; 711 while (offset < accessUnit->size()) { 712 // for subsequent fragments of "buffer": 713 // 0x47 714 // transport_error_indicator = b0 715 // payload_unit_start_indicator = b0 716 // transport_priority = b0 717 // PID = b0 0001 1110 ???? (13 bits) [0x1e0 + 1 + sourceIndex] 718 // transport_scrambling_control = b00 719 // adaptation_field_control = b01 (no adaptation field, payload only) 720 // continuity_counter = b???? 721 // the fragment of "buffer" follows. 722 723 memset(buffer->data(), 0, buffer->size()); 724 725 const unsigned continuity_counter = 726 mSources.editItemAt(sourceIndex)->incrementContinuityCounter(); 727 728 ptr = buffer->data(); 729 *ptr++ = 0x47; 730 *ptr++ = 0x00 | (PID >> 8); 731 *ptr++ = PID & 0xff; 732 *ptr++ = 0x10 | continuity_counter; 733 734 size_t sizeLeft = buffer->data() + buffer->size() - ptr; 735 size_t copy = accessUnit->size() - offset; 736 if (copy > sizeLeft) { 737 copy = sizeLeft; 738 } 739 740 memcpy(ptr, accessUnit->data() + offset, copy); 741 CHECK_EQ(fwrite(buffer->data(), 1, buffer->size(), mFile), 742 buffer->size()); 743 744 offset += copy; 745 } 746} 747 748void MPEG2TSWriter::writeTS() { 749 if (mNumTSPacketsWritten >= mNumTSPacketsBeforeMeta) { 750 writeProgramAssociationTable(); 751 writeProgramMap(); 752 753 mNumTSPacketsBeforeMeta = mNumTSPacketsWritten + 2500; 754 } 755} 756 757} // namespace android 758 759