MPEG4Writer.cpp revision d0ea545d8357e7d86ad5f19cb2c6499c91786473
1/* 2 * Copyright (C) 2009 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 "MPEG4Writer" 19#include <utils/Log.h> 20 21#include <arpa/inet.h> 22 23#include <ctype.h> 24#include <pthread.h> 25 26#include <media/stagefright/MPEG4Writer.h> 27#include <media/stagefright/MediaBuffer.h> 28#include <media/stagefright/MetaData.h> 29#include <media/stagefright/MediaDebug.h> 30#include <media/stagefright/MediaDefs.h> 31#include <media/stagefright/MediaErrors.h> 32#include <media/stagefright/MediaSource.h> 33#include <media/stagefright/Utils.h> 34#include <media/mediarecorder.h> 35 36#include "include/ESDS.h" 37 38namespace android { 39 40static const int64_t kMax32BitFileSize = 0x007fffffffLL; 41static const uint8_t kNalUnitTypeSeqParamSet = 0x07; 42static const uint8_t kNalUnitTypePicParamSet = 0x08; 43 44class MPEG4Writer::Track { 45public: 46 Track(MPEG4Writer *owner, const sp<MediaSource> &source); 47 48 ~Track(); 49 50 status_t start(MetaData *params); 51 status_t stop(); 52 status_t pause(); 53 bool reachedEOS(); 54 55 int64_t getDurationUs() const; 56 int64_t getEstimatedTrackSizeBytes() const; 57 void writeTrackHeader(int32_t trackID, bool use32BitOffset = true); 58 void bufferChunk(int64_t timestampUs); 59 bool isAvc() const { return mIsAvc; } 60 bool isAudio() const { return mIsAudio; } 61 bool isMPEG4() const { return mIsMPEG4; } 62 void addChunkOffset(off_t offset); 63 status_t dump(int fd, const Vector<String16>& args) const; 64 65private: 66 MPEG4Writer *mOwner; 67 sp<MetaData> mMeta; 68 sp<MediaSource> mSource; 69 volatile bool mDone; 70 volatile bool mPaused; 71 volatile bool mResumed; 72 bool mIsAvc; 73 bool mIsAudio; 74 bool mIsMPEG4; 75 int64_t mTrackDurationUs; 76 77 // For realtime applications, we need to adjust the media clock 78 // for video track based on the audio media clock 79 bool mIsRealTimeRecording; 80 int64_t mMaxTimeStampUs; 81 int64_t mEstimatedTrackSizeBytes; 82 int64_t mMdatSizeBytes; 83 int32_t mTimeScale; 84 85 pthread_t mThread; 86 87 // mNumSamples is used to track how many samples in mSampleSizes List. 88 // This is to reduce the cost associated with mSampleSizes.size() call, 89 // since it is O(n). Ideally, the fix should be in List class. 90 size_t mNumSamples; 91 List<size_t> mSampleSizes; 92 bool mSamplesHaveSameSize; 93 94 List<MediaBuffer *> mChunkSamples; 95 96 size_t mNumStcoTableEntries; 97 List<off_t> mChunkOffsets; 98 99 size_t mNumStscTableEntries; 100 struct StscTableEntry { 101 102 StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id) 103 : firstChunk(chunk), 104 samplesPerChunk(samples), 105 sampleDescriptionId(id) {} 106 107 uint32_t firstChunk; 108 uint32_t samplesPerChunk; 109 uint32_t sampleDescriptionId; 110 }; 111 List<StscTableEntry> mStscTableEntries; 112 113 size_t mNumStssTableEntries; 114 List<int32_t> mStssTableEntries; 115 116 size_t mNumSttsTableEntries; 117 struct SttsTableEntry { 118 119 SttsTableEntry(uint32_t count, uint32_t durationUs) 120 : sampleCount(count), sampleDurationUs(durationUs) {} 121 122 uint32_t sampleCount; 123 uint32_t sampleDurationUs; 124 }; 125 List<SttsTableEntry> mSttsTableEntries; 126 127 // Sequence parameter set or picture parameter set 128 struct AVCParamSet { 129 AVCParamSet(uint16_t length, const uint8_t *data) 130 : mLength(length), mData(data) {} 131 132 uint16_t mLength; 133 const uint8_t *mData; 134 }; 135 List<AVCParamSet> mSeqParamSets; 136 List<AVCParamSet> mPicParamSets; 137 uint8_t mProfileIdc; 138 uint8_t mProfileCompatible; 139 uint8_t mLevelIdc; 140 141 void *mCodecSpecificData; 142 size_t mCodecSpecificDataSize; 143 bool mGotAllCodecSpecificData; 144 bool mTrackingProgressStatus; 145 146 bool mReachedEOS; 147 int64_t mStartTimestampUs; 148 int64_t mPreviousTrackTimeUs; 149 int64_t mTrackEveryTimeDurationUs; 150 151 static void *ThreadWrapper(void *me); 152 status_t threadEntry(); 153 154 const uint8_t *parseParamSet( 155 const uint8_t *data, size_t length, int type, size_t *paramSetLen); 156 157 status_t makeAVCCodecSpecificData( 158 const uint8_t *data, size_t size); 159 status_t copyAVCCodecSpecificData( 160 const uint8_t *data, size_t size); 161 status_t parseAVCCodecSpecificData( 162 const uint8_t *data, size_t size); 163 164 // Track authoring progress status 165 void trackProgressStatus(int64_t timeUs, status_t err = OK); 166 void initTrackingProgressStatus(MetaData *params); 167 168 void getCodecSpecificDataFromInputFormatIfPossible(); 169 170 // Determine the track time scale 171 // If it is an audio track, try to use the sampling rate as 172 // the time scale; however, if user chooses the overwrite 173 // value, the user-supplied time scale will be used. 174 void setTimeScale(); 175 176 // Simple validation on the codec specific data 177 status_t checkCodecSpecificData() const; 178 179 void updateTrackSizeEstimate(); 180 void addOneStscTableEntry(size_t chunkId, size_t sampleId); 181 void addOneStssTableEntry(size_t sampleId); 182 void addOneSttsTableEntry(size_t sampleCount, int64_t durationUs); 183 184 Track(const Track &); 185 Track &operator=(const Track &); 186}; 187 188MPEG4Writer::MPEG4Writer(const char *filename) 189 : mFile(fopen(filename, "wb")), 190 mUse4ByteNalLength(true), 191 mUse32BitOffset(true), 192 mPaused(false), 193 mStarted(false), 194 mOffset(0), 195 mMdatOffset(0), 196 mEstimatedMoovBoxSize(0), 197 mInterleaveDurationUs(1000000) { 198 CHECK(mFile != NULL); 199} 200 201MPEG4Writer::MPEG4Writer(int fd) 202 : mFile(fdopen(fd, "wb")), 203 mUse4ByteNalLength(true), 204 mUse32BitOffset(true), 205 mPaused(false), 206 mStarted(false), 207 mOffset(0), 208 mMdatOffset(0), 209 mEstimatedMoovBoxSize(0), 210 mInterleaveDurationUs(1000000) { 211 CHECK(mFile != NULL); 212} 213 214MPEG4Writer::~MPEG4Writer() { 215 stop(); 216 217 while (!mTracks.empty()) { 218 List<Track *>::iterator it = mTracks.begin(); 219 delete *it; 220 (*it) = NULL; 221 mTracks.erase(it); 222 } 223 mTracks.clear(); 224} 225 226status_t MPEG4Writer::dump( 227 int fd, const Vector<String16>& args) { 228 const size_t SIZE = 256; 229 char buffer[SIZE]; 230 String8 result; 231 snprintf(buffer, SIZE, " MPEG4Writer %p\n", this); 232 result.append(buffer); 233 snprintf(buffer, SIZE, " mStarted: %s\n", mStarted? "true": "false"); 234 result.append(buffer); 235 ::write(fd, result.string(), result.size()); 236 for (List<Track *>::iterator it = mTracks.begin(); 237 it != mTracks.end(); ++it) { 238 (*it)->dump(fd, args); 239 } 240 return OK; 241} 242 243status_t MPEG4Writer::Track::dump( 244 int fd, const Vector<String16>& args) const { 245 const size_t SIZE = 256; 246 char buffer[SIZE]; 247 String8 result; 248 snprintf(buffer, SIZE, " %s track\n", mIsAudio? "Audio": "Video"); 249 result.append(buffer); 250 snprintf(buffer, SIZE, " reached EOS: %s\n", 251 mReachedEOS? "true": "false"); 252 result.append(buffer); 253 ::write(fd, result.string(), result.size()); 254 return OK; 255} 256 257status_t MPEG4Writer::addSource(const sp<MediaSource> &source) { 258 Track *track = new Track(this, source); 259 mTracks.push_back(track); 260 261 return OK; 262} 263 264status_t MPEG4Writer::startTracks(MetaData *params) { 265 for (List<Track *>::iterator it = mTracks.begin(); 266 it != mTracks.end(); ++it) { 267 status_t err = (*it)->start(params); 268 269 if (err != OK) { 270 for (List<Track *>::iterator it2 = mTracks.begin(); 271 it2 != it; ++it2) { 272 (*it2)->stop(); 273 } 274 275 return err; 276 } 277 } 278 return OK; 279} 280 281int64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) { 282 // This implementation is highly experimental/heurisitic. 283 // 284 // Statistical analysis shows that metadata usually accounts 285 // for a small portion of the total file size, usually < 0.6%. 286 // Currently, lets set to 0.4% for now. 287 288 // The default MIN_MOOV_BOX_SIZE is set to 0.4% x 1MB, 289 // where 1MB is the common file size limit for MMS application. 290 // The default MAX _MOOV_BOX_SIZE value is based on about 4 291 // minute video recording with a bit rate about 3 Mbps, because 292 // statistics also show that most of the video captured are going 293 // to be less than 3 minutes. 294 295 // If the estimation is wrong, we will pay the price of wasting 296 // some reserved space. This should not happen so often statistically. 297 static const int32_t factor = mUse32BitOffset? 1: 2; 298 static const int64_t MIN_MOOV_BOX_SIZE = 4 * 1024; // 4 KB 299 static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000); 300 int64_t size = MIN_MOOV_BOX_SIZE; 301 302 if (mMaxFileSizeLimitBytes != 0) { 303 size = mMaxFileSizeLimitBytes * 4 / 1000; 304 } else if (mMaxFileDurationLimitUs != 0) { 305 if (bitRate <= 0) { 306 // We could not estimate the file size since bitRate is not set. 307 size = MIN_MOOV_BOX_SIZE; 308 } else { 309 size = ((mMaxFileDurationLimitUs * bitRate * 4) / 1000 / 8000000); 310 } 311 } 312 if (size < MIN_MOOV_BOX_SIZE) { 313 size = MIN_MOOV_BOX_SIZE; 314 } 315 316 // Any long duration recording will be probably end up with 317 // non-streamable mp4 file. 318 if (size > MAX_MOOV_BOX_SIZE) { 319 size = MAX_MOOV_BOX_SIZE; 320 } 321 322 LOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated" 323 " moov size %lld bytes", 324 mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size); 325 return factor * size; 326} 327 328status_t MPEG4Writer::start(MetaData *param) { 329 if (mFile == NULL) { 330 return UNKNOWN_ERROR; 331 } 332 333 int32_t use64BitOffset; 334 if (param && 335 param->findInt32(kKey64BitFileOffset, &use64BitOffset) && 336 use64BitOffset) { 337 mUse32BitOffset = false; 338 } 339 340 if (mUse32BitOffset) { 341 // Implicit 32 bit file size limit 342 if (mMaxFileSizeLimitBytes == 0) { 343 mMaxFileSizeLimitBytes = kMax32BitFileSize; 344 } 345 346 // If file size is set to be larger than the 32 bit file 347 // size limit, treat it as an error. 348 if (mMaxFileSizeLimitBytes > kMax32BitFileSize) { 349 LOGW("32-bi file size limit (%lld bytes) too big. " 350 "It is changed to %lld bytes", 351 mMaxFileSizeLimitBytes, kMax32BitFileSize); 352 mMaxFileSizeLimitBytes = kMax32BitFileSize; 353 } 354 } 355 356 int32_t use2ByteNalLength; 357 if (param && 358 param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) && 359 use2ByteNalLength) { 360 mUse4ByteNalLength = false; 361 } 362 363 mStartTimestampUs = -1; 364 365 if (mStarted) { 366 if (mPaused) { 367 mPaused = false; 368 return startTracks(param); 369 } 370 return OK; 371 } 372 373 if (!param || 374 !param->findInt32(kKeyTimeScale, &mTimeScale)) { 375 mTimeScale = 1000; 376 } 377 CHECK(mTimeScale > 0); 378 LOGV("movie time scale: %d", mTimeScale); 379 380 mStreamableFile = true; 381 mWriteMoovBoxToMemory = false; 382 mMoovBoxBuffer = NULL; 383 mMoovBoxBufferOffset = 0; 384 385 beginBox("ftyp"); 386 { 387 int32_t fileType; 388 if (param && param->findInt32(kKeyFileType, &fileType) && 389 fileType != OUTPUT_FORMAT_MPEG_4) { 390 writeFourcc("3gp4"); 391 } else { 392 writeFourcc("isom"); 393 } 394 } 395 writeInt32(0); 396 writeFourcc("isom"); 397 writeFourcc("3gp4"); 398 endBox(); 399 400 mFreeBoxOffset = mOffset; 401 402 if (mEstimatedMoovBoxSize == 0) { 403 int32_t bitRate = -1; 404 if (param) { 405 param->findInt32(kKeyBitRate, &bitRate); 406 } 407 mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate); 408 } 409 CHECK(mEstimatedMoovBoxSize >= 8); 410 fseeko(mFile, mFreeBoxOffset, SEEK_SET); 411 writeInt32(mEstimatedMoovBoxSize); 412 write("free", 4); 413 414 mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; 415 mOffset = mMdatOffset; 416 fseeko(mFile, mMdatOffset, SEEK_SET); 417 if (mUse32BitOffset) { 418 write("????mdat", 8); 419 } else { 420 write("\x00\x00\x00\x01mdat????????", 16); 421 } 422 423 status_t err = startWriterThread(); 424 if (err != OK) { 425 return err; 426 } 427 428 err = startTracks(param); 429 if (err != OK) { 430 return err; 431 } 432 433 mStarted = true; 434 return OK; 435} 436 437bool MPEG4Writer::use32BitFileOffset() const { 438 return mUse32BitOffset; 439} 440 441status_t MPEG4Writer::pause() { 442 if (mFile == NULL) { 443 return OK; 444 } 445 mPaused = true; 446 status_t err = OK; 447 for (List<Track *>::iterator it = mTracks.begin(); 448 it != mTracks.end(); ++it) { 449 status_t status = (*it)->pause(); 450 if (status != OK) { 451 err = status; 452 } 453 } 454 return err; 455} 456 457void MPEG4Writer::stopWriterThread() { 458 LOGV("stopWriterThread"); 459 460 { 461 Mutex::Autolock autolock(mLock); 462 463 mDone = true; 464 mChunkReadyCondition.signal(); 465 } 466 467 void *dummy; 468 pthread_join(mThread, &dummy); 469} 470 471status_t MPEG4Writer::stop() { 472 if (mFile == NULL) { 473 return OK; 474 } 475 476 status_t err = OK; 477 int64_t maxDurationUs = 0; 478 for (List<Track *>::iterator it = mTracks.begin(); 479 it != mTracks.end(); ++it) { 480 status_t status = (*it)->stop(); 481 if (err == OK && status != OK) { 482 err = status; 483 } 484 485 int64_t durationUs = (*it)->getDurationUs(); 486 if (durationUs > maxDurationUs) { 487 maxDurationUs = durationUs; 488 } 489 } 490 491 stopWriterThread(); 492 493 // Do not write out movie header on error. 494 if (err != OK) { 495 fflush(mFile); 496 fclose(mFile); 497 mFile = NULL; 498 mStarted = false; 499 return err; 500 } 501 502 // Fix up the size of the 'mdat' chunk. 503 if (mUse32BitOffset) { 504 fseeko(mFile, mMdatOffset, SEEK_SET); 505 int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset)); 506 fwrite(&size, 1, 4, mFile); 507 } else { 508 fseeko(mFile, mMdatOffset + 8, SEEK_SET); 509 int64_t size = mOffset - mMdatOffset; 510 size = hton64(size); 511 fwrite(&size, 1, 8, mFile); 512 } 513 fseeko(mFile, mOffset, SEEK_SET); 514 515 time_t now = time(NULL); 516 const off_t moovOffset = mOffset; 517 mWriteMoovBoxToMemory = true; 518 mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); 519 mMoovBoxBufferOffset = 0; 520 CHECK(mMoovBoxBuffer != NULL); 521 int32_t duration = (maxDurationUs * mTimeScale + 5E5) / 1E6; 522 523 beginBox("moov"); 524 525 beginBox("mvhd"); 526 writeInt32(0); // version=0, flags=0 527 writeInt32(now); // creation time 528 writeInt32(now); // modification time 529 writeInt32(mTimeScale); // mvhd timescale 530 writeInt32(duration); 531 writeInt32(0x10000); // rate: 1.0 532 writeInt16(0x100); // volume 533 writeInt16(0); // reserved 534 writeInt32(0); // reserved 535 writeInt32(0); // reserved 536 writeInt32(0x10000); // matrix 537 writeInt32(0); 538 writeInt32(0); 539 writeInt32(0); 540 writeInt32(0x10000); 541 writeInt32(0); 542 writeInt32(0); 543 writeInt32(0); 544 writeInt32(0x40000000); 545 writeInt32(0); // predefined 546 writeInt32(0); // predefined 547 writeInt32(0); // predefined 548 writeInt32(0); // predefined 549 writeInt32(0); // predefined 550 writeInt32(0); // predefined 551 writeInt32(mTracks.size() + 1); // nextTrackID 552 endBox(); // mvhd 553 554 int32_t id = 1; 555 for (List<Track *>::iterator it = mTracks.begin(); 556 it != mTracks.end(); ++it, ++id) { 557 (*it)->writeTrackHeader(id, mUse32BitOffset); 558 } 559 endBox(); // moov 560 561 mWriteMoovBoxToMemory = false; 562 if (mStreamableFile) { 563 CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize); 564 565 // Moov box 566 fseeko(mFile, mFreeBoxOffset, SEEK_SET); 567 mOffset = mFreeBoxOffset; 568 write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile); 569 570 // Free box 571 fseeko(mFile, mOffset, SEEK_SET); 572 writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); 573 write("free", 4); 574 575 // Free temp memory 576 free(mMoovBoxBuffer); 577 mMoovBoxBuffer = NULL; 578 mMoovBoxBufferOffset = 0; 579 } else { 580 LOGI("The mp4 file will not be streamable."); 581 } 582 583 CHECK(mBoxes.empty()); 584 585 fflush(mFile); 586 fclose(mFile); 587 mFile = NULL; 588 mStarted = false; 589 return err; 590} 591 592status_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 593 mInterleaveDurationUs = durationUs; 594 return OK; 595} 596 597void MPEG4Writer::lock() { 598 mLock.lock(); 599} 600 601void MPEG4Writer::unlock() { 602 mLock.unlock(); 603} 604 605off_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { 606 off_t old_offset = mOffset; 607 608 fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 609 1, buffer->range_length(), mFile); 610 611 mOffset += buffer->range_length(); 612 613 return old_offset; 614} 615 616static void StripStartcode(MediaBuffer *buffer) { 617 if (buffer->range_length() < 4) { 618 return; 619 } 620 621 const uint8_t *ptr = 622 (const uint8_t *)buffer->data() + buffer->range_offset(); 623 624 if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 625 buffer->set_range( 626 buffer->range_offset() + 4, buffer->range_length() - 4); 627 } 628} 629 630off_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 631 off_t old_offset = mOffset; 632 633 size_t length = buffer->range_length(); 634 635 if (mUse4ByteNalLength) { 636 uint8_t x = length >> 24; 637 fwrite(&x, 1, 1, mFile); 638 x = (length >> 16) & 0xff; 639 fwrite(&x, 1, 1, mFile); 640 x = (length >> 8) & 0xff; 641 fwrite(&x, 1, 1, mFile); 642 x = length & 0xff; 643 fwrite(&x, 1, 1, mFile); 644 645 fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 646 1, length, mFile); 647 mOffset += length + 4; 648 } else { 649 CHECK(length < 65536); 650 651 uint8_t x = length >> 8; 652 fwrite(&x, 1, 1, mFile); 653 x = length & 0xff; 654 fwrite(&x, 1, 1, mFile); 655 fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 656 1, length, mFile); 657 mOffset += length + 2; 658 } 659 660 return old_offset; 661} 662 663size_t MPEG4Writer::write( 664 const void *ptr, size_t size, size_t nmemb, FILE *stream) { 665 666 const size_t bytes = size * nmemb; 667 if (mWriteMoovBoxToMemory) { 668 off_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes; 669 if (moovBoxSize > mEstimatedMoovBoxSize) { 670 for (List<off_t>::iterator it = mBoxes.begin(); 671 it != mBoxes.end(); ++it) { 672 (*it) += mOffset; 673 } 674 fseeko(mFile, mOffset, SEEK_SET); 675 fwrite(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, stream); 676 fwrite(ptr, size, nmemb, stream); 677 mOffset += (bytes + mMoovBoxBufferOffset); 678 free(mMoovBoxBuffer); 679 mMoovBoxBuffer = NULL; 680 mMoovBoxBufferOffset = 0; 681 mWriteMoovBoxToMemory = false; 682 mStreamableFile = false; 683 } else { 684 memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); 685 mMoovBoxBufferOffset += bytes; 686 } 687 } else { 688 fwrite(ptr, size, nmemb, stream); 689 mOffset += bytes; 690 } 691 return bytes; 692} 693 694void MPEG4Writer::beginBox(const char *fourcc) { 695 CHECK_EQ(strlen(fourcc), 4); 696 697 mBoxes.push_back(mWriteMoovBoxToMemory? 698 mMoovBoxBufferOffset: mOffset); 699 700 writeInt32(0); 701 writeFourcc(fourcc); 702} 703 704void MPEG4Writer::endBox() { 705 CHECK(!mBoxes.empty()); 706 707 off_t offset = *--mBoxes.end(); 708 mBoxes.erase(--mBoxes.end()); 709 710 if (mWriteMoovBoxToMemory) { 711 int32_t x = htonl(mMoovBoxBufferOffset - offset); 712 memcpy(mMoovBoxBuffer + offset, &x, 4); 713 } else { 714 fseeko(mFile, offset, SEEK_SET); 715 writeInt32(mOffset - offset); 716 mOffset -= 4; 717 fseeko(mFile, mOffset, SEEK_SET); 718 } 719} 720 721void MPEG4Writer::writeInt8(int8_t x) { 722 write(&x, 1, 1, mFile); 723} 724 725void MPEG4Writer::writeInt16(int16_t x) { 726 x = htons(x); 727 write(&x, 1, 2, mFile); 728} 729 730void MPEG4Writer::writeInt32(int32_t x) { 731 x = htonl(x); 732 write(&x, 1, 4, mFile); 733} 734 735void MPEG4Writer::writeInt64(int64_t x) { 736 x = hton64(x); 737 write(&x, 1, 8, mFile); 738} 739 740void MPEG4Writer::writeCString(const char *s) { 741 size_t n = strlen(s); 742 write(s, 1, n + 1, mFile); 743} 744 745void MPEG4Writer::writeFourcc(const char *s) { 746 CHECK_EQ(strlen(s), 4); 747 write(s, 1, 4, mFile); 748} 749 750void MPEG4Writer::write(const void *data, size_t size) { 751 write(data, 1, size, mFile); 752} 753 754bool MPEG4Writer::exceedsFileSizeLimit() { 755 // No limit 756 if (mMaxFileSizeLimitBytes == 0) { 757 return false; 758 } 759 760 int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 761 for (List<Track *>::iterator it = mTracks.begin(); 762 it != mTracks.end(); ++it) { 763 nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 764 } 765 766 return (nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes); 767} 768 769bool MPEG4Writer::exceedsFileDurationLimit() { 770 // No limit 771 if (mMaxFileDurationLimitUs == 0) { 772 return false; 773 } 774 775 for (List<Track *>::iterator it = mTracks.begin(); 776 it != mTracks.end(); ++it) { 777 if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { 778 return true; 779 } 780 } 781 return false; 782} 783 784bool MPEG4Writer::reachedEOS() { 785 bool allDone = true; 786 for (List<Track *>::iterator it = mTracks.begin(); 787 it != mTracks.end(); ++it) { 788 if (!(*it)->reachedEOS()) { 789 allDone = false; 790 break; 791 } 792 } 793 794 return allDone; 795} 796 797void MPEG4Writer::setStartTimestampUs(int64_t timeUs) { 798 LOGI("setStartTimestampUs: %lld", timeUs); 799 CHECK(timeUs >= 0); 800 Mutex::Autolock autoLock(mLock); 801 if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) { 802 mStartTimestampUs = timeUs; 803 LOGI("Earliest track starting time: %lld", mStartTimestampUs); 804 } 805} 806 807int64_t MPEG4Writer::getStartTimestampUs() { 808 Mutex::Autolock autoLock(mLock); 809 return mStartTimestampUs; 810} 811 812size_t MPEG4Writer::numTracks() { 813 Mutex::Autolock autolock(mLock); 814 return mTracks.size(); 815} 816 817//////////////////////////////////////////////////////////////////////////////// 818 819MPEG4Writer::Track::Track( 820 MPEG4Writer *owner, const sp<MediaSource> &source) 821 : mOwner(owner), 822 mMeta(source->getFormat()), 823 mSource(source), 824 mDone(false), 825 mPaused(false), 826 mResumed(false), 827 mTrackDurationUs(0), 828 mEstimatedTrackSizeBytes(0), 829 mSamplesHaveSameSize(true), 830 mCodecSpecificData(NULL), 831 mCodecSpecificDataSize(0), 832 mGotAllCodecSpecificData(false), 833 mReachedEOS(false) { 834 getCodecSpecificDataFromInputFormatIfPossible(); 835 836 const char *mime; 837 mMeta->findCString(kKeyMIMEType, &mime); 838 mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 839 mIsAudio = !strncasecmp(mime, "audio/", 6); 840 mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 841 !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 842 843 setTimeScale(); 844} 845 846void MPEG4Writer::Track::updateTrackSizeEstimate() { 847 848 int64_t stcoBoxSizeBytes = mOwner->use32BitFileOffset() 849 ? mNumStcoTableEntries * 4 850 : mNumStcoTableEntries * 8; 851 852 int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mNumSamples * 4); 853 854 mEstimatedTrackSizeBytes = mMdatSizeBytes + // media data size 855 mNumStscTableEntries * 12 + // stsc box size 856 mNumStssTableEntries * 4 + // stss box size 857 mNumSttsTableEntries * 8 + // stts box size 858 stcoBoxSizeBytes + // stco box size 859 stszBoxSizeBytes; // stsz box size 860} 861 862void MPEG4Writer::Track::addOneStscTableEntry( 863 size_t chunkId, size_t sampleId) { 864 865 StscTableEntry stscEntry(chunkId, sampleId, 1); 866 mStscTableEntries.push_back(stscEntry); 867 ++mNumStscTableEntries; 868} 869 870void MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) { 871 mStssTableEntries.push_back(sampleId); 872 ++mNumStssTableEntries; 873} 874 875void MPEG4Writer::Track::addOneSttsTableEntry( 876 size_t sampleCount, int64_t durationUs) { 877 878 SttsTableEntry sttsEntry(sampleCount, durationUs); 879 mSttsTableEntries.push_back(sttsEntry); 880 ++mNumSttsTableEntries; 881} 882 883void MPEG4Writer::Track::addChunkOffset(off_t offset) { 884 ++mNumStcoTableEntries; 885 mChunkOffsets.push_back(offset); 886} 887 888void MPEG4Writer::Track::setTimeScale() { 889 LOGV("setTimeScale"); 890 // Default time scale 891 mTimeScale = 90000; 892 893 if (mIsAudio) { 894 // Use the sampling rate as the default time scale for audio track. 895 int32_t sampleRate; 896 bool success = mMeta->findInt32(kKeySampleRate, &sampleRate); 897 CHECK(success); 898 mTimeScale = sampleRate; 899 } 900 901 // If someone would like to overwrite the timescale, use user-supplied value. 902 int32_t timeScale; 903 if (mMeta->findInt32(kKeyTimeScale, &timeScale)) { 904 mTimeScale = timeScale; 905 } 906 907 CHECK(mTimeScale > 0); 908} 909 910void MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() { 911 const char *mime; 912 CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 913 914 if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 915 uint32_t type; 916 const void *data; 917 size_t size; 918 if (mMeta->findData(kKeyAVCC, &type, &data, &size)) { 919 mCodecSpecificData = malloc(size); 920 mCodecSpecificDataSize = size; 921 memcpy(mCodecSpecificData, data, size); 922 mGotAllCodecSpecificData = true; 923 } 924 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 925 || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 926 uint32_t type; 927 const void *data; 928 size_t size; 929 if (mMeta->findData(kKeyESDS, &type, &data, &size)) { 930 ESDS esds(data, size); 931 if (esds.getCodecSpecificInfo(&data, &size) == OK) { 932 mCodecSpecificData = malloc(size); 933 mCodecSpecificDataSize = size; 934 memcpy(mCodecSpecificData, data, size); 935 mGotAllCodecSpecificData = true; 936 } 937 } 938 } 939} 940 941MPEG4Writer::Track::~Track() { 942 stop(); 943 944 if (mCodecSpecificData != NULL) { 945 free(mCodecSpecificData); 946 mCodecSpecificData = NULL; 947 } 948} 949 950void MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) { 951 LOGV("initTrackingProgressStatus"); 952 mPreviousTrackTimeUs = -1; 953 mTrackingProgressStatus = false; 954 mTrackEveryTimeDurationUs = 0; 955 { 956 int64_t timeUs; 957 if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) { 958 LOGV("Receive request to track progress status for every %lld us", timeUs); 959 mTrackEveryTimeDurationUs = timeUs; 960 mTrackingProgressStatus = true; 961 } 962 } 963} 964 965// static 966void *MPEG4Writer::ThreadWrapper(void *me) { 967 LOGV("ThreadWrapper: %p", me); 968 MPEG4Writer *writer = static_cast<MPEG4Writer *>(me); 969 writer->threadFunc(); 970 return NULL; 971} 972 973void MPEG4Writer::bufferChunk(const Chunk& chunk) { 974 LOGV("bufferChunk: %p", chunk.mTrack); 975 Mutex::Autolock autolock(mLock); 976 CHECK_EQ(mDone, false); 977 978 for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 979 it != mChunkInfos.end(); ++it) { 980 981 if (chunk.mTrack == it->mTrack) { // Found owner 982 it->mChunks.push_back(chunk); 983 mChunkReadyCondition.signal(); 984 return; 985 } 986 } 987 988 CHECK("Received a chunk for a unknown track" == 0); 989} 990 991void MPEG4Writer::writeFirstChunk(ChunkInfo* info) { 992 LOGV("writeFirstChunk: %p", info->mTrack); 993 994 List<Chunk>::iterator chunkIt = info->mChunks.begin(); 995 for (List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin(); 996 it != chunkIt->mSamples.end(); ++it) { 997 998 off_t offset = info->mTrack->isAvc() 999 ? addLengthPrefixedSample_l(*it) 1000 : addSample_l(*it); 1001 if (it == chunkIt->mSamples.begin()) { 1002 info->mTrack->addChunkOffset(offset); 1003 } 1004 } 1005 1006 // Done with the current chunk. 1007 // Release all the samples in this chunk. 1008 while (!chunkIt->mSamples.empty()) { 1009 List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin(); 1010 (*it)->release(); 1011 (*it) = NULL; 1012 chunkIt->mSamples.erase(it); 1013 } 1014 chunkIt->mSamples.clear(); 1015 info->mChunks.erase(chunkIt); 1016} 1017 1018void MPEG4Writer::writeChunks() { 1019 LOGV("writeChunks"); 1020 size_t outstandingChunks = 0; 1021 while (!mChunkInfos.empty()) { 1022 List<ChunkInfo>::iterator it = mChunkInfos.begin(); 1023 while (!it->mChunks.empty()) { 1024 CHECK_EQ(OK, writeOneChunk()); 1025 ++outstandingChunks; 1026 } 1027 it->mTrack = NULL; 1028 mChunkInfos.erase(it); 1029 } 1030 mChunkInfos.clear(); 1031 LOGD("%d chunks are written in the last batch", outstandingChunks); 1032} 1033 1034status_t MPEG4Writer::writeOneChunk() { 1035 LOGV("writeOneChunk"); 1036 1037 // Find the smallest timestamp, and write that chunk out 1038 // XXX: What if some track is just too slow? 1039 int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL; 1040 Track *track = NULL; 1041 for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 1042 it != mChunkInfos.end(); ++it) { 1043 if (!it->mChunks.empty()) { 1044 List<Chunk>::iterator chunkIt = it->mChunks.begin(); 1045 if (chunkIt->mTimeStampUs < minTimestampUs) { 1046 minTimestampUs = chunkIt->mTimeStampUs; 1047 track = it->mTrack; 1048 } 1049 } 1050 } 1051 1052 if (track == NULL) { 1053 LOGV("Nothing to be written after all"); 1054 return OK; 1055 } 1056 1057 if (mIsFirstChunk) { 1058 mIsFirstChunk = false; 1059 } 1060 for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 1061 it != mChunkInfos.end(); ++it) { 1062 if (it->mTrack == track) { 1063 writeFirstChunk(&(*it)); 1064 } 1065 } 1066 return OK; 1067} 1068 1069void MPEG4Writer::threadFunc() { 1070 LOGV("threadFunc"); 1071 1072 while (!mDone) { 1073 { 1074 Mutex::Autolock autolock(mLock); 1075 mChunkReadyCondition.wait(mLock); 1076 CHECK_EQ(writeOneChunk(), OK); 1077 } 1078 } 1079 1080 { 1081 // Write ALL samples 1082 Mutex::Autolock autolock(mLock); 1083 writeChunks(); 1084 } 1085} 1086 1087status_t MPEG4Writer::startWriterThread() { 1088 LOGV("startWriterThread"); 1089 1090 mDone = false; 1091 mIsFirstChunk = true; 1092 mDriftTimeUs = 0; 1093 for (List<Track *>::iterator it = mTracks.begin(); 1094 it != mTracks.end(); ++it) { 1095 ChunkInfo info; 1096 info.mTrack = *it; 1097 mChunkInfos.push_back(info); 1098 } 1099 1100 pthread_attr_t attr; 1101 pthread_attr_init(&attr); 1102 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 1103 pthread_create(&mThread, &attr, ThreadWrapper, this); 1104 pthread_attr_destroy(&attr); 1105 return OK; 1106} 1107 1108 1109status_t MPEG4Writer::Track::start(MetaData *params) { 1110 if (!mDone && mPaused) { 1111 mPaused = false; 1112 mResumed = true; 1113 return OK; 1114 } 1115 1116 int64_t startTimeUs; 1117 if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) { 1118 startTimeUs = 0; 1119 } 1120 1121 mIsRealTimeRecording = false; 1122 { 1123 int32_t isNotRealTime; 1124 if (params && params->findInt32(kKeyNotRealTime, &isNotRealTime)) { 1125 mIsRealTimeRecording = (isNotRealTime == 0); 1126 } 1127 } 1128 1129 initTrackingProgressStatus(params); 1130 1131 sp<MetaData> meta = new MetaData; 1132 meta->setInt64(kKeyTime, startTimeUs); 1133 status_t err = mSource->start(meta.get()); 1134 if (err != OK) { 1135 mDone = mReachedEOS = true; 1136 return err; 1137 } 1138 1139 pthread_attr_t attr; 1140 pthread_attr_init(&attr); 1141 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 1142 1143 mDone = false; 1144 mTrackDurationUs = 0; 1145 mReachedEOS = false; 1146 mEstimatedTrackSizeBytes = 0; 1147 mNumStcoTableEntries = 0; 1148 mNumStssTableEntries = 0; 1149 mNumStscTableEntries = 0; 1150 mNumSttsTableEntries = 0; 1151 mMdatSizeBytes = 0; 1152 1153 pthread_create(&mThread, &attr, ThreadWrapper, this); 1154 pthread_attr_destroy(&attr); 1155 1156 return OK; 1157} 1158 1159status_t MPEG4Writer::Track::pause() { 1160 mPaused = true; 1161 return OK; 1162} 1163 1164status_t MPEG4Writer::Track::stop() { 1165 if (mDone) { 1166 return OK; 1167 } 1168 1169 mDone = true; 1170 1171 void *dummy; 1172 pthread_join(mThread, &dummy); 1173 1174 status_t err = (status_t) dummy; 1175 1176 { 1177 status_t status = mSource->stop(); 1178 if (err == OK && status != OK && status != ERROR_END_OF_STREAM) { 1179 err = status; 1180 } 1181 } 1182 1183 return err; 1184} 1185 1186bool MPEG4Writer::Track::reachedEOS() { 1187 return mReachedEOS; 1188} 1189 1190// static 1191void *MPEG4Writer::Track::ThreadWrapper(void *me) { 1192 Track *track = static_cast<Track *>(me); 1193 1194 status_t err = track->threadEntry(); 1195 return (void *) err; 1196} 1197 1198static void getNalUnitType(uint8_t byte, uint8_t* type) { 1199 LOGV("getNalUnitType: %d", byte); 1200 1201 // nal_unit_type: 5-bit unsigned integer 1202 *type = (byte & 0x1F); 1203} 1204 1205static const uint8_t *findNextStartCode( 1206 const uint8_t *data, size_t length) { 1207 1208 LOGV("findNextStartCode: %p %d", data, length); 1209 1210 size_t bytesLeft = length; 1211 while (bytesLeft > 4 && 1212 memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) { 1213 --bytesLeft; 1214 } 1215 if (bytesLeft <= 4) { 1216 bytesLeft = 0; // Last parameter set 1217 } 1218 return &data[length - bytesLeft]; 1219} 1220 1221const uint8_t *MPEG4Writer::Track::parseParamSet( 1222 const uint8_t *data, size_t length, int type, size_t *paramSetLen) { 1223 1224 LOGV("parseParamSet"); 1225 CHECK(type == kNalUnitTypeSeqParamSet || 1226 type == kNalUnitTypePicParamSet); 1227 1228 const uint8_t *nextStartCode = findNextStartCode(data, length); 1229 *paramSetLen = nextStartCode - data; 1230 if (*paramSetLen == 0) { 1231 LOGE("Param set is malformed, since its length is 0"); 1232 return NULL; 1233 } 1234 1235 AVCParamSet paramSet(*paramSetLen, data); 1236 if (type == kNalUnitTypeSeqParamSet) { 1237 if (*paramSetLen < 4) { 1238 LOGE("Seq parameter set malformed"); 1239 return NULL; 1240 } 1241 if (mSeqParamSets.empty()) { 1242 mProfileIdc = data[1]; 1243 mProfileCompatible = data[2]; 1244 mLevelIdc = data[3]; 1245 } else { 1246 if (mProfileIdc != data[1] || 1247 mProfileCompatible != data[2] || 1248 mLevelIdc != data[3]) { 1249 LOGE("Inconsistent profile/level found in seq parameter sets"); 1250 return NULL; 1251 } 1252 } 1253 mSeqParamSets.push_back(paramSet); 1254 } else { 1255 mPicParamSets.push_back(paramSet); 1256 } 1257 return nextStartCode; 1258} 1259 1260status_t MPEG4Writer::Track::copyAVCCodecSpecificData( 1261 const uint8_t *data, size_t size) { 1262 LOGV("copyAVCCodecSpecificData"); 1263 1264 // 2 bytes for each of the parameter set length field 1265 // plus the 7 bytes for the header 1266 if (size < 4 + 7) { 1267 LOGE("Codec specific data length too short: %d", size); 1268 return ERROR_MALFORMED; 1269 } 1270 1271 mCodecSpecificDataSize = size; 1272 mCodecSpecificData = malloc(size); 1273 memcpy(mCodecSpecificData, data, size); 1274 return OK; 1275} 1276 1277status_t MPEG4Writer::Track::parseAVCCodecSpecificData( 1278 const uint8_t *data, size_t size) { 1279 1280 LOGV("parseAVCCodecSpecificData"); 1281 // Data starts with a start code. 1282 // SPS and PPS are separated with start codes. 1283 // Also, SPS must come before PPS 1284 uint8_t type = kNalUnitTypeSeqParamSet; 1285 bool gotSps = false; 1286 bool gotPps = false; 1287 const uint8_t *tmp = data; 1288 const uint8_t *nextStartCode = data; 1289 size_t bytesLeft = size; 1290 size_t paramSetLen = 0; 1291 mCodecSpecificDataSize = 0; 1292 while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 1293 getNalUnitType(*(tmp + 4), &type); 1294 if (type == kNalUnitTypeSeqParamSet) { 1295 if (gotPps) { 1296 LOGE("SPS must come before PPS"); 1297 return ERROR_MALFORMED; 1298 } 1299 if (!gotSps) { 1300 gotSps = true; 1301 } 1302 nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 1303 } else if (type == kNalUnitTypePicParamSet) { 1304 if (!gotSps) { 1305 LOGE("SPS must come before PPS"); 1306 return ERROR_MALFORMED; 1307 } 1308 if (!gotPps) { 1309 gotPps = true; 1310 } 1311 nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 1312 } else { 1313 LOGE("Only SPS and PPS Nal units are expected"); 1314 return ERROR_MALFORMED; 1315 } 1316 1317 if (nextStartCode == NULL) { 1318 return ERROR_MALFORMED; 1319 } 1320 1321 // Move on to find the next parameter set 1322 bytesLeft -= nextStartCode - tmp; 1323 tmp = nextStartCode; 1324 mCodecSpecificDataSize += (2 + paramSetLen); 1325 } 1326 1327 { 1328 // Check on the number of seq parameter sets 1329 size_t nSeqParamSets = mSeqParamSets.size(); 1330 if (nSeqParamSets == 0) { 1331 LOGE("Cound not find sequence parameter set"); 1332 return ERROR_MALFORMED; 1333 } 1334 1335 if (nSeqParamSets > 0x1F) { 1336 LOGE("Too many seq parameter sets (%d) found", nSeqParamSets); 1337 return ERROR_MALFORMED; 1338 } 1339 } 1340 1341 { 1342 // Check on the number of pic parameter sets 1343 size_t nPicParamSets = mPicParamSets.size(); 1344 if (nPicParamSets == 0) { 1345 LOGE("Cound not find picture parameter set"); 1346 return ERROR_MALFORMED; 1347 } 1348 if (nPicParamSets > 0xFF) { 1349 LOGE("Too many pic parameter sets (%d) found", nPicParamSets); 1350 return ERROR_MALFORMED; 1351 } 1352 } 1353 1354 { 1355 // Check on the profiles 1356 // These profiles requires additional parameter set extensions 1357 if (mProfileIdc == 100 || mProfileIdc == 110 || 1358 mProfileIdc == 122 || mProfileIdc == 144) { 1359 LOGE("Sorry, no support for profile_idc: %d!", mProfileIdc); 1360 return BAD_VALUE; 1361 } 1362 } 1363 1364 return OK; 1365} 1366 1367status_t MPEG4Writer::Track::makeAVCCodecSpecificData( 1368 const uint8_t *data, size_t size) { 1369 1370 if (mCodecSpecificData != NULL) { 1371 LOGE("Already have codec specific data"); 1372 return ERROR_MALFORMED; 1373 } 1374 1375 if (size < 4) { 1376 LOGE("Codec specific data length too short: %d", size); 1377 return ERROR_MALFORMED; 1378 } 1379 1380 // Data is in the form of AVCCodecSpecificData 1381 if (memcmp("\x00\x00\x00\x01", data, 4)) { 1382 return copyAVCCodecSpecificData(data, size); 1383 } 1384 1385 if (parseAVCCodecSpecificData(data, size) != OK) { 1386 return ERROR_MALFORMED; 1387 } 1388 1389 // ISO 14496-15: AVC file format 1390 mCodecSpecificDataSize += 7; // 7 more bytes in the header 1391 mCodecSpecificData = malloc(mCodecSpecificDataSize); 1392 uint8_t *header = (uint8_t *)mCodecSpecificData; 1393 header[0] = 1; // version 1394 header[1] = mProfileIdc; // profile indication 1395 header[2] = mProfileCompatible; // profile compatibility 1396 header[3] = mLevelIdc; 1397 1398 // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne 1399 if (mOwner->useNalLengthFour()) { 1400 header[4] = 0xfc | 3; // length size == 4 bytes 1401 } else { 1402 header[4] = 0xfc | 1; // length size == 2 bytes 1403 } 1404 1405 // 3-bit '111' followed by 5-bit numSequenceParameterSets 1406 int nSequenceParamSets = mSeqParamSets.size(); 1407 header[5] = 0xe0 | nSequenceParamSets; 1408 header += 6; 1409 for (List<AVCParamSet>::iterator it = mSeqParamSets.begin(); 1410 it != mSeqParamSets.end(); ++it) { 1411 // 16-bit sequence parameter set length 1412 uint16_t seqParamSetLength = it->mLength; 1413 header[0] = seqParamSetLength >> 8; 1414 header[1] = seqParamSetLength & 0xff; 1415 1416 // SPS NAL unit (sequence parameter length bytes) 1417 memcpy(&header[2], it->mData, seqParamSetLength); 1418 header += (2 + seqParamSetLength); 1419 } 1420 1421 // 8-bit nPictureParameterSets 1422 int nPictureParamSets = mPicParamSets.size(); 1423 header[0] = nPictureParamSets; 1424 header += 1; 1425 for (List<AVCParamSet>::iterator it = mPicParamSets.begin(); 1426 it != mPicParamSets.end(); ++it) { 1427 // 16-bit picture parameter set length 1428 uint16_t picParamSetLength = it->mLength; 1429 header[0] = picParamSetLength >> 8; 1430 header[1] = picParamSetLength & 0xff; 1431 1432 // PPS Nal unit (picture parameter set length bytes) 1433 memcpy(&header[2], it->mData, picParamSetLength); 1434 header += (2 + picParamSetLength); 1435 } 1436 1437 return OK; 1438} 1439 1440status_t MPEG4Writer::Track::threadEntry() { 1441 int32_t count = 0; 1442 const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 1443 int64_t chunkTimestampUs = 0; 1444 int32_t nChunks = 0; 1445 int32_t nZeroLengthFrames = 0; 1446 int64_t lastTimestampUs = 0; // Previous sample time stamp in ms 1447 int64_t lastDurationUs = 0; // Between the previous two samples in ms 1448 int64_t currDurationTicks = 0; // Timescale based ticks 1449 int64_t lastDurationTicks = 0; // Timescale based ticks 1450 int32_t sampleCount = 1; // Sample count in the current stts table entry 1451 uint32_t previousSampleSize = 0; // Size of the previous sample 1452 int64_t previousPausedDurationUs = 0; 1453 int64_t timestampUs; 1454 1455 sp<MetaData> meta_data; 1456 1457 mNumSamples = 0; 1458 status_t err = OK; 1459 MediaBuffer *buffer; 1460 while (!mDone && (err = mSource->read(&buffer)) == OK) { 1461 if (buffer->range_length() == 0) { 1462 buffer->release(); 1463 buffer = NULL; 1464 ++nZeroLengthFrames; 1465 continue; 1466 } 1467 1468 // If the codec specific data has not been received yet, delay pause. 1469 // After the codec specific data is received, discard what we received 1470 // when the track is to be paused. 1471 if (mPaused && !mResumed) { 1472 buffer->release(); 1473 buffer = NULL; 1474 continue; 1475 } 1476 1477 ++count; 1478 1479 int32_t isCodecConfig; 1480 if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 1481 && isCodecConfig) { 1482 CHECK(!mGotAllCodecSpecificData); 1483 1484 if (mIsAvc) { 1485 status_t err = makeAVCCodecSpecificData( 1486 (const uint8_t *)buffer->data() 1487 + buffer->range_offset(), 1488 buffer->range_length()); 1489 CHECK_EQ(OK, err); 1490 } else if (mIsMPEG4) { 1491 mCodecSpecificDataSize = buffer->range_length(); 1492 mCodecSpecificData = malloc(mCodecSpecificDataSize); 1493 memcpy(mCodecSpecificData, 1494 (const uint8_t *)buffer->data() 1495 + buffer->range_offset(), 1496 buffer->range_length()); 1497 } 1498 1499 buffer->release(); 1500 buffer = NULL; 1501 1502 mGotAllCodecSpecificData = true; 1503 continue; 1504 } 1505 1506 // Make a deep copy of the MediaBuffer and Metadata and release 1507 // the original as soon as we can 1508 MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 1509 memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 1510 buffer->range_length()); 1511 copy->set_range(0, buffer->range_length()); 1512 meta_data = new MetaData(*buffer->meta_data().get()); 1513 buffer->release(); 1514 buffer = NULL; 1515 1516 if (mIsAvc) StripStartcode(copy); 1517 1518 size_t sampleSize = copy->range_length(); 1519 if (mIsAvc) { 1520 if (mOwner->useNalLengthFour()) { 1521 sampleSize += 4; 1522 } else { 1523 sampleSize += 2; 1524 } 1525 } 1526 1527 // Max file size or duration handling 1528 mMdatSizeBytes += sampleSize; 1529 updateTrackSizeEstimate(); 1530 1531 if (mOwner->exceedsFileSizeLimit()) { 1532 mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 1533 break; 1534 } 1535 if (mOwner->exceedsFileDurationLimit()) { 1536 mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 1537 break; 1538 } 1539 1540 1541 int32_t isSync = false; 1542 meta_data->findInt32(kKeyIsSyncFrame, &isSync); 1543 1544 /* 1545 * The original timestamp found in the data buffer will be modified as below: 1546 * 1547 * There is a playback offset into this track if the track's start time 1548 * is not the same as the movie start time, which will be recorded in edst 1549 * box of the output file. The playback offset is to make sure that the 1550 * starting time of the audio/video tracks are synchronized. Although the 1551 * track's media timestamp may be subject to various modifications 1552 * as outlined below, the track's playback offset time remains unchanged 1553 * once the first data buffer of the track is received. 1554 * 1555 * The media time stamp will be calculated by subtracting the playback offset 1556 * (and potential pause durations) from the original timestamp in the buffer. 1557 * 1558 * If this track is a video track for a real-time recording application with 1559 * both audio and video tracks, its media timestamp will subject to further 1560 * modification based on the media clock of the audio track. This modification 1561 * is needed for the purpose of maintaining good audio/video synchronization. 1562 * 1563 * If the recording session is paused and resumed multiple times, the track 1564 * media timestamp will be modified as if the recording session had never been 1565 * paused at all during playback of the recorded output file. In other words, 1566 * the output file will have no memory of pause/resume durations. 1567 * 1568 */ 1569 CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 1570 LOGV("%s timestampUs: %lld", mIsAudio? "Audio": "Video", timestampUs); 1571 1572//////////////////////////////////////////////////////////////////////////////// 1573 if (mSampleSizes.empty()) { 1574 mStartTimestampUs = timestampUs; 1575 mOwner->setStartTimestampUs(mStartTimestampUs); 1576 previousPausedDurationUs = mStartTimestampUs; 1577 } 1578 1579 if (mResumed) { 1580 int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs; 1581 CHECK(durExcludingEarlierPausesUs >= 0); 1582 int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs; 1583 CHECK(pausedDurationUs >= lastDurationUs); 1584 previousPausedDurationUs += pausedDurationUs - lastDurationUs; 1585 mResumed = false; 1586 } 1587 1588 timestampUs -= previousPausedDurationUs; 1589 CHECK(timestampUs >= 0); 1590 if (mIsRealTimeRecording && !mIsAudio) { 1591 // The minor adjustment on the timestamp is heuristic/experimental 1592 // We are adjusting the timestamp to reduce the fluctuation of the duration 1593 // of neighboring samples. This in turn helps reduce the track header size, 1594 // especially, the number of entries in the "stts" box. 1595 if (mNumSamples > 1) { 1596 int64_t currDriftTimeUs = mOwner->getDriftTimeUs(); 1597 int64_t durationUs = timestampUs + currDriftTimeUs - lastTimestampUs; 1598 int64_t diffUs = (durationUs > lastDurationUs) 1599 ? durationUs - lastDurationUs 1600 : lastDurationUs - durationUs; 1601 if (diffUs <= 5000) { // XXX: Magic number 5ms 1602 timestampUs = lastTimestampUs + lastDurationUs; 1603 } else { 1604 timestampUs += currDriftTimeUs; 1605 } 1606 } 1607 } 1608 CHECK(timestampUs >= 0); 1609 if (mNumSamples > 1) { 1610 if (timestampUs <= lastTimestampUs) { 1611 LOGW("Frame arrives too late!"); 1612 // Don't drop the late frame, since dropping a frame may cause 1613 // problems later during playback 1614 1615 // The idea here is to avoid having two or more samples with the 1616 // same timestamp in the output file. 1617 if (mTimeScale >= 1000000LL) { 1618 timestampUs = lastTimestampUs + 1; 1619 } else { 1620 timestampUs = lastTimestampUs + (1000000LL + (mTimeScale >> 1)) / mTimeScale; 1621 } 1622 } 1623 } 1624 1625 LOGV("%s media time stamp: %lld and previous paused duration %lld", 1626 mIsAudio? "Audio": "Video", timestampUs, previousPausedDurationUs); 1627 if (timestampUs > mTrackDurationUs) { 1628 mTrackDurationUs = timestampUs; 1629 } 1630 1631 mSampleSizes.push_back(sampleSize); 1632 ++mNumSamples; 1633 if (mNumSamples > 2) { 1634 // We need to use the time scale based ticks, rather than the 1635 // timestamp itself to determine whether we have to use a new 1636 // stts entry, since we may have rounding errors. 1637 // The calculation is intended to reduce the accumulated 1638 // rounding errors. 1639 currDurationTicks = 1640 ((timestampUs * mTimeScale + 500000LL) / 1000000LL - 1641 (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL); 1642 1643 if (currDurationTicks != lastDurationTicks) { 1644 addOneSttsTableEntry(sampleCount, lastDurationUs); 1645 sampleCount = 1; 1646 } else { 1647 ++sampleCount; 1648 } 1649 } 1650 if (mSamplesHaveSameSize) { 1651 if (mNumSamples >= 2 && previousSampleSize != sampleSize) { 1652 mSamplesHaveSameSize = false; 1653 } 1654 previousSampleSize = sampleSize; 1655 } 1656 lastDurationUs = timestampUs - lastTimestampUs; 1657 lastDurationTicks = currDurationTicks; 1658 lastTimestampUs = timestampUs; 1659 if (mIsRealTimeRecording && mIsAudio) { 1660 int64_t driftTimeUs = 0; 1661 if (meta_data->findInt64(kKeyDriftTime, &driftTimeUs)) { 1662 mOwner->setDriftTimeUs(driftTimeUs); 1663 } 1664 } 1665 1666 if (isSync != 0) { 1667 addOneStssTableEntry(mNumSamples); 1668 } 1669 1670 if (mTrackingProgressStatus) { 1671 if (mPreviousTrackTimeUs <= 0) { 1672 mPreviousTrackTimeUs = mStartTimestampUs; 1673 } 1674 trackProgressStatus(timestampUs); 1675 } 1676 if (mOwner->numTracks() == 1) { 1677 off_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy) 1678 : mOwner->addSample_l(copy); 1679 if (mChunkOffsets.empty()) { 1680 addChunkOffset(offset); 1681 } 1682 copy->release(); 1683 copy = NULL; 1684 continue; 1685 } 1686 1687 mChunkSamples.push_back(copy); 1688 if (interleaveDurationUs == 0) { 1689 addOneStscTableEntry(++nChunks, 1); 1690 bufferChunk(timestampUs); 1691 } else { 1692 if (chunkTimestampUs == 0) { 1693 chunkTimestampUs = timestampUs; 1694 } else { 1695 if (timestampUs - chunkTimestampUs > interleaveDurationUs) { 1696 ++nChunks; 1697 if (nChunks == 1 || // First chunk 1698 (--(mStscTableEntries.end()))->samplesPerChunk != 1699 mChunkSamples.size()) { 1700 addOneStscTableEntry(nChunks, mChunkSamples.size()); 1701 } 1702 bufferChunk(timestampUs); 1703 chunkTimestampUs = timestampUs; 1704 } 1705 } 1706 } 1707 1708 } 1709 1710 if (mSampleSizes.empty() || // no samples written 1711 (!mIsAudio && mNumStssTableEntries == 0) || // no sync frames for video 1712 (OK != checkCodecSpecificData())) { // no codec specific data 1713 err = ERROR_MALFORMED; 1714 } 1715 mOwner->trackProgressStatus(this, -1, err); 1716 1717 // Last chunk 1718 if (mOwner->numTracks() == 1) { 1719 addOneStscTableEntry(1, mNumSamples); 1720 } else if (!mChunkSamples.empty()) { 1721 addOneStscTableEntry(++nChunks, mChunkSamples.size()); 1722 bufferChunk(timestampUs); 1723 } 1724 1725 // We don't really know how long the last frame lasts, since 1726 // there is no frame time after it, just repeat the previous 1727 // frame's duration. 1728 if (mNumSamples == 1) { 1729 lastDurationUs = 0; // A single sample's duration 1730 } else { 1731 ++sampleCount; // Count for the last sample 1732 } 1733 addOneSttsTableEntry(sampleCount, lastDurationUs); 1734 mTrackDurationUs += lastDurationUs; 1735 mReachedEOS = true; 1736 LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s", 1737 count, nZeroLengthFrames, mNumSamples, mIsAudio? "audio": "video"); 1738 1739 if (err == ERROR_END_OF_STREAM) { 1740 return OK; 1741 } 1742 return err; 1743} 1744 1745void MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) { 1746 LOGV("trackProgressStatus: %lld us", timeUs); 1747 if (mTrackEveryTimeDurationUs > 0 && 1748 timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 1749 LOGV("Fire time tracking progress status at %lld us", timeUs); 1750 mOwner->trackProgressStatus(this, timeUs - mPreviousTrackTimeUs, err); 1751 mPreviousTrackTimeUs = timeUs; 1752 } 1753} 1754 1755void MPEG4Writer::trackProgressStatus( 1756 const MPEG4Writer::Track* track, int64_t timeUs, status_t err) { 1757 Mutex::Autolock lock(mLock); 1758 int32_t nTracks = mTracks.size(); 1759 CHECK(nTracks >= 1); 1760 CHECK(nTracks < 64); // Arbitrary number 1761 1762 int32_t trackNum = 0; 1763 CHECK(trackNum < nTracks); 1764 trackNum <<= 16; 1765 1766 // Error notification 1767 // Do not consider ERROR_END_OF_STREAM an error 1768 if (err != OK && err != ERROR_END_OF_STREAM) { 1769 notify(MEDIA_RECORDER_EVENT_ERROR, 1770 trackNum | MEDIA_RECORDER_ERROR_UNKNOWN, 1771 err); 1772 return; 1773 } 1774 1775 if (timeUs == -1) { 1776 // Send completion notification 1777 notify(MEDIA_RECORDER_EVENT_INFO, 1778 trackNum | MEDIA_RECORDER_INFO_COMPLETION_STATUS, 1779 err); 1780 return; 1781 } else { 1782 // Send progress status 1783 notify(MEDIA_RECORDER_EVENT_INFO, 1784 trackNum | MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS, 1785 timeUs / 1000); 1786 } 1787} 1788 1789void MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) { 1790 LOGV("setDriftTimeUs: %lld us", driftTimeUs); 1791 Mutex::Autolock autolock(mLock); 1792 mDriftTimeUs = driftTimeUs; 1793} 1794 1795int64_t MPEG4Writer::getDriftTimeUs() { 1796 LOGV("getDriftTimeUs: %lld us", mDriftTimeUs); 1797 Mutex::Autolock autolock(mLock); 1798 return mDriftTimeUs; 1799} 1800 1801bool MPEG4Writer::useNalLengthFour() { 1802 return mUse4ByteNalLength; 1803} 1804 1805void MPEG4Writer::Track::bufferChunk(int64_t timestampUs) { 1806 LOGV("bufferChunk"); 1807 1808 Chunk chunk(this, timestampUs, mChunkSamples); 1809 mOwner->bufferChunk(chunk); 1810 mChunkSamples.clear(); 1811} 1812 1813int64_t MPEG4Writer::Track::getDurationUs() const { 1814 return mTrackDurationUs; 1815} 1816 1817int64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 1818 return mEstimatedTrackSizeBytes; 1819} 1820 1821status_t MPEG4Writer::Track::checkCodecSpecificData() const { 1822 const char *mime; 1823 CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 1824 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) || 1825 !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) || 1826 !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 1827 if (!mCodecSpecificData || 1828 mCodecSpecificDataSize <= 0) { 1829 LOGE("Missing codec specific data"); 1830 return ERROR_MALFORMED; 1831 } 1832 } else { 1833 if (mCodecSpecificData || 1834 mCodecSpecificDataSize > 0) { 1835 LOGE("Unexepected codec specific data found"); 1836 return ERROR_MALFORMED; 1837 } 1838 } 1839 return OK; 1840} 1841 1842void MPEG4Writer::Track::writeTrackHeader( 1843 int32_t trackID, bool use32BitOffset) { 1844 const char *mime; 1845 bool success = mMeta->findCString(kKeyMIMEType, &mime); 1846 CHECK(success); 1847 1848 LOGV("%s track time scale: %d", 1849 mIsAudio? "Audio": "Video", mTimeScale); 1850 1851 time_t now = time(NULL); 1852 int32_t mvhdTimeScale = mOwner->getTimeScale(); 1853 int64_t trakDurationUs = getDurationUs(); 1854 1855 mOwner->beginBox("trak"); 1856 1857 mOwner->beginBox("tkhd"); 1858 // Flags = 7 to indicate that the track is enabled, and 1859 // part of the presentation 1860 mOwner->writeInt32(0x07); // version=0, flags=7 1861 mOwner->writeInt32(now); // creation time 1862 mOwner->writeInt32(now); // modification time 1863 mOwner->writeInt32(trackID); 1864 mOwner->writeInt32(0); // reserved 1865 int32_t tkhdDuration = 1866 (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 1867 mOwner->writeInt32(tkhdDuration); // in mvhd timescale 1868 mOwner->writeInt32(0); // reserved 1869 mOwner->writeInt32(0); // reserved 1870 mOwner->writeInt16(0); // layer 1871 mOwner->writeInt16(0); // alternate group 1872 mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume 1873 mOwner->writeInt16(0); // reserved 1874 1875 mOwner->writeInt32(0x10000); // matrix 1876 mOwner->writeInt32(0); 1877 mOwner->writeInt32(0); 1878 mOwner->writeInt32(0); 1879 mOwner->writeInt32(0x10000); 1880 mOwner->writeInt32(0); 1881 mOwner->writeInt32(0); 1882 mOwner->writeInt32(0); 1883 mOwner->writeInt32(0x40000000); 1884 1885 if (mIsAudio) { 1886 mOwner->writeInt32(0); 1887 mOwner->writeInt32(0); 1888 } else { 1889 int32_t width, height; 1890 bool success = mMeta->findInt32(kKeyWidth, &width); 1891 success = success && mMeta->findInt32(kKeyHeight, &height); 1892 CHECK(success); 1893 1894 mOwner->writeInt32(width << 16); // 32-bit fixed-point value 1895 mOwner->writeInt32(height << 16); // 32-bit fixed-point value 1896 } 1897 mOwner->endBox(); // tkhd 1898 1899 int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 1900 if (mStartTimestampUs != moovStartTimeUs) { 1901 mOwner->beginBox("edts"); 1902 mOwner->beginBox("elst"); 1903 mOwner->writeInt32(0); // version=0, flags=0: 32-bit time 1904 mOwner->writeInt32(2); // never ends with an empty list 1905 1906 // First elst entry: specify the starting time offset 1907 int64_t offsetUs = mStartTimestampUs - moovStartTimeUs; 1908 LOGV("OffsetUs: %lld", offsetUs); 1909 int32_t seg = (offsetUs * mvhdTimeScale + 5E5) / 1E6; 1910 mOwner->writeInt32(seg); // in mvhd timecale 1911 mOwner->writeInt32(-1); // starting time offset 1912 mOwner->writeInt32(1 << 16); // rate = 1.0 1913 1914 // Second elst entry: specify the track duration 1915 seg = (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 1916 mOwner->writeInt32(seg); // in mvhd timescale 1917 mOwner->writeInt32(0); 1918 mOwner->writeInt32(1 << 16); 1919 mOwner->endBox(); 1920 mOwner->endBox(); 1921 } 1922 1923 mOwner->beginBox("mdia"); 1924 1925 mOwner->beginBox("mdhd"); 1926 mOwner->writeInt32(0); // version=0, flags=0 1927 mOwner->writeInt32(now); // creation time 1928 mOwner->writeInt32(now); // modification time 1929 mOwner->writeInt32(mTimeScale); // media timescale 1930 int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6; 1931 mOwner->writeInt32(mdhdDuration); // use media timescale 1932 // Language follows the three letter standard ISO-639-2/T 1933 // 'e', 'n', 'g' for "English", for instance. 1934 // Each character is packed as the difference between its ASCII value and 0x60. 1935 // For "English", these are 00101, 01110, 00111. 1936 // XXX: Where is the padding bit located: 0x15C7? 1937 mOwner->writeInt16(0); // language code 1938 mOwner->writeInt16(0); // predefined 1939 mOwner->endBox(); 1940 1941 mOwner->beginBox("hdlr"); 1942 mOwner->writeInt32(0); // version=0, flags=0 1943 mOwner->writeInt32(0); // component type: should be mhlr 1944 mOwner->writeFourcc(mIsAudio ? "soun" : "vide"); // component subtype 1945 mOwner->writeInt32(0); // reserved 1946 mOwner->writeInt32(0); // reserved 1947 mOwner->writeInt32(0); // reserved 1948 // Removing "r" for the name string just makes the string 4 byte aligned 1949 mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle"); // name 1950 mOwner->endBox(); 1951 1952 mOwner->beginBox("minf"); 1953 if (mIsAudio) { 1954 mOwner->beginBox("smhd"); 1955 mOwner->writeInt32(0); // version=0, flags=0 1956 mOwner->writeInt16(0); // balance 1957 mOwner->writeInt16(0); // reserved 1958 mOwner->endBox(); 1959 } else { 1960 mOwner->beginBox("vmhd"); 1961 mOwner->writeInt32(0x01); // version=0, flags=1 1962 mOwner->writeInt16(0); // graphics mode 1963 mOwner->writeInt16(0); // opcolor 1964 mOwner->writeInt16(0); 1965 mOwner->writeInt16(0); 1966 mOwner->endBox(); 1967 } 1968 1969 mOwner->beginBox("dinf"); 1970 mOwner->beginBox("dref"); 1971 mOwner->writeInt32(0); // version=0, flags=0 1972 mOwner->writeInt32(1); // entry count (either url or urn) 1973 // The table index here refers to the sample description index 1974 // in the sample table entries. 1975 mOwner->beginBox("url "); 1976 mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 1977 mOwner->endBox(); // url 1978 mOwner->endBox(); // dref 1979 mOwner->endBox(); // dinf 1980 1981 mOwner->beginBox("stbl"); 1982 1983 mOwner->beginBox("stsd"); 1984 mOwner->writeInt32(0); // version=0, flags=0 1985 mOwner->writeInt32(1); // entry count 1986 if (mIsAudio) { 1987 const char *fourcc = NULL; 1988 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 1989 fourcc = "samr"; 1990 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 1991 fourcc = "sawb"; 1992 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 1993 fourcc = "mp4a"; 1994 } else { 1995 LOGE("Unknown mime type '%s'.", mime); 1996 CHECK(!"should not be here, unknown mime type."); 1997 } 1998 1999 mOwner->beginBox(fourcc); // audio format 2000 mOwner->writeInt32(0); // reserved 2001 mOwner->writeInt16(0); // reserved 2002 mOwner->writeInt16(0x1); // data ref index 2003 mOwner->writeInt32(0); // reserved 2004 mOwner->writeInt32(0); // reserved 2005 int32_t nChannels; 2006 CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 2007 mOwner->writeInt16(nChannels); // channel count 2008 mOwner->writeInt16(16); // sample size 2009 mOwner->writeInt16(0); // predefined 2010 mOwner->writeInt16(0); // reserved 2011 2012 int32_t samplerate; 2013 bool success = mMeta->findInt32(kKeySampleRate, &samplerate); 2014 CHECK(success); 2015 mOwner->writeInt32(samplerate << 16); 2016 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2017 mOwner->beginBox("esds"); 2018 CHECK(mCodecSpecificData); 2019 CHECK(mCodecSpecificDataSize > 0); 2020 2021 mOwner->writeInt32(0); // version=0, flags=0 2022 mOwner->writeInt8(0x03); // ES_DescrTag 2023 mOwner->writeInt8(23 + mCodecSpecificDataSize); 2024 mOwner->writeInt16(0x0000);// ES_ID 2025 mOwner->writeInt8(0x00); 2026 2027 mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2028 mOwner->writeInt8(15 + mCodecSpecificDataSize); 2029 mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 2030 mOwner->writeInt8(0x15); // streamType AudioStream 2031 2032 mOwner->writeInt16(0x03); // XXX 2033 mOwner->writeInt8(0x00); // buffer size 24-bit 2034 mOwner->writeInt32(96000); // max bit rate 2035 mOwner->writeInt32(96000); // avg bit rate 2036 2037 mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2038 mOwner->writeInt8(mCodecSpecificDataSize); 2039 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2040 2041 static const uint8_t kData2[] = { 2042 0x06, // SLConfigDescriptorTag 2043 0x01, 2044 0x02 2045 }; 2046 mOwner->write(kData2, sizeof(kData2)); 2047 2048 mOwner->endBox(); // esds 2049 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) || 2050 !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 2051 // 3gpp2 Spec AMRSampleEntry fields 2052 mOwner->beginBox("damr"); 2053 mOwner->writeCString(" "); // vendor: 4 bytes 2054 mOwner->writeInt8(0); // decoder version 2055 mOwner->writeInt16(0x83FF); // mode set: all enabled 2056 mOwner->writeInt8(0); // mode change period 2057 mOwner->writeInt8(1); // frames per sample 2058 mOwner->endBox(); 2059 } 2060 mOwner->endBox(); 2061 } else { 2062 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2063 mOwner->beginBox("mp4v"); 2064 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2065 mOwner->beginBox("s263"); 2066 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2067 mOwner->beginBox("avc1"); 2068 } else { 2069 LOGE("Unknown mime type '%s'.", mime); 2070 CHECK(!"should not be here, unknown mime type."); 2071 } 2072 2073 mOwner->writeInt32(0); // reserved 2074 mOwner->writeInt16(0); // reserved 2075 mOwner->writeInt16(1); // data ref index 2076 mOwner->writeInt16(0); // predefined 2077 mOwner->writeInt16(0); // reserved 2078 mOwner->writeInt32(0); // predefined 2079 mOwner->writeInt32(0); // predefined 2080 mOwner->writeInt32(0); // predefined 2081 2082 int32_t width, height; 2083 bool success = mMeta->findInt32(kKeyWidth, &width); 2084 success = success && mMeta->findInt32(kKeyHeight, &height); 2085 CHECK(success); 2086 2087 mOwner->writeInt16(width); 2088 mOwner->writeInt16(height); 2089 mOwner->writeInt32(0x480000); // horiz resolution 2090 mOwner->writeInt32(0x480000); // vert resolution 2091 mOwner->writeInt32(0); // reserved 2092 mOwner->writeInt16(1); // frame count 2093 mOwner->write(" ", 32); 2094 mOwner->writeInt16(0x18); // depth 2095 mOwner->writeInt16(-1); // predefined 2096 2097 CHECK(23 + mCodecSpecificDataSize < 128); 2098 2099 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2100 CHECK(mCodecSpecificData); 2101 CHECK(mCodecSpecificDataSize > 0); 2102 mOwner->beginBox("esds"); 2103 2104 mOwner->writeInt32(0); // version=0, flags=0 2105 2106 mOwner->writeInt8(0x03); // ES_DescrTag 2107 mOwner->writeInt8(23 + mCodecSpecificDataSize); 2108 mOwner->writeInt16(0x0000); // ES_ID 2109 mOwner->writeInt8(0x1f); 2110 2111 mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2112 mOwner->writeInt8(15 + mCodecSpecificDataSize); 2113 mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 2114 mOwner->writeInt8(0x11); // streamType VisualStream 2115 2116 static const uint8_t kData[] = { 2117 0x01, 0x77, 0x00, 2118 0x00, 0x03, 0xe8, 0x00, 2119 0x00, 0x03, 0xe8, 0x00 2120 }; 2121 mOwner->write(kData, sizeof(kData)); 2122 2123 mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2124 2125 mOwner->writeInt8(mCodecSpecificDataSize); 2126 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2127 2128 static const uint8_t kData2[] = { 2129 0x06, // SLConfigDescriptorTag 2130 0x01, 2131 0x02 2132 }; 2133 mOwner->write(kData2, sizeof(kData2)); 2134 2135 mOwner->endBox(); // esds 2136 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2137 mOwner->beginBox("d263"); 2138 2139 mOwner->writeInt32(0); // vendor 2140 mOwner->writeInt8(0); // decoder version 2141 mOwner->writeInt8(10); // level: 10 2142 mOwner->writeInt8(0); // profile: 0 2143 2144 mOwner->endBox(); // d263 2145 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2146 CHECK(mCodecSpecificData); 2147 CHECK(mCodecSpecificDataSize >= 5); 2148 2149 // Patch avcc's lengthSize field to match the number 2150 // of bytes we use to indicate the size of a nal unit. 2151 uint8_t *ptr = (uint8_t *)mCodecSpecificData; 2152 ptr[4] = 2153 (ptr[4] & 0xfc) 2154 | (mOwner->useNalLengthFour() ? 3 : 1); 2155 2156 mOwner->beginBox("avcC"); 2157 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2158 mOwner->endBox(); // avcC 2159 } 2160 2161 mOwner->beginBox("pasp"); 2162 // This is useful if the pixel is not square 2163 mOwner->writeInt32(1 << 16); // hspacing 2164 mOwner->writeInt32(1 << 16); // vspacing 2165 mOwner->endBox(); // pasp 2166 mOwner->endBox(); // mp4v, s263 or avc1 2167 } 2168 mOwner->endBox(); // stsd 2169 2170 mOwner->beginBox("stts"); 2171 mOwner->writeInt32(0); // version=0, flags=0 2172 mOwner->writeInt32(mNumSttsTableEntries); 2173 int64_t prevTimestampUs = 0; 2174 for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin(); 2175 it != mSttsTableEntries.end(); ++it) { 2176 mOwner->writeInt32(it->sampleCount); 2177 2178 // Make sure that we are calculating the sample duration the exactly 2179 // same way as we made decision on how to create stts entries. 2180 int64_t currTimestampUs = prevTimestampUs + it->sampleDurationUs; 2181 int32_t dur = ((currTimestampUs * mTimeScale + 500000LL) / 1000000LL - 2182 (prevTimestampUs * mTimeScale + 500000LL) / 1000000LL); 2183 prevTimestampUs += (it->sampleCount * it->sampleDurationUs); 2184 2185 mOwner->writeInt32(dur); 2186 } 2187 mOwner->endBox(); // stts 2188 2189 if (!mIsAudio) { 2190 mOwner->beginBox("stss"); 2191 mOwner->writeInt32(0); // version=0, flags=0 2192 mOwner->writeInt32(mNumStssTableEntries); // number of sync frames 2193 for (List<int32_t>::iterator it = mStssTableEntries.begin(); 2194 it != mStssTableEntries.end(); ++it) { 2195 mOwner->writeInt32(*it); 2196 } 2197 mOwner->endBox(); // stss 2198 } 2199 2200 mOwner->beginBox("stsz"); 2201 mOwner->writeInt32(0); // version=0, flags=0 2202 if (mSamplesHaveSameSize) { 2203 List<size_t>::iterator it = mSampleSizes.begin(); 2204 mOwner->writeInt32(*it); // default sample size 2205 } else { 2206 mOwner->writeInt32(0); 2207 } 2208 mOwner->writeInt32(mNumSamples); 2209 if (!mSamplesHaveSameSize) { 2210 for (List<size_t>::iterator it = mSampleSizes.begin(); 2211 it != mSampleSizes.end(); ++it) { 2212 mOwner->writeInt32(*it); 2213 } 2214 } 2215 mOwner->endBox(); // stsz 2216 2217 mOwner->beginBox("stsc"); 2218 mOwner->writeInt32(0); // version=0, flags=0 2219 mOwner->writeInt32(mNumStscTableEntries); 2220 for (List<StscTableEntry>::iterator it = mStscTableEntries.begin(); 2221 it != mStscTableEntries.end(); ++it) { 2222 mOwner->writeInt32(it->firstChunk); 2223 mOwner->writeInt32(it->samplesPerChunk); 2224 mOwner->writeInt32(it->sampleDescriptionId); 2225 } 2226 mOwner->endBox(); // stsc 2227 mOwner->beginBox(use32BitOffset? "stco": "co64"); 2228 mOwner->writeInt32(0); // version=0, flags=0 2229 mOwner->writeInt32(mNumStcoTableEntries); 2230 for (List<off_t>::iterator it = mChunkOffsets.begin(); 2231 it != mChunkOffsets.end(); ++it) { 2232 if (use32BitOffset) { 2233 mOwner->writeInt32(static_cast<int32_t>(*it)); 2234 } else { 2235 mOwner->writeInt64((*it)); 2236 } 2237 } 2238 mOwner->endBox(); // stco or co64 2239 2240 mOwner->endBox(); // stbl 2241 mOwner->endBox(); // minf 2242 mOwner->endBox(); // mdia 2243 mOwner->endBox(); // trak 2244} 2245 2246} // namespace android 2247