MPEG4Writer.cpp revision 1d6fa7af1288b550faabe4ec2cf98684236723db
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 <inttypes.h> 20#include <utils/Log.h> 21 22#include <arpa/inet.h> 23 24#include <pthread.h> 25#include <sys/prctl.h> 26 27#include <media/stagefright/foundation/ADebug.h> 28#include <media/stagefright/MPEG4Writer.h> 29#include <media/stagefright/MediaBuffer.h> 30#include <media/stagefright/MetaData.h> 31#include <media/stagefright/MediaDefs.h> 32#include <media/stagefright/MediaErrors.h> 33#include <media/stagefright/MediaSource.h> 34#include <media/stagefright/Utils.h> 35#include <media/mediarecorder.h> 36#include <cutils/properties.h> 37#include <sys/types.h> 38#include <sys/stat.h> 39#include <fcntl.h> 40#include <unistd.h> 41 42#include "include/ESDS.h" 43 44namespace android { 45 46static const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024; 47static const int64_t kMax32BitFileSize = 0x007fffffffLL; 48static const uint8_t kNalUnitTypeSeqParamSet = 0x07; 49static const uint8_t kNalUnitTypePicParamSet = 0x08; 50static const int64_t kInitialDelayTimeUs = 700000LL; 51 52class MPEG4Writer::Track { 53public: 54 Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId); 55 56 ~Track(); 57 58 status_t start(MetaData *params); 59 status_t stop(); 60 status_t pause(); 61 bool reachedEOS(); 62 63 int64_t getDurationUs() const; 64 int64_t getEstimatedTrackSizeBytes() const; 65 void writeTrackHeader(bool use32BitOffset = true); 66 void bufferChunk(int64_t timestampUs); 67 bool isAvc() const { return mIsAvc; } 68 bool isAudio() const { return mIsAudio; } 69 bool isMPEG4() const { return mIsMPEG4; } 70 void addChunkOffset(off64_t offset); 71 int32_t getTrackId() const { return mTrackId; } 72 status_t dump(int fd, const Vector<String16>& args) const; 73 74private: 75 enum { 76 kMaxCttsOffsetTimeUs = 1000000LL, // 1 second 77 kSampleArraySize = 1000, 78 }; 79 80 // A helper class to handle faster write box with table entries 81 template<class TYPE> 82 struct ListTableEntries { 83 ListTableEntries(uint32_t elementCapacity, uint32_t entryCapacity) 84 : mElementCapacity(elementCapacity), 85 mEntryCapacity(entryCapacity), 86 mTotalNumTableEntries(0), 87 mNumValuesInCurrEntry(0), 88 mCurrTableEntriesElement(NULL) { 89 CHECK_GT(mElementCapacity, 0); 90 CHECK_GT(mEntryCapacity, 0); 91 } 92 93 // Free the allocated memory. 94 ~ListTableEntries() { 95 while (!mTableEntryList.empty()) { 96 typename List<TYPE *>::iterator it = mTableEntryList.begin(); 97 delete[] (*it); 98 mTableEntryList.erase(it); 99 } 100 } 101 102 // Replace the value at the given position by the given value. 103 // There must be an existing value at the given position. 104 // @arg value must be in network byte order 105 // @arg pos location the value must be in. 106 void set(const TYPE& value, uint32_t pos) { 107 CHECK_LT(pos, mTotalNumTableEntries * mEntryCapacity); 108 109 typename List<TYPE *>::iterator it = mTableEntryList.begin(); 110 uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity)); 111 while (it != mTableEntryList.end() && iterations > 0) { 112 ++it; 113 --iterations; 114 } 115 CHECK(it != mTableEntryList.end()); 116 CHECK_EQ(iterations, 0); 117 118 (*it)[(pos % (mElementCapacity * mEntryCapacity))] = value; 119 } 120 121 // Get the value at the given position by the given value. 122 // @arg value the retrieved value at the position in network byte order. 123 // @arg pos location the value must be in. 124 // @return true if a value is found. 125 bool get(TYPE& value, uint32_t pos) const { 126 if (pos >= mTotalNumTableEntries * mEntryCapacity) { 127 return false; 128 } 129 130 typename List<TYPE *>::iterator it = mTableEntryList.begin(); 131 uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity)); 132 while (it != mTableEntryList.end() && iterations > 0) { 133 ++it; 134 --iterations; 135 } 136 CHECK(it != mTableEntryList.end()); 137 CHECK_EQ(iterations, 0); 138 139 value = (*it)[(pos % (mElementCapacity * mEntryCapacity))]; 140 return true; 141 } 142 143 // Store a single value. 144 // @arg value must be in network byte order. 145 void add(const TYPE& value) { 146 CHECK_LT(mNumValuesInCurrEntry, mElementCapacity); 147 uint32_t nEntries = mTotalNumTableEntries % mElementCapacity; 148 uint32_t nValues = mNumValuesInCurrEntry % mEntryCapacity; 149 if (nEntries == 0 && nValues == 0) { 150 mCurrTableEntriesElement = new TYPE[mEntryCapacity * mElementCapacity]; 151 CHECK(mCurrTableEntriesElement != NULL); 152 mTableEntryList.push_back(mCurrTableEntriesElement); 153 } 154 155 uint32_t pos = nEntries * mEntryCapacity + nValues; 156 mCurrTableEntriesElement[pos] = value; 157 158 ++mNumValuesInCurrEntry; 159 if ((mNumValuesInCurrEntry % mEntryCapacity) == 0) { 160 ++mTotalNumTableEntries; 161 mNumValuesInCurrEntry = 0; 162 } 163 } 164 165 // Write out the table entries: 166 // 1. the number of entries goes first 167 // 2. followed by the values in the table enties in order 168 // @arg writer the writer to actual write to the storage 169 void write(MPEG4Writer *writer) const { 170 CHECK_EQ(mNumValuesInCurrEntry % mEntryCapacity, 0); 171 uint32_t nEntries = mTotalNumTableEntries; 172 writer->writeInt32(nEntries); 173 for (typename List<TYPE *>::iterator it = mTableEntryList.begin(); 174 it != mTableEntryList.end(); ++it) { 175 CHECK_GT(nEntries, 0); 176 if (nEntries >= mElementCapacity) { 177 writer->write(*it, sizeof(TYPE) * mEntryCapacity, mElementCapacity); 178 nEntries -= mElementCapacity; 179 } else { 180 writer->write(*it, sizeof(TYPE) * mEntryCapacity, nEntries); 181 break; 182 } 183 } 184 } 185 186 // Return the number of entries in the table. 187 uint32_t count() const { return mTotalNumTableEntries; } 188 189 private: 190 uint32_t mElementCapacity; // # entries in an element 191 uint32_t mEntryCapacity; // # of values in each entry 192 uint32_t mTotalNumTableEntries; 193 uint32_t mNumValuesInCurrEntry; // up to mEntryCapacity 194 TYPE *mCurrTableEntriesElement; 195 mutable List<TYPE *> mTableEntryList; 196 197 DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries); 198 }; 199 200 201 202 MPEG4Writer *mOwner; 203 sp<MetaData> mMeta; 204 sp<MediaSource> mSource; 205 volatile bool mDone; 206 volatile bool mPaused; 207 volatile bool mResumed; 208 volatile bool mStarted; 209 bool mIsAvc; 210 bool mIsAudio; 211 bool mIsMPEG4; 212 int32_t mTrackId; 213 int64_t mTrackDurationUs; 214 int64_t mMaxChunkDurationUs; 215 216 int64_t mEstimatedTrackSizeBytes; 217 int64_t mMdatSizeBytes; 218 int32_t mTimeScale; 219 220 pthread_t mThread; 221 222 223 List<MediaBuffer *> mChunkSamples; 224 225 bool mSamplesHaveSameSize; 226 ListTableEntries<uint32_t> *mStszTableEntries; 227 228 ListTableEntries<uint32_t> *mStcoTableEntries; 229 ListTableEntries<off64_t> *mCo64TableEntries; 230 ListTableEntries<uint32_t> *mStscTableEntries; 231 ListTableEntries<uint32_t> *mStssTableEntries; 232 ListTableEntries<uint32_t> *mSttsTableEntries; 233 ListTableEntries<uint32_t> *mCttsTableEntries; 234 235 int64_t mMinCttsOffsetTimeUs; 236 int64_t mMaxCttsOffsetTimeUs; 237 238 // Sequence parameter set or picture parameter set 239 struct AVCParamSet { 240 AVCParamSet(uint16_t length, const uint8_t *data) 241 : mLength(length), mData(data) {} 242 243 uint16_t mLength; 244 const uint8_t *mData; 245 }; 246 List<AVCParamSet> mSeqParamSets; 247 List<AVCParamSet> mPicParamSets; 248 uint8_t mProfileIdc; 249 uint8_t mProfileCompatible; 250 uint8_t mLevelIdc; 251 252 void *mCodecSpecificData; 253 size_t mCodecSpecificDataSize; 254 bool mGotAllCodecSpecificData; 255 bool mTrackingProgressStatus; 256 257 bool mReachedEOS; 258 int64_t mStartTimestampUs; 259 int64_t mStartTimeRealUs; 260 int64_t mFirstSampleTimeRealUs; 261 int64_t mPreviousTrackTimeUs; 262 int64_t mTrackEveryTimeDurationUs; 263 264 // Update the audio track's drift information. 265 void updateDriftTime(const sp<MetaData>& meta); 266 267 int32_t getStartTimeOffsetScaledTime() const; 268 269 static void *ThreadWrapper(void *me); 270 status_t threadEntry(); 271 272 const uint8_t *parseParamSet( 273 const uint8_t *data, size_t length, int type, size_t *paramSetLen); 274 275 status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size); 276 status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size); 277 status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size); 278 279 // Track authoring progress status 280 void trackProgressStatus(int64_t timeUs, status_t err = OK); 281 void initTrackingProgressStatus(MetaData *params); 282 283 void getCodecSpecificDataFromInputFormatIfPossible(); 284 285 // Determine the track time scale 286 // If it is an audio track, try to use the sampling rate as 287 // the time scale; however, if user chooses the overwrite 288 // value, the user-supplied time scale will be used. 289 void setTimeScale(); 290 291 // Simple validation on the codec specific data 292 status_t checkCodecSpecificData() const; 293 int32_t mRotation; 294 295 void updateTrackSizeEstimate(); 296 void addOneStscTableEntry(size_t chunkId, size_t sampleId); 297 void addOneStssTableEntry(size_t sampleId); 298 299 // Duration is time scale based 300 void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur); 301 void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur); 302 303 bool isTrackMalFormed() const; 304 void sendTrackSummary(bool hasMultipleTracks); 305 306 // Write the boxes 307 void writeStcoBox(bool use32BitOffset); 308 void writeStscBox(); 309 void writeStszBox(); 310 void writeStssBox(); 311 void writeSttsBox(); 312 void writeCttsBox(); 313 void writeD263Box(); 314 void writePaspBox(); 315 void writeAvccBox(); 316 void writeUrlBox(); 317 void writeDrefBox(); 318 void writeDinfBox(); 319 void writeDamrBox(); 320 void writeMdhdBox(uint32_t now); 321 void writeSmhdBox(); 322 void writeVmhdBox(); 323 void writeHdlrBox(); 324 void writeTkhdBox(uint32_t now); 325 void writeMp4aEsdsBox(); 326 void writeMp4vEsdsBox(); 327 void writeAudioFourCCBox(); 328 void writeVideoFourCCBox(); 329 void writeStblBox(bool use32BitOffset); 330 331 Track(const Track &); 332 Track &operator=(const Track &); 333}; 334 335MPEG4Writer::MPEG4Writer(const char *filename) 336 : mFd(-1), 337 mInitCheck(NO_INIT), 338 mIsRealTimeRecording(true), 339 mUse4ByteNalLength(true), 340 mUse32BitOffset(true), 341 mIsFileSizeLimitExplicitlyRequested(false), 342 mPaused(false), 343 mStarted(false), 344 mWriterThreadStarted(false), 345 mOffset(0), 346 mMdatOffset(0), 347 mEstimatedMoovBoxSize(0), 348 mInterleaveDurationUs(1000000), 349 mLatitudex10000(0), 350 mLongitudex10000(0), 351 mAreGeoTagsAvailable(false), 352 mStartTimeOffsetMs(-1) { 353 354 mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR); 355 if (mFd >= 0) { 356 mInitCheck = OK; 357 } 358} 359 360MPEG4Writer::MPEG4Writer(int fd) 361 : mFd(dup(fd)), 362 mInitCheck(mFd < 0? NO_INIT: OK), 363 mIsRealTimeRecording(true), 364 mUse4ByteNalLength(true), 365 mUse32BitOffset(true), 366 mIsFileSizeLimitExplicitlyRequested(false), 367 mPaused(false), 368 mStarted(false), 369 mWriterThreadStarted(false), 370 mOffset(0), 371 mMdatOffset(0), 372 mEstimatedMoovBoxSize(0), 373 mInterleaveDurationUs(1000000), 374 mLatitudex10000(0), 375 mLongitudex10000(0), 376 mAreGeoTagsAvailable(false), 377 mStartTimeOffsetMs(-1) { 378} 379 380MPEG4Writer::~MPEG4Writer() { 381 reset(); 382 383 while (!mTracks.empty()) { 384 List<Track *>::iterator it = mTracks.begin(); 385 delete *it; 386 (*it) = NULL; 387 mTracks.erase(it); 388 } 389 mTracks.clear(); 390} 391 392status_t MPEG4Writer::dump( 393 int fd, const Vector<String16>& args) { 394 const size_t SIZE = 256; 395 char buffer[SIZE]; 396 String8 result; 397 snprintf(buffer, SIZE, " MPEG4Writer %p\n", this); 398 result.append(buffer); 399 snprintf(buffer, SIZE, " mStarted: %s\n", mStarted? "true": "false"); 400 result.append(buffer); 401 ::write(fd, result.string(), result.size()); 402 for (List<Track *>::iterator it = mTracks.begin(); 403 it != mTracks.end(); ++it) { 404 (*it)->dump(fd, args); 405 } 406 return OK; 407} 408 409status_t MPEG4Writer::Track::dump( 410 int fd, const Vector<String16>& args) const { 411 const size_t SIZE = 256; 412 char buffer[SIZE]; 413 String8 result; 414 snprintf(buffer, SIZE, " %s track\n", mIsAudio? "Audio": "Video"); 415 result.append(buffer); 416 snprintf(buffer, SIZE, " reached EOS: %s\n", 417 mReachedEOS? "true": "false"); 418 result.append(buffer); 419 snprintf(buffer, SIZE, " frames encoded : %d\n", mStszTableEntries->count()); 420 result.append(buffer); 421 snprintf(buffer, SIZE, " duration encoded : %" PRId64 " us\n", mTrackDurationUs); 422 result.append(buffer); 423 ::write(fd, result.string(), result.size()); 424 return OK; 425} 426 427status_t MPEG4Writer::addSource(const sp<MediaSource> &source) { 428 Mutex::Autolock l(mLock); 429 if (mStarted) { 430 ALOGE("Attempt to add source AFTER recording is started"); 431 return UNKNOWN_ERROR; 432 } 433 434 // At most 2 tracks can be supported. 435 if (mTracks.size() >= 2) { 436 ALOGE("Too many tracks (%d) to add", mTracks.size()); 437 return ERROR_UNSUPPORTED; 438 } 439 440 CHECK(source.get() != NULL); 441 442 // A track of type other than video or audio is not supported. 443 const char *mime; 444 source->getFormat()->findCString(kKeyMIMEType, &mime); 445 bool isAudio = !strncasecmp(mime, "audio/", 6); 446 bool isVideo = !strncasecmp(mime, "video/", 6); 447 if (!isAudio && !isVideo) { 448 ALOGE("Track (%s) other than video or audio is not supported", 449 mime); 450 return ERROR_UNSUPPORTED; 451 } 452 453 // At this point, we know the track to be added is either 454 // video or audio. Thus, we only need to check whether it 455 // is an audio track or not (if it is not, then it must be 456 // a video track). 457 458 // No more than one video or one audio track is supported. 459 for (List<Track*>::iterator it = mTracks.begin(); 460 it != mTracks.end(); ++it) { 461 if ((*it)->isAudio() == isAudio) { 462 ALOGE("%s track already exists", isAudio? "Audio": "Video"); 463 return ERROR_UNSUPPORTED; 464 } 465 } 466 467 // This is the first track of either audio or video. 468 // Go ahead to add the track. 469 Track *track = new Track(this, source, 1 + mTracks.size()); 470 mTracks.push_back(track); 471 472 return OK; 473} 474 475status_t MPEG4Writer::startTracks(MetaData *params) { 476 if (mTracks.empty()) { 477 ALOGE("No source added"); 478 return INVALID_OPERATION; 479 } 480 481 for (List<Track *>::iterator it = mTracks.begin(); 482 it != mTracks.end(); ++it) { 483 status_t err = (*it)->start(params); 484 485 if (err != OK) { 486 for (List<Track *>::iterator it2 = mTracks.begin(); 487 it2 != it; ++it2) { 488 (*it2)->stop(); 489 } 490 491 return err; 492 } 493 } 494 return OK; 495} 496 497int64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) { 498 // This implementation is highly experimental/heurisitic. 499 // 500 // Statistical analysis shows that metadata usually accounts 501 // for a small portion of the total file size, usually < 0.6%. 502 503 // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2, 504 // where 1MB is the common file size limit for MMS application. 505 // The default MAX _MOOV_BOX_SIZE value is based on about 3 506 // minute video recording with a bit rate about 3 Mbps, because 507 // statistics also show that most of the video captured are going 508 // to be less than 3 minutes. 509 510 // If the estimation is wrong, we will pay the price of wasting 511 // some reserved space. This should not happen so often statistically. 512 static const int32_t factor = mUse32BitOffset? 1: 2; 513 static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024; // 3 KB 514 static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000); 515 int64_t size = MIN_MOOV_BOX_SIZE; 516 517 // Max file size limit is set 518 if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 519 size = mMaxFileSizeLimitBytes * 6 / 1000; 520 } 521 522 // Max file duration limit is set 523 if (mMaxFileDurationLimitUs != 0) { 524 if (bitRate > 0) { 525 int64_t size2 = 526 ((mMaxFileDurationLimitUs * bitRate * 6) / 1000 / 8000000); 527 if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 528 // When both file size and duration limits are set, 529 // we use the smaller limit of the two. 530 if (size > size2) { 531 size = size2; 532 } 533 } else { 534 // Only max file duration limit is set 535 size = size2; 536 } 537 } 538 } 539 540 if (size < MIN_MOOV_BOX_SIZE) { 541 size = MIN_MOOV_BOX_SIZE; 542 } 543 544 // Any long duration recording will be probably end up with 545 // non-streamable mp4 file. 546 if (size > MAX_MOOV_BOX_SIZE) { 547 size = MAX_MOOV_BOX_SIZE; 548 } 549 550 ALOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated" 551 " moov size %lld bytes", 552 mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size); 553 return factor * size; 554} 555 556status_t MPEG4Writer::start(MetaData *param) { 557 if (mInitCheck != OK) { 558 return UNKNOWN_ERROR; 559 } 560 561 /* 562 * Check mMaxFileSizeLimitBytes at the beginning 563 * since mMaxFileSizeLimitBytes may be implicitly 564 * changed later for 32-bit file offset even if 565 * user does not ask to set it explicitly. 566 */ 567 if (mMaxFileSizeLimitBytes != 0) { 568 mIsFileSizeLimitExplicitlyRequested = true; 569 } 570 571 int32_t use64BitOffset; 572 if (param && 573 param->findInt32(kKey64BitFileOffset, &use64BitOffset) && 574 use64BitOffset) { 575 mUse32BitOffset = false; 576 } 577 578 if (mUse32BitOffset) { 579 // Implicit 32 bit file size limit 580 if (mMaxFileSizeLimitBytes == 0) { 581 mMaxFileSizeLimitBytes = kMax32BitFileSize; 582 } 583 584 // If file size is set to be larger than the 32 bit file 585 // size limit, treat it as an error. 586 if (mMaxFileSizeLimitBytes > kMax32BitFileSize) { 587 ALOGW("32-bit file size limit (%lld bytes) too big. " 588 "It is changed to %lld bytes", 589 mMaxFileSizeLimitBytes, kMax32BitFileSize); 590 mMaxFileSizeLimitBytes = kMax32BitFileSize; 591 } 592 } 593 594 int32_t use2ByteNalLength; 595 if (param && 596 param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) && 597 use2ByteNalLength) { 598 mUse4ByteNalLength = false; 599 } 600 601 int32_t isRealTimeRecording; 602 if (param && param->findInt32(kKeyRealTimeRecording, &isRealTimeRecording)) { 603 mIsRealTimeRecording = isRealTimeRecording; 604 } 605 606 mStartTimestampUs = -1; 607 608 if (mStarted) { 609 if (mPaused) { 610 mPaused = false; 611 return startTracks(param); 612 } 613 return OK; 614 } 615 616 if (!param || 617 !param->findInt32(kKeyTimeScale, &mTimeScale)) { 618 mTimeScale = 1000; 619 } 620 CHECK_GT(mTimeScale, 0); 621 ALOGV("movie time scale: %d", mTimeScale); 622 623 /* 624 * When the requested file size limit is small, the priority 625 * is to meet the file size limit requirement, rather than 626 * to make the file streamable. mStreamableFile does not tell 627 * whether the actual recorded file is streamable or not. 628 */ 629 mStreamableFile = 630 (mMaxFileSizeLimitBytes != 0 && 631 mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes); 632 633 /* 634 * mWriteMoovBoxToMemory is true if the amount of data in moov box is 635 * smaller than the reserved free space at the beginning of a file, AND 636 * when the content of moov box is constructed. Note that video/audio 637 * frame data is always written to the file but not in the memory. 638 * 639 * Before stop()/reset() is called, mWriteMoovBoxToMemory is always 640 * false. When reset() is called at the end of a recording session, 641 * Moov box needs to be constructed. 642 * 643 * 1) Right before a moov box is constructed, mWriteMoovBoxToMemory 644 * to set to mStreamableFile so that if 645 * the file is intended to be streamable, it is set to true; 646 * otherwise, it is set to false. When the value is set to false, 647 * all the content of the moov box is written immediately to 648 * the end of the file. When the value is set to true, all the 649 * content of the moov box is written to an in-memory cache, 650 * mMoovBoxBuffer, util the following condition happens. Note 651 * that the size of the in-memory cache is the same as the 652 * reserved free space at the beginning of the file. 653 * 654 * 2) While the data of the moov box is written to an in-memory 655 * cache, the data size is checked against the reserved space. 656 * If the data size surpasses the reserved space, subsequent moov 657 * data could no longer be hold in the in-memory cache. This also 658 * indicates that the reserved space was too small. At this point, 659 * _all_ moov data must be written to the end of the file. 660 * mWriteMoovBoxToMemory must be set to false to direct the write 661 * to the file. 662 * 663 * 3) If the data size in moov box is smaller than the reserved 664 * space after moov box is completely constructed, the in-memory 665 * cache copy of the moov box is written to the reserved free 666 * space. Thus, immediately after the moov is completedly 667 * constructed, mWriteMoovBoxToMemory is always set to false. 668 */ 669 mWriteMoovBoxToMemory = false; 670 mMoovBoxBuffer = NULL; 671 mMoovBoxBufferOffset = 0; 672 673 writeFtypBox(param); 674 675 mFreeBoxOffset = mOffset; 676 677 if (mEstimatedMoovBoxSize == 0) { 678 int32_t bitRate = -1; 679 if (param) { 680 param->findInt32(kKeyBitRate, &bitRate); 681 } 682 mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate); 683 } 684 CHECK_GE(mEstimatedMoovBoxSize, 8); 685 if (mStreamableFile) { 686 // Reserve a 'free' box only for streamable file 687 lseek64(mFd, mFreeBoxOffset, SEEK_SET); 688 writeInt32(mEstimatedMoovBoxSize); 689 write("free", 4); 690 mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; 691 } else { 692 mMdatOffset = mOffset; 693 } 694 695 mOffset = mMdatOffset; 696 lseek64(mFd, mMdatOffset, SEEK_SET); 697 if (mUse32BitOffset) { 698 write("????mdat", 8); 699 } else { 700 write("\x00\x00\x00\x01mdat????????", 16); 701 } 702 703 status_t err = startWriterThread(); 704 if (err != OK) { 705 return err; 706 } 707 708 err = startTracks(param); 709 if (err != OK) { 710 return err; 711 } 712 713 mStarted = true; 714 return OK; 715} 716 717bool MPEG4Writer::use32BitFileOffset() const { 718 return mUse32BitOffset; 719} 720 721status_t MPEG4Writer::pause() { 722 if (mInitCheck != OK) { 723 return OK; 724 } 725 mPaused = true; 726 status_t err = OK; 727 for (List<Track *>::iterator it = mTracks.begin(); 728 it != mTracks.end(); ++it) { 729 status_t status = (*it)->pause(); 730 if (status != OK) { 731 err = status; 732 } 733 } 734 return err; 735} 736 737void MPEG4Writer::stopWriterThread() { 738 ALOGD("Stopping writer thread"); 739 if (!mWriterThreadStarted) { 740 return; 741 } 742 743 { 744 Mutex::Autolock autolock(mLock); 745 746 mDone = true; 747 mChunkReadyCondition.signal(); 748 } 749 750 void *dummy; 751 pthread_join(mThread, &dummy); 752 mWriterThreadStarted = false; 753 ALOGD("Writer thread stopped"); 754} 755 756/* 757 * MP4 file standard defines a composition matrix: 758 * | a b u | 759 * | c d v | 760 * | x y w | 761 * 762 * the element in the matrix is stored in the following 763 * order: {a, b, u, c, d, v, x, y, w}, 764 * where a, b, c, d, x, and y is in 16.16 format, while 765 * u, v and w is in 2.30 format. 766 */ 767void MPEG4Writer::writeCompositionMatrix(int degrees) { 768 ALOGV("writeCompositionMatrix"); 769 uint32_t a = 0x00010000; 770 uint32_t b = 0; 771 uint32_t c = 0; 772 uint32_t d = 0x00010000; 773 switch (degrees) { 774 case 0: 775 break; 776 case 90: 777 a = 0; 778 b = 0x00010000; 779 c = 0xFFFF0000; 780 d = 0; 781 break; 782 case 180: 783 a = 0xFFFF0000; 784 d = 0xFFFF0000; 785 break; 786 case 270: 787 a = 0; 788 b = 0xFFFF0000; 789 c = 0x00010000; 790 d = 0; 791 break; 792 default: 793 CHECK(!"Should never reach this unknown rotation"); 794 break; 795 } 796 797 writeInt32(a); // a 798 writeInt32(b); // b 799 writeInt32(0); // u 800 writeInt32(c); // c 801 writeInt32(d); // d 802 writeInt32(0); // v 803 writeInt32(0); // x 804 writeInt32(0); // y 805 writeInt32(0x40000000); // w 806} 807 808void MPEG4Writer::release() { 809 close(mFd); 810 mFd = -1; 811 mInitCheck = NO_INIT; 812 mStarted = false; 813} 814 815status_t MPEG4Writer::reset() { 816 if (mInitCheck != OK) { 817 return OK; 818 } else { 819 if (!mWriterThreadStarted || 820 !mStarted) { 821 if (mWriterThreadStarted) { 822 stopWriterThread(); 823 } 824 release(); 825 return OK; 826 } 827 } 828 829 status_t err = OK; 830 int64_t maxDurationUs = 0; 831 int64_t minDurationUs = 0x7fffffffffffffffLL; 832 for (List<Track *>::iterator it = mTracks.begin(); 833 it != mTracks.end(); ++it) { 834 status_t status = (*it)->stop(); 835 if (err == OK && status != OK) { 836 err = status; 837 } 838 839 int64_t durationUs = (*it)->getDurationUs(); 840 if (durationUs > maxDurationUs) { 841 maxDurationUs = durationUs; 842 } 843 if (durationUs < minDurationUs) { 844 minDurationUs = durationUs; 845 } 846 } 847 848 if (mTracks.size() > 1) { 849 ALOGD("Duration from tracks range is [%lld, %lld] us", 850 minDurationUs, maxDurationUs); 851 } 852 853 stopWriterThread(); 854 855 // Do not write out movie header on error. 856 if (err != OK) { 857 release(); 858 return err; 859 } 860 861 // Fix up the size of the 'mdat' chunk. 862 if (mUse32BitOffset) { 863 lseek64(mFd, mMdatOffset, SEEK_SET); 864 int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset)); 865 ::write(mFd, &size, 4); 866 } else { 867 lseek64(mFd, mMdatOffset + 8, SEEK_SET); 868 int64_t size = mOffset - mMdatOffset; 869 size = hton64(size); 870 ::write(mFd, &size, 8); 871 } 872 lseek64(mFd, mOffset, SEEK_SET); 873 874 // Construct moov box now 875 mMoovBoxBufferOffset = 0; 876 mWriteMoovBoxToMemory = mStreamableFile; 877 if (mWriteMoovBoxToMemory) { 878 // There is no need to allocate in-memory cache 879 // for moov box if the file is not streamable. 880 881 mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); 882 CHECK(mMoovBoxBuffer != NULL); 883 } 884 writeMoovBox(maxDurationUs); 885 886 // mWriteMoovBoxToMemory could be set to false in 887 // MPEG4Writer::write() method 888 if (mWriteMoovBoxToMemory) { 889 mWriteMoovBoxToMemory = false; 890 // Content of the moov box is saved in the cache, and the in-memory 891 // moov box needs to be written to the file in a single shot. 892 893 CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize); 894 895 // Moov box 896 lseek64(mFd, mFreeBoxOffset, SEEK_SET); 897 mOffset = mFreeBoxOffset; 898 write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset); 899 900 // Free box 901 lseek64(mFd, mOffset, SEEK_SET); 902 writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); 903 write("free", 4); 904 } else { 905 ALOGI("The mp4 file will not be streamable."); 906 } 907 908 // Free in-memory cache for moov box 909 if (mMoovBoxBuffer != NULL) { 910 free(mMoovBoxBuffer); 911 mMoovBoxBuffer = NULL; 912 mMoovBoxBufferOffset = 0; 913 } 914 915 CHECK(mBoxes.empty()); 916 917 release(); 918 return err; 919} 920 921uint32_t MPEG4Writer::getMpeg4Time() { 922 time_t now = time(NULL); 923 // MP4 file uses time counting seconds since midnight, Jan. 1, 1904 924 // while time function returns Unix epoch values which starts 925 // at 1970-01-01. Lets add the number of seconds between them 926 uint32_t mpeg4Time = now + (66 * 365 + 17) * (24 * 60 * 60); 927 return mpeg4Time; 928} 929 930void MPEG4Writer::writeMvhdBox(int64_t durationUs) { 931 uint32_t now = getMpeg4Time(); 932 beginBox("mvhd"); 933 writeInt32(0); // version=0, flags=0 934 writeInt32(now); // creation time 935 writeInt32(now); // modification time 936 writeInt32(mTimeScale); // mvhd timescale 937 int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6; 938 writeInt32(duration); 939 writeInt32(0x10000); // rate: 1.0 940 writeInt16(0x100); // volume 941 writeInt16(0); // reserved 942 writeInt32(0); // reserved 943 writeInt32(0); // reserved 944 writeCompositionMatrix(0); // matrix 945 writeInt32(0); // predefined 946 writeInt32(0); // predefined 947 writeInt32(0); // predefined 948 writeInt32(0); // predefined 949 writeInt32(0); // predefined 950 writeInt32(0); // predefined 951 writeInt32(mTracks.size() + 1); // nextTrackID 952 endBox(); // mvhd 953} 954 955void MPEG4Writer::writeMoovBox(int64_t durationUs) { 956 beginBox("moov"); 957 writeMvhdBox(durationUs); 958 if (mAreGeoTagsAvailable) { 959 writeUdtaBox(); 960 } 961 int32_t id = 1; 962 for (List<Track *>::iterator it = mTracks.begin(); 963 it != mTracks.end(); ++it, ++id) { 964 (*it)->writeTrackHeader(mUse32BitOffset); 965 } 966 endBox(); // moov 967} 968 969void MPEG4Writer::writeFtypBox(MetaData *param) { 970 beginBox("ftyp"); 971 972 int32_t fileType; 973 if (param && param->findInt32(kKeyFileType, &fileType) && 974 fileType != OUTPUT_FORMAT_MPEG_4) { 975 writeFourcc("3gp4"); 976 writeInt32(0); 977 writeFourcc("isom"); 978 writeFourcc("3gp4"); 979 } else { 980 writeFourcc("mp42"); 981 writeInt32(0); 982 writeFourcc("isom"); 983 writeFourcc("mp42"); 984 } 985 986 endBox(); 987} 988 989static bool isTestModeEnabled() { 990#if (PROPERTY_VALUE_MAX < 5) 991#error "PROPERTY_VALUE_MAX must be at least 5" 992#endif 993 994 // Test mode is enabled only if rw.media.record.test system 995 // property is enabled. 996 char value[PROPERTY_VALUE_MAX]; 997 if (property_get("rw.media.record.test", value, NULL) && 998 (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) { 999 return true; 1000 } 1001 return false; 1002} 1003 1004void MPEG4Writer::sendSessionSummary() { 1005 // Send session summary only if test mode is enabled 1006 if (!isTestModeEnabled()) { 1007 return; 1008 } 1009 1010 for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 1011 it != mChunkInfos.end(); ++it) { 1012 int trackNum = it->mTrack->getTrackId() << 28; 1013 notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 1014 trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS, 1015 it->mMaxInterChunkDurUs); 1016 } 1017} 1018 1019status_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 1020 mInterleaveDurationUs = durationUs; 1021 return OK; 1022} 1023 1024void MPEG4Writer::lock() { 1025 mLock.lock(); 1026} 1027 1028void MPEG4Writer::unlock() { 1029 mLock.unlock(); 1030} 1031 1032off64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { 1033 off64_t old_offset = mOffset; 1034 1035 ::write(mFd, 1036 (const uint8_t *)buffer->data() + buffer->range_offset(), 1037 buffer->range_length()); 1038 1039 mOffset += buffer->range_length(); 1040 1041 return old_offset; 1042} 1043 1044static void StripStartcode(MediaBuffer *buffer) { 1045 if (buffer->range_length() < 4) { 1046 return; 1047 } 1048 1049 const uint8_t *ptr = 1050 (const uint8_t *)buffer->data() + buffer->range_offset(); 1051 1052 if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 1053 buffer->set_range( 1054 buffer->range_offset() + 4, buffer->range_length() - 4); 1055 } 1056} 1057 1058off64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 1059 off64_t old_offset = mOffset; 1060 1061 size_t length = buffer->range_length(); 1062 1063 if (mUse4ByteNalLength) { 1064 uint8_t x = length >> 24; 1065 ::write(mFd, &x, 1); 1066 x = (length >> 16) & 0xff; 1067 ::write(mFd, &x, 1); 1068 x = (length >> 8) & 0xff; 1069 ::write(mFd, &x, 1); 1070 x = length & 0xff; 1071 ::write(mFd, &x, 1); 1072 1073 ::write(mFd, 1074 (const uint8_t *)buffer->data() + buffer->range_offset(), 1075 length); 1076 1077 mOffset += length + 4; 1078 } else { 1079 CHECK_LT(length, 65536); 1080 1081 uint8_t x = length >> 8; 1082 ::write(mFd, &x, 1); 1083 x = length & 0xff; 1084 ::write(mFd, &x, 1); 1085 ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length); 1086 mOffset += length + 2; 1087 } 1088 1089 return old_offset; 1090} 1091 1092size_t MPEG4Writer::write( 1093 const void *ptr, size_t size, size_t nmemb) { 1094 1095 const size_t bytes = size * nmemb; 1096 if (mWriteMoovBoxToMemory) { 1097 1098 off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes; 1099 if (moovBoxSize > mEstimatedMoovBoxSize) { 1100 // The reserved moov box at the beginning of the file 1101 // is not big enough. Moov box should be written to 1102 // the end of the file from now on, but not to the 1103 // in-memory cache. 1104 1105 // We write partial moov box that is in the memory to 1106 // the file first. 1107 for (List<off64_t>::iterator it = mBoxes.begin(); 1108 it != mBoxes.end(); ++it) { 1109 (*it) += mOffset; 1110 } 1111 lseek64(mFd, mOffset, SEEK_SET); 1112 ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset); 1113 ::write(mFd, ptr, bytes); 1114 mOffset += (bytes + mMoovBoxBufferOffset); 1115 1116 // All subsequent moov box content will be written 1117 // to the end of the file. 1118 mWriteMoovBoxToMemory = false; 1119 } else { 1120 memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); 1121 mMoovBoxBufferOffset += bytes; 1122 } 1123 } else { 1124 ::write(mFd, ptr, size * nmemb); 1125 mOffset += bytes; 1126 } 1127 return bytes; 1128} 1129 1130void MPEG4Writer::beginBox(const char *fourcc) { 1131 CHECK_EQ(strlen(fourcc), 4); 1132 1133 mBoxes.push_back(mWriteMoovBoxToMemory? 1134 mMoovBoxBufferOffset: mOffset); 1135 1136 writeInt32(0); 1137 writeFourcc(fourcc); 1138} 1139 1140void MPEG4Writer::endBox() { 1141 CHECK(!mBoxes.empty()); 1142 1143 off64_t offset = *--mBoxes.end(); 1144 mBoxes.erase(--mBoxes.end()); 1145 1146 if (mWriteMoovBoxToMemory) { 1147 int32_t x = htonl(mMoovBoxBufferOffset - offset); 1148 memcpy(mMoovBoxBuffer + offset, &x, 4); 1149 } else { 1150 lseek64(mFd, offset, SEEK_SET); 1151 writeInt32(mOffset - offset); 1152 mOffset -= 4; 1153 lseek64(mFd, mOffset, SEEK_SET); 1154 } 1155} 1156 1157void MPEG4Writer::writeInt8(int8_t x) { 1158 write(&x, 1, 1); 1159} 1160 1161void MPEG4Writer::writeInt16(int16_t x) { 1162 x = htons(x); 1163 write(&x, 1, 2); 1164} 1165 1166void MPEG4Writer::writeInt32(int32_t x) { 1167 x = htonl(x); 1168 write(&x, 1, 4); 1169} 1170 1171void MPEG4Writer::writeInt64(int64_t x) { 1172 x = hton64(x); 1173 write(&x, 1, 8); 1174} 1175 1176void MPEG4Writer::writeCString(const char *s) { 1177 size_t n = strlen(s); 1178 write(s, 1, n + 1); 1179} 1180 1181void MPEG4Writer::writeFourcc(const char *s) { 1182 CHECK_EQ(strlen(s), 4); 1183 write(s, 1, 4); 1184} 1185 1186 1187// Written in +/-DD.DDDD format 1188void MPEG4Writer::writeLatitude(int degreex10000) { 1189 bool isNegative = (degreex10000 < 0); 1190 char sign = isNegative? '-': '+'; 1191 1192 // Handle the whole part 1193 char str[9]; 1194 int wholePart = degreex10000 / 10000; 1195 if (wholePart == 0) { 1196 snprintf(str, 5, "%c%.2d.", sign, wholePart); 1197 } else { 1198 snprintf(str, 5, "%+.2d.", wholePart); 1199 } 1200 1201 // Handle the fractional part 1202 int fractionalPart = degreex10000 - (wholePart * 10000); 1203 if (fractionalPart < 0) { 1204 fractionalPart = -fractionalPart; 1205 } 1206 snprintf(&str[4], 5, "%.4d", fractionalPart); 1207 1208 // Do not write the null terminator 1209 write(str, 1, 8); 1210} 1211 1212// Written in +/- DDD.DDDD format 1213void MPEG4Writer::writeLongitude(int degreex10000) { 1214 bool isNegative = (degreex10000 < 0); 1215 char sign = isNegative? '-': '+'; 1216 1217 // Handle the whole part 1218 char str[10]; 1219 int wholePart = degreex10000 / 10000; 1220 if (wholePart == 0) { 1221 snprintf(str, 6, "%c%.3d.", sign, wholePart); 1222 } else { 1223 snprintf(str, 6, "%+.3d.", wholePart); 1224 } 1225 1226 // Handle the fractional part 1227 int fractionalPart = degreex10000 - (wholePart * 10000); 1228 if (fractionalPart < 0) { 1229 fractionalPart = -fractionalPart; 1230 } 1231 snprintf(&str[5], 5, "%.4d", fractionalPart); 1232 1233 // Do not write the null terminator 1234 write(str, 1, 9); 1235} 1236 1237/* 1238 * Geodata is stored according to ISO-6709 standard. 1239 * latitudex10000 is latitude in degrees times 10000, and 1240 * longitudex10000 is longitude in degrees times 10000. 1241 * The range for the latitude is in [-90, +90], and 1242 * The range for the longitude is in [-180, +180] 1243 */ 1244status_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) { 1245 // Is latitude or longitude out of range? 1246 if (latitudex10000 < -900000 || latitudex10000 > 900000 || 1247 longitudex10000 < -1800000 || longitudex10000 > 1800000) { 1248 return BAD_VALUE; 1249 } 1250 1251 mLatitudex10000 = latitudex10000; 1252 mLongitudex10000 = longitudex10000; 1253 mAreGeoTagsAvailable = true; 1254 return OK; 1255} 1256 1257void MPEG4Writer::write(const void *data, size_t size) { 1258 write(data, 1, size); 1259} 1260 1261bool MPEG4Writer::isFileStreamable() const { 1262 return mStreamableFile; 1263} 1264 1265bool MPEG4Writer::exceedsFileSizeLimit() { 1266 // No limit 1267 if (mMaxFileSizeLimitBytes == 0) { 1268 return false; 1269 } 1270 1271 int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 1272 for (List<Track *>::iterator it = mTracks.begin(); 1273 it != mTracks.end(); ++it) { 1274 nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 1275 } 1276 1277 if (!mStreamableFile) { 1278 // Add 1024 bytes as error tolerance 1279 return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes; 1280 } 1281 // Be conservative in the estimate: do not exceed 95% of 1282 // the target file limit. For small target file size limit, though, 1283 // this will not help. 1284 return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100); 1285} 1286 1287bool MPEG4Writer::exceedsFileDurationLimit() { 1288 // No limit 1289 if (mMaxFileDurationLimitUs == 0) { 1290 return false; 1291 } 1292 1293 for (List<Track *>::iterator it = mTracks.begin(); 1294 it != mTracks.end(); ++it) { 1295 if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { 1296 return true; 1297 } 1298 } 1299 return false; 1300} 1301 1302bool MPEG4Writer::reachedEOS() { 1303 bool allDone = true; 1304 for (List<Track *>::iterator it = mTracks.begin(); 1305 it != mTracks.end(); ++it) { 1306 if (!(*it)->reachedEOS()) { 1307 allDone = false; 1308 break; 1309 } 1310 } 1311 1312 return allDone; 1313} 1314 1315void MPEG4Writer::setStartTimestampUs(int64_t timeUs) { 1316 ALOGI("setStartTimestampUs: %lld", timeUs); 1317 CHECK_GE(timeUs, 0ll); 1318 Mutex::Autolock autoLock(mLock); 1319 if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) { 1320 mStartTimestampUs = timeUs; 1321 ALOGI("Earliest track starting time: %lld", mStartTimestampUs); 1322 } 1323} 1324 1325int64_t MPEG4Writer::getStartTimestampUs() { 1326 Mutex::Autolock autoLock(mLock); 1327 return mStartTimestampUs; 1328} 1329 1330size_t MPEG4Writer::numTracks() { 1331 Mutex::Autolock autolock(mLock); 1332 return mTracks.size(); 1333} 1334 1335//////////////////////////////////////////////////////////////////////////////// 1336 1337MPEG4Writer::Track::Track( 1338 MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId) 1339 : mOwner(owner), 1340 mMeta(source->getFormat()), 1341 mSource(source), 1342 mDone(false), 1343 mPaused(false), 1344 mResumed(false), 1345 mStarted(false), 1346 mTrackId(trackId), 1347 mTrackDurationUs(0), 1348 mEstimatedTrackSizeBytes(0), 1349 mSamplesHaveSameSize(true), 1350 mStszTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1351 mStcoTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1352 mCo64TableEntries(new ListTableEntries<off64_t>(1000, 1)), 1353 mStscTableEntries(new ListTableEntries<uint32_t>(1000, 3)), 1354 mStssTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1355 mSttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)), 1356 mCttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)), 1357 mCodecSpecificData(NULL), 1358 mCodecSpecificDataSize(0), 1359 mGotAllCodecSpecificData(false), 1360 mReachedEOS(false), 1361 mRotation(0) { 1362 getCodecSpecificDataFromInputFormatIfPossible(); 1363 1364 const char *mime; 1365 mMeta->findCString(kKeyMIMEType, &mime); 1366 mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 1367 mIsAudio = !strncasecmp(mime, "audio/", 6); 1368 mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 1369 !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 1370 1371 setTimeScale(); 1372} 1373 1374void MPEG4Writer::Track::updateTrackSizeEstimate() { 1375 1376 uint32_t stcoBoxCount = (mOwner->use32BitFileOffset() 1377 ? mStcoTableEntries->count() 1378 : mCo64TableEntries->count()); 1379 int64_t stcoBoxSizeBytes = stcoBoxCount * 4; 1380 int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4); 1381 1382 mEstimatedTrackSizeBytes = mMdatSizeBytes; // media data size 1383 if (!mOwner->isFileStreamable()) { 1384 // Reserved free space is not large enough to hold 1385 // all meta data and thus wasted. 1386 mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 + // stsc box size 1387 mStssTableEntries->count() * 4 + // stss box size 1388 mSttsTableEntries->count() * 8 + // stts box size 1389 mCttsTableEntries->count() * 8 + // ctts box size 1390 stcoBoxSizeBytes + // stco box size 1391 stszBoxSizeBytes; // stsz box size 1392 } 1393} 1394 1395void MPEG4Writer::Track::addOneStscTableEntry( 1396 size_t chunkId, size_t sampleId) { 1397 1398 mStscTableEntries->add(htonl(chunkId)); 1399 mStscTableEntries->add(htonl(sampleId)); 1400 mStscTableEntries->add(htonl(1)); 1401} 1402 1403void MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) { 1404 mStssTableEntries->add(htonl(sampleId)); 1405} 1406 1407void MPEG4Writer::Track::addOneSttsTableEntry( 1408 size_t sampleCount, int32_t duration) { 1409 1410 if (duration == 0) { 1411 ALOGW("0-duration samples found: %zu", sampleCount); 1412 } 1413 mSttsTableEntries->add(htonl(sampleCount)); 1414 mSttsTableEntries->add(htonl(duration)); 1415} 1416 1417void MPEG4Writer::Track::addOneCttsTableEntry( 1418 size_t sampleCount, int32_t duration) { 1419 1420 if (mIsAudio) { 1421 return; 1422 } 1423 mCttsTableEntries->add(htonl(sampleCount)); 1424 mCttsTableEntries->add(htonl(duration)); 1425} 1426 1427void MPEG4Writer::Track::addChunkOffset(off64_t offset) { 1428 if (mOwner->use32BitFileOffset()) { 1429 uint32_t value = offset; 1430 mStcoTableEntries->add(htonl(value)); 1431 } else { 1432 mCo64TableEntries->add(hton64(offset)); 1433 } 1434} 1435 1436void MPEG4Writer::Track::setTimeScale() { 1437 ALOGV("setTimeScale"); 1438 // Default time scale 1439 mTimeScale = 90000; 1440 1441 if (mIsAudio) { 1442 // Use the sampling rate as the default time scale for audio track. 1443 int32_t sampleRate; 1444 bool success = mMeta->findInt32(kKeySampleRate, &sampleRate); 1445 CHECK(success); 1446 mTimeScale = sampleRate; 1447 } 1448 1449 // If someone would like to overwrite the timescale, use user-supplied value. 1450 int32_t timeScale; 1451 if (mMeta->findInt32(kKeyTimeScale, &timeScale)) { 1452 mTimeScale = timeScale; 1453 } 1454 1455 CHECK_GT(mTimeScale, 0); 1456} 1457 1458void MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() { 1459 const char *mime; 1460 CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 1461 1462 if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 1463 uint32_t type; 1464 const void *data; 1465 size_t size; 1466 if (mMeta->findData(kKeyAVCC, &type, &data, &size)) { 1467 mCodecSpecificData = malloc(size); 1468 mCodecSpecificDataSize = size; 1469 memcpy(mCodecSpecificData, data, size); 1470 mGotAllCodecSpecificData = true; 1471 } 1472 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 1473 || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 1474 uint32_t type; 1475 const void *data; 1476 size_t size; 1477 if (mMeta->findData(kKeyESDS, &type, &data, &size)) { 1478 ESDS esds(data, size); 1479 if (esds.getCodecSpecificInfo(&data, &size) == OK) { 1480 mCodecSpecificData = malloc(size); 1481 mCodecSpecificDataSize = size; 1482 memcpy(mCodecSpecificData, data, size); 1483 mGotAllCodecSpecificData = true; 1484 } 1485 } 1486 } 1487} 1488 1489MPEG4Writer::Track::~Track() { 1490 stop(); 1491 1492 delete mStszTableEntries; 1493 delete mStcoTableEntries; 1494 delete mCo64TableEntries; 1495 delete mStscTableEntries; 1496 delete mSttsTableEntries; 1497 delete mStssTableEntries; 1498 delete mCttsTableEntries; 1499 1500 mStszTableEntries = NULL; 1501 mStcoTableEntries = NULL; 1502 mCo64TableEntries = NULL; 1503 mStscTableEntries = NULL; 1504 mSttsTableEntries = NULL; 1505 mStssTableEntries = NULL; 1506 mCttsTableEntries = NULL; 1507 1508 if (mCodecSpecificData != NULL) { 1509 free(mCodecSpecificData); 1510 mCodecSpecificData = NULL; 1511 } 1512} 1513 1514void MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) { 1515 ALOGV("initTrackingProgressStatus"); 1516 mPreviousTrackTimeUs = -1; 1517 mTrackingProgressStatus = false; 1518 mTrackEveryTimeDurationUs = 0; 1519 { 1520 int64_t timeUs; 1521 if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) { 1522 ALOGV("Receive request to track progress status for every %lld us", timeUs); 1523 mTrackEveryTimeDurationUs = timeUs; 1524 mTrackingProgressStatus = true; 1525 } 1526 } 1527} 1528 1529// static 1530void *MPEG4Writer::ThreadWrapper(void *me) { 1531 ALOGV("ThreadWrapper: %p", me); 1532 MPEG4Writer *writer = static_cast<MPEG4Writer *>(me); 1533 writer->threadFunc(); 1534 return NULL; 1535} 1536 1537void MPEG4Writer::bufferChunk(const Chunk& chunk) { 1538 ALOGV("bufferChunk: %p", chunk.mTrack); 1539 Mutex::Autolock autolock(mLock); 1540 CHECK_EQ(mDone, false); 1541 1542 for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 1543 it != mChunkInfos.end(); ++it) { 1544 1545 if (chunk.mTrack == it->mTrack) { // Found owner 1546 it->mChunks.push_back(chunk); 1547 mChunkReadyCondition.signal(); 1548 return; 1549 } 1550 } 1551 1552 CHECK(!"Received a chunk for a unknown track"); 1553} 1554 1555void MPEG4Writer::writeChunkToFile(Chunk* chunk) { 1556 ALOGV("writeChunkToFile: %lld from %s track", 1557 chunk->mTimeStampUs, chunk->mTrack->isAudio()? "audio": "video"); 1558 1559 int32_t isFirstSample = true; 1560 while (!chunk->mSamples.empty()) { 1561 List<MediaBuffer *>::iterator it = chunk->mSamples.begin(); 1562 1563 off64_t offset = chunk->mTrack->isAvc() 1564 ? addLengthPrefixedSample_l(*it) 1565 : addSample_l(*it); 1566 1567 if (isFirstSample) { 1568 chunk->mTrack->addChunkOffset(offset); 1569 isFirstSample = false; 1570 } 1571 1572 (*it)->release(); 1573 (*it) = NULL; 1574 chunk->mSamples.erase(it); 1575 } 1576 chunk->mSamples.clear(); 1577} 1578 1579void MPEG4Writer::writeAllChunks() { 1580 ALOGV("writeAllChunks"); 1581 size_t outstandingChunks = 0; 1582 Chunk chunk; 1583 while (findChunkToWrite(&chunk)) { 1584 writeChunkToFile(&chunk); 1585 ++outstandingChunks; 1586 } 1587 1588 sendSessionSummary(); 1589 1590 mChunkInfos.clear(); 1591 ALOGD("%zu chunks are written in the last batch", outstandingChunks); 1592} 1593 1594bool MPEG4Writer::findChunkToWrite(Chunk *chunk) { 1595 ALOGV("findChunkToWrite"); 1596 1597 int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL; 1598 Track *track = NULL; 1599 for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 1600 it != mChunkInfos.end(); ++it) { 1601 if (!it->mChunks.empty()) { 1602 List<Chunk>::iterator chunkIt = it->mChunks.begin(); 1603 if (chunkIt->mTimeStampUs < minTimestampUs) { 1604 minTimestampUs = chunkIt->mTimeStampUs; 1605 track = it->mTrack; 1606 } 1607 } 1608 } 1609 1610 if (track == NULL) { 1611 ALOGV("Nothing to be written after all"); 1612 return false; 1613 } 1614 1615 if (mIsFirstChunk) { 1616 mIsFirstChunk = false; 1617 } 1618 1619 for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 1620 it != mChunkInfos.end(); ++it) { 1621 if (it->mTrack == track) { 1622 *chunk = *(it->mChunks.begin()); 1623 it->mChunks.erase(it->mChunks.begin()); 1624 CHECK_EQ(chunk->mTrack, track); 1625 1626 int64_t interChunkTimeUs = 1627 chunk->mTimeStampUs - it->mPrevChunkTimestampUs; 1628 if (interChunkTimeUs > it->mPrevChunkTimestampUs) { 1629 it->mMaxInterChunkDurUs = interChunkTimeUs; 1630 } 1631 1632 return true; 1633 } 1634 } 1635 1636 return false; 1637} 1638 1639void MPEG4Writer::threadFunc() { 1640 ALOGV("threadFunc"); 1641 1642 prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0); 1643 1644 Mutex::Autolock autoLock(mLock); 1645 while (!mDone) { 1646 Chunk chunk; 1647 bool chunkFound = false; 1648 1649 while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) { 1650 mChunkReadyCondition.wait(mLock); 1651 } 1652 1653 // In real time recording mode, write without holding the lock in order 1654 // to reduce the blocking time for media track threads. 1655 // Otherwise, hold the lock until the existing chunks get written to the 1656 // file. 1657 if (chunkFound) { 1658 if (mIsRealTimeRecording) { 1659 mLock.unlock(); 1660 } 1661 writeChunkToFile(&chunk); 1662 if (mIsRealTimeRecording) { 1663 mLock.lock(); 1664 } 1665 } 1666 } 1667 1668 writeAllChunks(); 1669} 1670 1671status_t MPEG4Writer::startWriterThread() { 1672 ALOGV("startWriterThread"); 1673 1674 mDone = false; 1675 mIsFirstChunk = true; 1676 mDriftTimeUs = 0; 1677 for (List<Track *>::iterator it = mTracks.begin(); 1678 it != mTracks.end(); ++it) { 1679 ChunkInfo info; 1680 info.mTrack = *it; 1681 info.mPrevChunkTimestampUs = 0; 1682 info.mMaxInterChunkDurUs = 0; 1683 mChunkInfos.push_back(info); 1684 } 1685 1686 pthread_attr_t attr; 1687 pthread_attr_init(&attr); 1688 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 1689 pthread_create(&mThread, &attr, ThreadWrapper, this); 1690 pthread_attr_destroy(&attr); 1691 mWriterThreadStarted = true; 1692 return OK; 1693} 1694 1695 1696status_t MPEG4Writer::Track::start(MetaData *params) { 1697 if (!mDone && mPaused) { 1698 mPaused = false; 1699 mResumed = true; 1700 return OK; 1701 } 1702 1703 int64_t startTimeUs; 1704 if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) { 1705 startTimeUs = 0; 1706 } 1707 mStartTimeRealUs = startTimeUs; 1708 1709 int32_t rotationDegrees; 1710 if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) { 1711 mRotation = rotationDegrees; 1712 } 1713 1714 initTrackingProgressStatus(params); 1715 1716 sp<MetaData> meta = new MetaData; 1717 if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) { 1718 /* 1719 * This extra delay of accepting incoming audio/video signals 1720 * helps to align a/v start time at the beginning of a recording 1721 * session, and it also helps eliminate the "recording" sound for 1722 * camcorder applications. 1723 * 1724 * If client does not set the start time offset, we fall back to 1725 * use the default initial delay value. 1726 */ 1727 int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 1728 if (startTimeOffsetUs < 0) { // Start time offset was not set 1729 startTimeOffsetUs = kInitialDelayTimeUs; 1730 } 1731 startTimeUs += startTimeOffsetUs; 1732 ALOGI("Start time offset: %lld us", startTimeOffsetUs); 1733 } 1734 1735 meta->setInt64(kKeyTime, startTimeUs); 1736 1737 status_t err = mSource->start(meta.get()); 1738 if (err != OK) { 1739 mDone = mReachedEOS = true; 1740 return err; 1741 } 1742 1743 pthread_attr_t attr; 1744 pthread_attr_init(&attr); 1745 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 1746 1747 mDone = false; 1748 mStarted = true; 1749 mTrackDurationUs = 0; 1750 mReachedEOS = false; 1751 mEstimatedTrackSizeBytes = 0; 1752 mMdatSizeBytes = 0; 1753 mMaxChunkDurationUs = 0; 1754 1755 pthread_create(&mThread, &attr, ThreadWrapper, this); 1756 pthread_attr_destroy(&attr); 1757 1758 return OK; 1759} 1760 1761status_t MPEG4Writer::Track::pause() { 1762 mPaused = true; 1763 return OK; 1764} 1765 1766status_t MPEG4Writer::Track::stop() { 1767 ALOGD("%s track stopping", mIsAudio? "Audio": "Video"); 1768 if (!mStarted) { 1769 ALOGE("Stop() called but track is not started"); 1770 return ERROR_END_OF_STREAM; 1771 } 1772 1773 if (mDone) { 1774 return OK; 1775 } 1776 mDone = true; 1777 1778 ALOGD("%s track source stopping", mIsAudio? "Audio": "Video"); 1779 mSource->stop(); 1780 ALOGD("%s track source stopped", mIsAudio? "Audio": "Video"); 1781 1782 void *dummy; 1783 pthread_join(mThread, &dummy); 1784 status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); 1785 1786 ALOGD("%s track stopped", mIsAudio? "Audio": "Video"); 1787 return err; 1788} 1789 1790bool MPEG4Writer::Track::reachedEOS() { 1791 return mReachedEOS; 1792} 1793 1794// static 1795void *MPEG4Writer::Track::ThreadWrapper(void *me) { 1796 Track *track = static_cast<Track *>(me); 1797 1798 status_t err = track->threadEntry(); 1799 return (void *)(uintptr_t)err; 1800} 1801 1802static void getNalUnitType(uint8_t byte, uint8_t* type) { 1803 ALOGV("getNalUnitType: %d", byte); 1804 1805 // nal_unit_type: 5-bit unsigned integer 1806 *type = (byte & 0x1F); 1807} 1808 1809static const uint8_t *findNextStartCode( 1810 const uint8_t *data, size_t length) { 1811 1812 ALOGV("findNextStartCode: %p %d", data, length); 1813 1814 size_t bytesLeft = length; 1815 while (bytesLeft > 4 && 1816 memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) { 1817 --bytesLeft; 1818 } 1819 if (bytesLeft <= 4) { 1820 bytesLeft = 0; // Last parameter set 1821 } 1822 return &data[length - bytesLeft]; 1823} 1824 1825const uint8_t *MPEG4Writer::Track::parseParamSet( 1826 const uint8_t *data, size_t length, int type, size_t *paramSetLen) { 1827 1828 ALOGV("parseParamSet"); 1829 CHECK(type == kNalUnitTypeSeqParamSet || 1830 type == kNalUnitTypePicParamSet); 1831 1832 const uint8_t *nextStartCode = findNextStartCode(data, length); 1833 *paramSetLen = nextStartCode - data; 1834 if (*paramSetLen == 0) { 1835 ALOGE("Param set is malformed, since its length is 0"); 1836 return NULL; 1837 } 1838 1839 AVCParamSet paramSet(*paramSetLen, data); 1840 if (type == kNalUnitTypeSeqParamSet) { 1841 if (*paramSetLen < 4) { 1842 ALOGE("Seq parameter set malformed"); 1843 return NULL; 1844 } 1845 if (mSeqParamSets.empty()) { 1846 mProfileIdc = data[1]; 1847 mProfileCompatible = data[2]; 1848 mLevelIdc = data[3]; 1849 } else { 1850 if (mProfileIdc != data[1] || 1851 mProfileCompatible != data[2] || 1852 mLevelIdc != data[3]) { 1853 ALOGE("Inconsistent profile/level found in seq parameter sets"); 1854 return NULL; 1855 } 1856 } 1857 mSeqParamSets.push_back(paramSet); 1858 } else { 1859 mPicParamSets.push_back(paramSet); 1860 } 1861 return nextStartCode; 1862} 1863 1864status_t MPEG4Writer::Track::copyAVCCodecSpecificData( 1865 const uint8_t *data, size_t size) { 1866 ALOGV("copyAVCCodecSpecificData"); 1867 1868 // 2 bytes for each of the parameter set length field 1869 // plus the 7 bytes for the header 1870 if (size < 4 + 7) { 1871 ALOGE("Codec specific data length too short: %zu", size); 1872 return ERROR_MALFORMED; 1873 } 1874 1875 mCodecSpecificDataSize = size; 1876 mCodecSpecificData = malloc(size); 1877 memcpy(mCodecSpecificData, data, size); 1878 return OK; 1879} 1880 1881status_t MPEG4Writer::Track::parseAVCCodecSpecificData( 1882 const uint8_t *data, size_t size) { 1883 1884 ALOGV("parseAVCCodecSpecificData"); 1885 // Data starts with a start code. 1886 // SPS and PPS are separated with start codes. 1887 // Also, SPS must come before PPS 1888 uint8_t type = kNalUnitTypeSeqParamSet; 1889 bool gotSps = false; 1890 bool gotPps = false; 1891 const uint8_t *tmp = data; 1892 const uint8_t *nextStartCode = data; 1893 size_t bytesLeft = size; 1894 size_t paramSetLen = 0; 1895 mCodecSpecificDataSize = 0; 1896 while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 1897 getNalUnitType(*(tmp + 4), &type); 1898 if (type == kNalUnitTypeSeqParamSet) { 1899 if (gotPps) { 1900 ALOGE("SPS must come before PPS"); 1901 return ERROR_MALFORMED; 1902 } 1903 if (!gotSps) { 1904 gotSps = true; 1905 } 1906 nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 1907 } else if (type == kNalUnitTypePicParamSet) { 1908 if (!gotSps) { 1909 ALOGE("SPS must come before PPS"); 1910 return ERROR_MALFORMED; 1911 } 1912 if (!gotPps) { 1913 gotPps = true; 1914 } 1915 nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 1916 } else { 1917 ALOGE("Only SPS and PPS Nal units are expected"); 1918 return ERROR_MALFORMED; 1919 } 1920 1921 if (nextStartCode == NULL) { 1922 return ERROR_MALFORMED; 1923 } 1924 1925 // Move on to find the next parameter set 1926 bytesLeft -= nextStartCode - tmp; 1927 tmp = nextStartCode; 1928 mCodecSpecificDataSize += (2 + paramSetLen); 1929 } 1930 1931 { 1932 // Check on the number of seq parameter sets 1933 size_t nSeqParamSets = mSeqParamSets.size(); 1934 if (nSeqParamSets == 0) { 1935 ALOGE("Cound not find sequence parameter set"); 1936 return ERROR_MALFORMED; 1937 } 1938 1939 if (nSeqParamSets > 0x1F) { 1940 ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets); 1941 return ERROR_MALFORMED; 1942 } 1943 } 1944 1945 { 1946 // Check on the number of pic parameter sets 1947 size_t nPicParamSets = mPicParamSets.size(); 1948 if (nPicParamSets == 0) { 1949 ALOGE("Cound not find picture parameter set"); 1950 return ERROR_MALFORMED; 1951 } 1952 if (nPicParamSets > 0xFF) { 1953 ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets); 1954 return ERROR_MALFORMED; 1955 } 1956 } 1957// FIXME: 1958// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above 1959// and remove #if 0 1960#if 0 1961 { 1962 // Check on the profiles 1963 // These profiles requires additional parameter set extensions 1964 if (mProfileIdc == 100 || mProfileIdc == 110 || 1965 mProfileIdc == 122 || mProfileIdc == 144) { 1966 ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc); 1967 return BAD_VALUE; 1968 } 1969 } 1970#endif 1971 return OK; 1972} 1973 1974status_t MPEG4Writer::Track::makeAVCCodecSpecificData( 1975 const uint8_t *data, size_t size) { 1976 1977 if (mCodecSpecificData != NULL) { 1978 ALOGE("Already have codec specific data"); 1979 return ERROR_MALFORMED; 1980 } 1981 1982 if (size < 4) { 1983 ALOGE("Codec specific data length too short: %zu", size); 1984 return ERROR_MALFORMED; 1985 } 1986 1987 // Data is in the form of AVCCodecSpecificData 1988 if (memcmp("\x00\x00\x00\x01", data, 4)) { 1989 return copyAVCCodecSpecificData(data, size); 1990 } 1991 1992 if (parseAVCCodecSpecificData(data, size) != OK) { 1993 return ERROR_MALFORMED; 1994 } 1995 1996 // ISO 14496-15: AVC file format 1997 mCodecSpecificDataSize += 7; // 7 more bytes in the header 1998 mCodecSpecificData = malloc(mCodecSpecificDataSize); 1999 uint8_t *header = (uint8_t *)mCodecSpecificData; 2000 header[0] = 1; // version 2001 header[1] = mProfileIdc; // profile indication 2002 header[2] = mProfileCompatible; // profile compatibility 2003 header[3] = mLevelIdc; 2004 2005 // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne 2006 if (mOwner->useNalLengthFour()) { 2007 header[4] = 0xfc | 3; // length size == 4 bytes 2008 } else { 2009 header[4] = 0xfc | 1; // length size == 2 bytes 2010 } 2011 2012 // 3-bit '111' followed by 5-bit numSequenceParameterSets 2013 int nSequenceParamSets = mSeqParamSets.size(); 2014 header[5] = 0xe0 | nSequenceParamSets; 2015 header += 6; 2016 for (List<AVCParamSet>::iterator it = mSeqParamSets.begin(); 2017 it != mSeqParamSets.end(); ++it) { 2018 // 16-bit sequence parameter set length 2019 uint16_t seqParamSetLength = it->mLength; 2020 header[0] = seqParamSetLength >> 8; 2021 header[1] = seqParamSetLength & 0xff; 2022 2023 // SPS NAL unit (sequence parameter length bytes) 2024 memcpy(&header[2], it->mData, seqParamSetLength); 2025 header += (2 + seqParamSetLength); 2026 } 2027 2028 // 8-bit nPictureParameterSets 2029 int nPictureParamSets = mPicParamSets.size(); 2030 header[0] = nPictureParamSets; 2031 header += 1; 2032 for (List<AVCParamSet>::iterator it = mPicParamSets.begin(); 2033 it != mPicParamSets.end(); ++it) { 2034 // 16-bit picture parameter set length 2035 uint16_t picParamSetLength = it->mLength; 2036 header[0] = picParamSetLength >> 8; 2037 header[1] = picParamSetLength & 0xff; 2038 2039 // PPS Nal unit (picture parameter set length bytes) 2040 memcpy(&header[2], it->mData, picParamSetLength); 2041 header += (2 + picParamSetLength); 2042 } 2043 2044 return OK; 2045} 2046 2047/* 2048 * Updates the drift time from the audio track so that 2049 * the video track can get the updated drift time information 2050 * from the file writer. The fluctuation of the drift time of the audio 2051 * encoding path is smoothed out with a simple filter by giving a larger 2052 * weight to more recently drift time. The filter coefficients, 0.5 and 0.5, 2053 * are heuristically determined. 2054 */ 2055void MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) { 2056 int64_t driftTimeUs = 0; 2057 if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) { 2058 int64_t prevDriftTimeUs = mOwner->getDriftTimeUs(); 2059 int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1; 2060 mOwner->setDriftTimeUs(timeUs); 2061 } 2062} 2063 2064status_t MPEG4Writer::Track::threadEntry() { 2065 int32_t count = 0; 2066 const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 2067 const bool hasMultipleTracks = (mOwner->numTracks() > 1); 2068 int64_t chunkTimestampUs = 0; 2069 int32_t nChunks = 0; 2070 int32_t nZeroLengthFrames = 0; 2071 int64_t lastTimestampUs = 0; // Previous sample time stamp 2072 int64_t lastDurationUs = 0; // Between the previous two samples 2073 int64_t currDurationTicks = 0; // Timescale based ticks 2074 int64_t lastDurationTicks = 0; // Timescale based ticks 2075 int32_t sampleCount = 1; // Sample count in the current stts table entry 2076 uint32_t previousSampleSize = 0; // Size of the previous sample 2077 int64_t previousPausedDurationUs = 0; 2078 int64_t timestampUs = 0; 2079 int64_t cttsOffsetTimeUs = 0; 2080 int64_t currCttsOffsetTimeTicks = 0; // Timescale based ticks 2081 int64_t lastCttsOffsetTimeTicks = -1; // Timescale based ticks 2082 int32_t cttsSampleCount = 0; // Sample count in the current ctts table entry 2083 uint32_t lastSamplesPerChunk = 0; 2084 2085 if (mIsAudio) { 2086 prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0); 2087 } else { 2088 prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0); 2089 } 2090 2091 if (mOwner->isRealTimeRecording()) { 2092 androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); 2093 } 2094 2095 sp<MetaData> meta_data; 2096 2097 status_t err = OK; 2098 MediaBuffer *buffer; 2099 while (!mDone && (err = mSource->read(&buffer)) == OK) { 2100 if (buffer->range_length() == 0) { 2101 buffer->release(); 2102 buffer = NULL; 2103 ++nZeroLengthFrames; 2104 continue; 2105 } 2106 2107 // If the codec specific data has not been received yet, delay pause. 2108 // After the codec specific data is received, discard what we received 2109 // when the track is to be paused. 2110 if (mPaused && !mResumed) { 2111 buffer->release(); 2112 buffer = NULL; 2113 continue; 2114 } 2115 2116 ++count; 2117 2118 int32_t isCodecConfig; 2119 if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 2120 && isCodecConfig) { 2121 CHECK(!mGotAllCodecSpecificData); 2122 2123 if (mIsAvc) { 2124 status_t err = makeAVCCodecSpecificData( 2125 (const uint8_t *)buffer->data() 2126 + buffer->range_offset(), 2127 buffer->range_length()); 2128 CHECK_EQ((status_t)OK, err); 2129 } else if (mIsMPEG4) { 2130 mCodecSpecificDataSize = buffer->range_length(); 2131 mCodecSpecificData = malloc(mCodecSpecificDataSize); 2132 memcpy(mCodecSpecificData, 2133 (const uint8_t *)buffer->data() 2134 + buffer->range_offset(), 2135 buffer->range_length()); 2136 } 2137 2138 buffer->release(); 2139 buffer = NULL; 2140 2141 mGotAllCodecSpecificData = true; 2142 continue; 2143 } 2144 2145 // Make a deep copy of the MediaBuffer and Metadata and release 2146 // the original as soon as we can 2147 MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 2148 memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 2149 buffer->range_length()); 2150 copy->set_range(0, buffer->range_length()); 2151 meta_data = new MetaData(*buffer->meta_data().get()); 2152 buffer->release(); 2153 buffer = NULL; 2154 2155 if (mIsAvc) StripStartcode(copy); 2156 2157 size_t sampleSize = copy->range_length(); 2158 if (mIsAvc) { 2159 if (mOwner->useNalLengthFour()) { 2160 sampleSize += 4; 2161 } else { 2162 sampleSize += 2; 2163 } 2164 } 2165 2166 // Max file size or duration handling 2167 mMdatSizeBytes += sampleSize; 2168 updateTrackSizeEstimate(); 2169 2170 if (mOwner->exceedsFileSizeLimit()) { 2171 mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 2172 break; 2173 } 2174 if (mOwner->exceedsFileDurationLimit()) { 2175 mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 2176 break; 2177 } 2178 2179 2180 int32_t isSync = false; 2181 meta_data->findInt32(kKeyIsSyncFrame, &isSync); 2182 CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 2183 2184//////////////////////////////////////////////////////////////////////////////// 2185 if (mStszTableEntries->count() == 0) { 2186 mFirstSampleTimeRealUs = systemTime() / 1000; 2187 mStartTimestampUs = timestampUs; 2188 mOwner->setStartTimestampUs(mStartTimestampUs); 2189 previousPausedDurationUs = mStartTimestampUs; 2190 } 2191 2192 if (mResumed) { 2193 int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs; 2194 CHECK_GE(durExcludingEarlierPausesUs, 0ll); 2195 int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs; 2196 CHECK_GE(pausedDurationUs, lastDurationUs); 2197 previousPausedDurationUs += pausedDurationUs - lastDurationUs; 2198 mResumed = false; 2199 } 2200 2201 timestampUs -= previousPausedDurationUs; 2202 CHECK_GE(timestampUs, 0ll); 2203 if (!mIsAudio) { 2204 /* 2205 * Composition time: timestampUs 2206 * Decoding time: decodingTimeUs 2207 * Composition time offset = composition time - decoding time 2208 */ 2209 int64_t decodingTimeUs; 2210 CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs)); 2211 decodingTimeUs -= previousPausedDurationUs; 2212 cttsOffsetTimeUs = 2213 timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs; 2214 CHECK_GE(cttsOffsetTimeUs, 0ll); 2215 timestampUs = decodingTimeUs; 2216 ALOGV("decoding time: %lld and ctts offset time: %lld", 2217 timestampUs, cttsOffsetTimeUs); 2218 2219 // Update ctts box table if necessary 2220 currCttsOffsetTimeTicks = 2221 (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL; 2222 CHECK_LE(currCttsOffsetTimeTicks, 0x0FFFFFFFFLL); 2223 if (mStszTableEntries->count() == 0) { 2224 // Force the first ctts table entry to have one single entry 2225 // so that we can do adjustment for the initial track start 2226 // time offset easily in writeCttsBox(). 2227 lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 2228 addOneCttsTableEntry(1, currCttsOffsetTimeTicks); 2229 cttsSampleCount = 0; // No sample in ctts box is pending 2230 } else { 2231 if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) { 2232 addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 2233 lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 2234 cttsSampleCount = 1; // One sample in ctts box is pending 2235 } else { 2236 ++cttsSampleCount; 2237 } 2238 } 2239 2240 // Update ctts time offset range 2241 if (mStszTableEntries->count() == 0) { 2242 mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2243 mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2244 } else { 2245 if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) { 2246 mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2247 } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) { 2248 mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2249 } 2250 } 2251 2252 } 2253 2254 if (mOwner->isRealTimeRecording()) { 2255 if (mIsAudio) { 2256 updateDriftTime(meta_data); 2257 } 2258 } 2259 2260 CHECK_GE(timestampUs, 0ll); 2261 ALOGV("%s media time stamp: %lld and previous paused duration %lld", 2262 mIsAudio? "Audio": "Video", timestampUs, previousPausedDurationUs); 2263 if (timestampUs > mTrackDurationUs) { 2264 mTrackDurationUs = timestampUs; 2265 } 2266 2267 // We need to use the time scale based ticks, rather than the 2268 // timestamp itself to determine whether we have to use a new 2269 // stts entry, since we may have rounding errors. 2270 // The calculation is intended to reduce the accumulated 2271 // rounding errors. 2272 currDurationTicks = 2273 ((timestampUs * mTimeScale + 500000LL) / 1000000LL - 2274 (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL); 2275 if (currDurationTicks < 0ll) { 2276 ALOGE("timestampUs %lld < lastTimestampUs %lld for %s track", 2277 timestampUs, lastTimestampUs, mIsAudio? "Audio": "Video"); 2278 return UNKNOWN_ERROR; 2279 } 2280 2281 mStszTableEntries->add(htonl(sampleSize)); 2282 if (mStszTableEntries->count() > 2) { 2283 2284 // Force the first sample to have its own stts entry so that 2285 // we can adjust its value later to maintain the A/V sync. 2286 if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) { 2287 addOneSttsTableEntry(sampleCount, lastDurationTicks); 2288 sampleCount = 1; 2289 } else { 2290 ++sampleCount; 2291 } 2292 2293 } 2294 if (mSamplesHaveSameSize) { 2295 if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) { 2296 mSamplesHaveSameSize = false; 2297 } 2298 previousSampleSize = sampleSize; 2299 } 2300 ALOGV("%s timestampUs/lastTimestampUs: %lld/%lld", 2301 mIsAudio? "Audio": "Video", timestampUs, lastTimestampUs); 2302 lastDurationUs = timestampUs - lastTimestampUs; 2303 lastDurationTicks = currDurationTicks; 2304 lastTimestampUs = timestampUs; 2305 2306 if (isSync != 0) { 2307 addOneStssTableEntry(mStszTableEntries->count()); 2308 } 2309 2310 if (mTrackingProgressStatus) { 2311 if (mPreviousTrackTimeUs <= 0) { 2312 mPreviousTrackTimeUs = mStartTimestampUs; 2313 } 2314 trackProgressStatus(timestampUs); 2315 } 2316 if (!hasMultipleTracks) { 2317 off64_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy) 2318 : mOwner->addSample_l(copy); 2319 2320 uint32_t count = (mOwner->use32BitFileOffset() 2321 ? mStcoTableEntries->count() 2322 : mCo64TableEntries->count()); 2323 2324 if (count == 0) { 2325 addChunkOffset(offset); 2326 } 2327 copy->release(); 2328 copy = NULL; 2329 continue; 2330 } 2331 2332 mChunkSamples.push_back(copy); 2333 if (interleaveDurationUs == 0) { 2334 addOneStscTableEntry(++nChunks, 1); 2335 bufferChunk(timestampUs); 2336 } else { 2337 if (chunkTimestampUs == 0) { 2338 chunkTimestampUs = timestampUs; 2339 } else { 2340 int64_t chunkDurationUs = timestampUs - chunkTimestampUs; 2341 if (chunkDurationUs > interleaveDurationUs) { 2342 if (chunkDurationUs > mMaxChunkDurationUs) { 2343 mMaxChunkDurationUs = chunkDurationUs; 2344 } 2345 ++nChunks; 2346 if (nChunks == 1 || // First chunk 2347 lastSamplesPerChunk != mChunkSamples.size()) { 2348 lastSamplesPerChunk = mChunkSamples.size(); 2349 addOneStscTableEntry(nChunks, lastSamplesPerChunk); 2350 } 2351 bufferChunk(timestampUs); 2352 chunkTimestampUs = timestampUs; 2353 } 2354 } 2355 } 2356 2357 } 2358 2359 if (isTrackMalFormed()) { 2360 err = ERROR_MALFORMED; 2361 } 2362 2363 mOwner->trackProgressStatus(mTrackId, -1, err); 2364 2365 // Last chunk 2366 if (!hasMultipleTracks) { 2367 addOneStscTableEntry(1, mStszTableEntries->count()); 2368 } else if (!mChunkSamples.empty()) { 2369 addOneStscTableEntry(++nChunks, mChunkSamples.size()); 2370 bufferChunk(timestampUs); 2371 } 2372 2373 // We don't really know how long the last frame lasts, since 2374 // there is no frame time after it, just repeat the previous 2375 // frame's duration. 2376 if (mStszTableEntries->count() == 1) { 2377 lastDurationUs = 0; // A single sample's duration 2378 lastDurationTicks = 0; 2379 } else { 2380 ++sampleCount; // Count for the last sample 2381 } 2382 2383 if (mStszTableEntries->count() <= 2) { 2384 addOneSttsTableEntry(1, lastDurationTicks); 2385 if (sampleCount - 1 > 0) { 2386 addOneSttsTableEntry(sampleCount - 1, lastDurationTicks); 2387 } 2388 } else { 2389 addOneSttsTableEntry(sampleCount, lastDurationTicks); 2390 } 2391 2392 // The last ctts box may not have been written yet, and this 2393 // is to make sure that we write out the last ctts box. 2394 if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) { 2395 if (cttsSampleCount > 0) { 2396 addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 2397 } 2398 } 2399 2400 mTrackDurationUs += lastDurationUs; 2401 mReachedEOS = true; 2402 2403 sendTrackSummary(hasMultipleTracks); 2404 2405 ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s", 2406 count, nZeroLengthFrames, mStszTableEntries->count(), mIsAudio? "audio": "video"); 2407 if (mIsAudio) { 2408 ALOGI("Audio track drift time: %lld us", mOwner->getDriftTimeUs()); 2409 } 2410 2411 if (err == ERROR_END_OF_STREAM) { 2412 return OK; 2413 } 2414 return err; 2415} 2416 2417bool MPEG4Writer::Track::isTrackMalFormed() const { 2418 if (mStszTableEntries->count() == 0) { // no samples written 2419 ALOGE("The number of recorded samples is 0"); 2420 return true; 2421 } 2422 2423 if (!mIsAudio && mStssTableEntries->count() == 0) { // no sync frames for video 2424 ALOGE("There are no sync frames for video track"); 2425 return true; 2426 } 2427 2428 if (OK != checkCodecSpecificData()) { // no codec specific data 2429 return true; 2430 } 2431 2432 return false; 2433} 2434 2435void MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) { 2436 2437 // Send track summary only if test mode is enabled. 2438 if (!isTestModeEnabled()) { 2439 return; 2440 } 2441 2442 int trackNum = (mTrackId << 28); 2443 2444 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2445 trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE, 2446 mIsAudio? 0: 1); 2447 2448 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2449 trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS, 2450 mTrackDurationUs / 1000); 2451 2452 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2453 trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES, 2454 mStszTableEntries->count()); 2455 2456 { 2457 // The system delay time excluding the requested initial delay that 2458 // is used to eliminate the recording sound. 2459 int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 2460 if (startTimeOffsetUs < 0) { // Start time offset was not set 2461 startTimeOffsetUs = kInitialDelayTimeUs; 2462 } 2463 int64_t initialDelayUs = 2464 mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs; 2465 2466 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2467 trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS, 2468 (initialDelayUs) / 1000); 2469 } 2470 2471 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2472 trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES, 2473 mMdatSizeBytes / 1024); 2474 2475 if (hasMultipleTracks) { 2476 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2477 trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS, 2478 mMaxChunkDurationUs / 1000); 2479 2480 int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 2481 if (mStartTimestampUs != moovStartTimeUs) { 2482 int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 2483 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2484 trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS, 2485 startTimeOffsetUs / 1000); 2486 } 2487 } 2488} 2489 2490void MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) { 2491 ALOGV("trackProgressStatus: %lld us", timeUs); 2492 2493 if (mTrackEveryTimeDurationUs > 0 && 2494 timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 2495 ALOGV("Fire time tracking progress status at %lld us", timeUs); 2496 mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err); 2497 mPreviousTrackTimeUs = timeUs; 2498 } 2499} 2500 2501void MPEG4Writer::trackProgressStatus( 2502 size_t trackId, int64_t timeUs, status_t err) { 2503 Mutex::Autolock lock(mLock); 2504 int32_t trackNum = (trackId << 28); 2505 2506 // Error notification 2507 // Do not consider ERROR_END_OF_STREAM an error 2508 if (err != OK && err != ERROR_END_OF_STREAM) { 2509 notify(MEDIA_RECORDER_TRACK_EVENT_ERROR, 2510 trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL, 2511 err); 2512 return; 2513 } 2514 2515 if (timeUs == -1) { 2516 // Send completion notification 2517 notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2518 trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, 2519 err); 2520 } else { 2521 // Send progress status 2522 notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2523 trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME, 2524 timeUs / 1000); 2525 } 2526} 2527 2528void MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) { 2529 ALOGV("setDriftTimeUs: %lld us", driftTimeUs); 2530 Mutex::Autolock autolock(mLock); 2531 mDriftTimeUs = driftTimeUs; 2532} 2533 2534int64_t MPEG4Writer::getDriftTimeUs() { 2535 ALOGV("getDriftTimeUs: %lld us", mDriftTimeUs); 2536 Mutex::Autolock autolock(mLock); 2537 return mDriftTimeUs; 2538} 2539 2540bool MPEG4Writer::isRealTimeRecording() const { 2541 return mIsRealTimeRecording; 2542} 2543 2544bool MPEG4Writer::useNalLengthFour() { 2545 return mUse4ByteNalLength; 2546} 2547 2548void MPEG4Writer::Track::bufferChunk(int64_t timestampUs) { 2549 ALOGV("bufferChunk"); 2550 2551 Chunk chunk(this, timestampUs, mChunkSamples); 2552 mOwner->bufferChunk(chunk); 2553 mChunkSamples.clear(); 2554} 2555 2556int64_t MPEG4Writer::Track::getDurationUs() const { 2557 return mTrackDurationUs; 2558} 2559 2560int64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 2561 return mEstimatedTrackSizeBytes; 2562} 2563 2564status_t MPEG4Writer::Track::checkCodecSpecificData() const { 2565 const char *mime; 2566 CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 2567 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) || 2568 !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) || 2569 !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2570 if (!mCodecSpecificData || 2571 mCodecSpecificDataSize <= 0) { 2572 ALOGE("Missing codec specific data"); 2573 return ERROR_MALFORMED; 2574 } 2575 } else { 2576 if (mCodecSpecificData || 2577 mCodecSpecificDataSize > 0) { 2578 ALOGE("Unexepected codec specific data found"); 2579 return ERROR_MALFORMED; 2580 } 2581 } 2582 return OK; 2583} 2584 2585void MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) { 2586 2587 ALOGV("%s track time scale: %d", 2588 mIsAudio? "Audio": "Video", mTimeScale); 2589 2590 uint32_t now = getMpeg4Time(); 2591 mOwner->beginBox("trak"); 2592 writeTkhdBox(now); 2593 mOwner->beginBox("mdia"); 2594 writeMdhdBox(now); 2595 writeHdlrBox(); 2596 mOwner->beginBox("minf"); 2597 if (mIsAudio) { 2598 writeSmhdBox(); 2599 } else { 2600 writeVmhdBox(); 2601 } 2602 writeDinfBox(); 2603 writeStblBox(use32BitOffset); 2604 mOwner->endBox(); // minf 2605 mOwner->endBox(); // mdia 2606 mOwner->endBox(); // trak 2607} 2608 2609void MPEG4Writer::Track::writeStblBox(bool use32BitOffset) { 2610 mOwner->beginBox("stbl"); 2611 mOwner->beginBox("stsd"); 2612 mOwner->writeInt32(0); // version=0, flags=0 2613 mOwner->writeInt32(1); // entry count 2614 if (mIsAudio) { 2615 writeAudioFourCCBox(); 2616 } else { 2617 writeVideoFourCCBox(); 2618 } 2619 mOwner->endBox(); // stsd 2620 writeSttsBox(); 2621 writeCttsBox(); 2622 if (!mIsAudio) { 2623 writeStssBox(); 2624 } 2625 writeStszBox(); 2626 writeStscBox(); 2627 writeStcoBox(use32BitOffset); 2628 mOwner->endBox(); // stbl 2629} 2630 2631void MPEG4Writer::Track::writeVideoFourCCBox() { 2632 const char *mime; 2633 bool success = mMeta->findCString(kKeyMIMEType, &mime); 2634 CHECK(success); 2635 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2636 mOwner->beginBox("mp4v"); 2637 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2638 mOwner->beginBox("s263"); 2639 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2640 mOwner->beginBox("avc1"); 2641 } else { 2642 ALOGE("Unknown mime type '%s'.", mime); 2643 CHECK(!"should not be here, unknown mime type."); 2644 } 2645 2646 mOwner->writeInt32(0); // reserved 2647 mOwner->writeInt16(0); // reserved 2648 mOwner->writeInt16(1); // data ref index 2649 mOwner->writeInt16(0); // predefined 2650 mOwner->writeInt16(0); // reserved 2651 mOwner->writeInt32(0); // predefined 2652 mOwner->writeInt32(0); // predefined 2653 mOwner->writeInt32(0); // predefined 2654 2655 int32_t width, height; 2656 success = mMeta->findInt32(kKeyWidth, &width); 2657 success = success && mMeta->findInt32(kKeyHeight, &height); 2658 CHECK(success); 2659 2660 mOwner->writeInt16(width); 2661 mOwner->writeInt16(height); 2662 mOwner->writeInt32(0x480000); // horiz resolution 2663 mOwner->writeInt32(0x480000); // vert resolution 2664 mOwner->writeInt32(0); // reserved 2665 mOwner->writeInt16(1); // frame count 2666 mOwner->writeInt8(0); // compressor string length 2667 mOwner->write(" ", 31); 2668 mOwner->writeInt16(0x18); // depth 2669 mOwner->writeInt16(-1); // predefined 2670 2671 CHECK_LT(23 + mCodecSpecificDataSize, 128); 2672 2673 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2674 writeMp4vEsdsBox(); 2675 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2676 writeD263Box(); 2677 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2678 writeAvccBox(); 2679 } 2680 2681 writePaspBox(); 2682 mOwner->endBox(); // mp4v, s263 or avc1 2683} 2684 2685void MPEG4Writer::Track::writeAudioFourCCBox() { 2686 const char *mime; 2687 bool success = mMeta->findCString(kKeyMIMEType, &mime); 2688 CHECK(success); 2689 const char *fourcc = NULL; 2690 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 2691 fourcc = "samr"; 2692 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 2693 fourcc = "sawb"; 2694 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2695 fourcc = "mp4a"; 2696 } else { 2697 ALOGE("Unknown mime type '%s'.", mime); 2698 CHECK(!"should not be here, unknown mime type."); 2699 } 2700 2701 mOwner->beginBox(fourcc); // audio format 2702 mOwner->writeInt32(0); // reserved 2703 mOwner->writeInt16(0); // reserved 2704 mOwner->writeInt16(0x1); // data ref index 2705 mOwner->writeInt32(0); // reserved 2706 mOwner->writeInt32(0); // reserved 2707 int32_t nChannels; 2708 CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 2709 mOwner->writeInt16(nChannels); // channel count 2710 mOwner->writeInt16(16); // sample size 2711 mOwner->writeInt16(0); // predefined 2712 mOwner->writeInt16(0); // reserved 2713 2714 int32_t samplerate; 2715 success = mMeta->findInt32(kKeySampleRate, &samplerate); 2716 CHECK(success); 2717 mOwner->writeInt32(samplerate << 16); 2718 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2719 writeMp4aEsdsBox(); 2720 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) || 2721 !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 2722 writeDamrBox(); 2723 } 2724 mOwner->endBox(); 2725} 2726 2727void MPEG4Writer::Track::writeMp4aEsdsBox() { 2728 mOwner->beginBox("esds"); 2729 CHECK(mCodecSpecificData); 2730 CHECK_GT(mCodecSpecificDataSize, 0); 2731 2732 // Make sure all sizes encode to a single byte. 2733 CHECK_LT(mCodecSpecificDataSize + 23, 128); 2734 2735 mOwner->writeInt32(0); // version=0, flags=0 2736 mOwner->writeInt8(0x03); // ES_DescrTag 2737 mOwner->writeInt8(23 + mCodecSpecificDataSize); 2738 mOwner->writeInt16(0x0000);// ES_ID 2739 mOwner->writeInt8(0x00); 2740 2741 mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2742 mOwner->writeInt8(15 + mCodecSpecificDataSize); 2743 mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 2744 mOwner->writeInt8(0x15); // streamType AudioStream 2745 2746 mOwner->writeInt16(0x03); // XXX 2747 mOwner->writeInt8(0x00); // buffer size 24-bit 2748 mOwner->writeInt32(96000); // max bit rate 2749 mOwner->writeInt32(96000); // avg bit rate 2750 2751 mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2752 mOwner->writeInt8(mCodecSpecificDataSize); 2753 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2754 2755 static const uint8_t kData2[] = { 2756 0x06, // SLConfigDescriptorTag 2757 0x01, 2758 0x02 2759 }; 2760 mOwner->write(kData2, sizeof(kData2)); 2761 2762 mOwner->endBox(); // esds 2763} 2764 2765void MPEG4Writer::Track::writeMp4vEsdsBox() { 2766 CHECK(mCodecSpecificData); 2767 CHECK_GT(mCodecSpecificDataSize, 0); 2768 mOwner->beginBox("esds"); 2769 2770 mOwner->writeInt32(0); // version=0, flags=0 2771 2772 mOwner->writeInt8(0x03); // ES_DescrTag 2773 mOwner->writeInt8(23 + mCodecSpecificDataSize); 2774 mOwner->writeInt16(0x0000); // ES_ID 2775 mOwner->writeInt8(0x1f); 2776 2777 mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2778 mOwner->writeInt8(15 + mCodecSpecificDataSize); 2779 mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 2780 mOwner->writeInt8(0x11); // streamType VisualStream 2781 2782 static const uint8_t kData[] = { 2783 0x01, 0x77, 0x00, 2784 0x00, 0x03, 0xe8, 0x00, 2785 0x00, 0x03, 0xe8, 0x00 2786 }; 2787 mOwner->write(kData, sizeof(kData)); 2788 2789 mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2790 2791 mOwner->writeInt8(mCodecSpecificDataSize); 2792 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2793 2794 static const uint8_t kData2[] = { 2795 0x06, // SLConfigDescriptorTag 2796 0x01, 2797 0x02 2798 }; 2799 mOwner->write(kData2, sizeof(kData2)); 2800 2801 mOwner->endBox(); // esds 2802} 2803 2804void MPEG4Writer::Track::writeTkhdBox(uint32_t now) { 2805 mOwner->beginBox("tkhd"); 2806 // Flags = 7 to indicate that the track is enabled, and 2807 // part of the presentation 2808 mOwner->writeInt32(0x07); // version=0, flags=7 2809 mOwner->writeInt32(now); // creation time 2810 mOwner->writeInt32(now); // modification time 2811 mOwner->writeInt32(mTrackId); // track id starts with 1 2812 mOwner->writeInt32(0); // reserved 2813 int64_t trakDurationUs = getDurationUs(); 2814 int32_t mvhdTimeScale = mOwner->getTimeScale(); 2815 int32_t tkhdDuration = 2816 (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 2817 mOwner->writeInt32(tkhdDuration); // in mvhd timescale 2818 mOwner->writeInt32(0); // reserved 2819 mOwner->writeInt32(0); // reserved 2820 mOwner->writeInt16(0); // layer 2821 mOwner->writeInt16(0); // alternate group 2822 mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume 2823 mOwner->writeInt16(0); // reserved 2824 2825 mOwner->writeCompositionMatrix(mRotation); // matrix 2826 2827 if (mIsAudio) { 2828 mOwner->writeInt32(0); 2829 mOwner->writeInt32(0); 2830 } else { 2831 int32_t width, height; 2832 bool success = mMeta->findInt32(kKeyWidth, &width); 2833 success = success && mMeta->findInt32(kKeyHeight, &height); 2834 CHECK(success); 2835 2836 mOwner->writeInt32(width << 16); // 32-bit fixed-point value 2837 mOwner->writeInt32(height << 16); // 32-bit fixed-point value 2838 } 2839 mOwner->endBox(); // tkhd 2840} 2841 2842void MPEG4Writer::Track::writeVmhdBox() { 2843 mOwner->beginBox("vmhd"); 2844 mOwner->writeInt32(0x01); // version=0, flags=1 2845 mOwner->writeInt16(0); // graphics mode 2846 mOwner->writeInt16(0); // opcolor 2847 mOwner->writeInt16(0); 2848 mOwner->writeInt16(0); 2849 mOwner->endBox(); 2850} 2851 2852void MPEG4Writer::Track::writeSmhdBox() { 2853 mOwner->beginBox("smhd"); 2854 mOwner->writeInt32(0); // version=0, flags=0 2855 mOwner->writeInt16(0); // balance 2856 mOwner->writeInt16(0); // reserved 2857 mOwner->endBox(); 2858} 2859 2860void MPEG4Writer::Track::writeHdlrBox() { 2861 mOwner->beginBox("hdlr"); 2862 mOwner->writeInt32(0); // version=0, flags=0 2863 mOwner->writeInt32(0); // component type: should be mhlr 2864 mOwner->writeFourcc(mIsAudio ? "soun" : "vide"); // component subtype 2865 mOwner->writeInt32(0); // reserved 2866 mOwner->writeInt32(0); // reserved 2867 mOwner->writeInt32(0); // reserved 2868 // Removing "r" for the name string just makes the string 4 byte aligned 2869 mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle"); // name 2870 mOwner->endBox(); 2871} 2872 2873void MPEG4Writer::Track::writeMdhdBox(uint32_t now) { 2874 int64_t trakDurationUs = getDurationUs(); 2875 mOwner->beginBox("mdhd"); 2876 mOwner->writeInt32(0); // version=0, flags=0 2877 mOwner->writeInt32(now); // creation time 2878 mOwner->writeInt32(now); // modification time 2879 mOwner->writeInt32(mTimeScale); // media timescale 2880 int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6; 2881 mOwner->writeInt32(mdhdDuration); // use media timescale 2882 // Language follows the three letter standard ISO-639-2/T 2883 // 'e', 'n', 'g' for "English", for instance. 2884 // Each character is packed as the difference between its ASCII value and 0x60. 2885 // For "English", these are 00101, 01110, 00111. 2886 // XXX: Where is the padding bit located: 0x15C7? 2887 mOwner->writeInt16(0); // language code 2888 mOwner->writeInt16(0); // predefined 2889 mOwner->endBox(); 2890} 2891 2892void MPEG4Writer::Track::writeDamrBox() { 2893 // 3gpp2 Spec AMRSampleEntry fields 2894 mOwner->beginBox("damr"); 2895 mOwner->writeCString(" "); // vendor: 4 bytes 2896 mOwner->writeInt8(0); // decoder version 2897 mOwner->writeInt16(0x83FF); // mode set: all enabled 2898 mOwner->writeInt8(0); // mode change period 2899 mOwner->writeInt8(1); // frames per sample 2900 mOwner->endBox(); 2901} 2902 2903void MPEG4Writer::Track::writeUrlBox() { 2904 // The table index here refers to the sample description index 2905 // in the sample table entries. 2906 mOwner->beginBox("url "); 2907 mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 2908 mOwner->endBox(); // url 2909} 2910 2911void MPEG4Writer::Track::writeDrefBox() { 2912 mOwner->beginBox("dref"); 2913 mOwner->writeInt32(0); // version=0, flags=0 2914 mOwner->writeInt32(1); // entry count (either url or urn) 2915 writeUrlBox(); 2916 mOwner->endBox(); // dref 2917} 2918 2919void MPEG4Writer::Track::writeDinfBox() { 2920 mOwner->beginBox("dinf"); 2921 writeDrefBox(); 2922 mOwner->endBox(); // dinf 2923} 2924 2925void MPEG4Writer::Track::writeAvccBox() { 2926 CHECK(mCodecSpecificData); 2927 CHECK_GE(mCodecSpecificDataSize, 5); 2928 2929 // Patch avcc's lengthSize field to match the number 2930 // of bytes we use to indicate the size of a nal unit. 2931 uint8_t *ptr = (uint8_t *)mCodecSpecificData; 2932 ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); 2933 mOwner->beginBox("avcC"); 2934 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2935 mOwner->endBox(); // avcC 2936} 2937 2938void MPEG4Writer::Track::writeD263Box() { 2939 mOwner->beginBox("d263"); 2940 mOwner->writeInt32(0); // vendor 2941 mOwner->writeInt8(0); // decoder version 2942 mOwner->writeInt8(10); // level: 10 2943 mOwner->writeInt8(0); // profile: 0 2944 mOwner->endBox(); // d263 2945} 2946 2947// This is useful if the pixel is not square 2948void MPEG4Writer::Track::writePaspBox() { 2949 mOwner->beginBox("pasp"); 2950 mOwner->writeInt32(1 << 16); // hspacing 2951 mOwner->writeInt32(1 << 16); // vspacing 2952 mOwner->endBox(); // pasp 2953} 2954 2955int32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const { 2956 int64_t trackStartTimeOffsetUs = 0; 2957 int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 2958 if (mStartTimestampUs != moovStartTimeUs) { 2959 CHECK_GT(mStartTimestampUs, moovStartTimeUs); 2960 trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 2961 } 2962 return (trackStartTimeOffsetUs * mTimeScale + 500000LL) / 1000000LL; 2963} 2964 2965void MPEG4Writer::Track::writeSttsBox() { 2966 mOwner->beginBox("stts"); 2967 mOwner->writeInt32(0); // version=0, flags=0 2968 uint32_t duration; 2969 CHECK(mSttsTableEntries->get(duration, 1)); 2970 duration = htonl(duration); // Back to host byte order 2971 mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1); 2972 mSttsTableEntries->write(mOwner); 2973 mOwner->endBox(); // stts 2974} 2975 2976void MPEG4Writer::Track::writeCttsBox() { 2977 if (mIsAudio) { // ctts is not for audio 2978 return; 2979 } 2980 2981 // There is no B frame at all 2982 if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) { 2983 return; 2984 } 2985 2986 // Do not write ctts box when there is no need to have it. 2987 if (mCttsTableEntries->count() == 0) { 2988 return; 2989 } 2990 2991 ALOGV("ctts box has %d entries with range [%lld, %lld]", 2992 mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs); 2993 2994 mOwner->beginBox("ctts"); 2995 mOwner->writeInt32(0); // version=0, flags=0 2996 uint32_t duration; 2997 CHECK(mCttsTableEntries->get(duration, 1)); 2998 duration = htonl(duration); // Back host byte order 2999 mCttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime() - mMinCttsOffsetTimeUs), 1); 3000 mCttsTableEntries->write(mOwner); 3001 mOwner->endBox(); // ctts 3002} 3003 3004void MPEG4Writer::Track::writeStssBox() { 3005 mOwner->beginBox("stss"); 3006 mOwner->writeInt32(0); // version=0, flags=0 3007 mStssTableEntries->write(mOwner); 3008 mOwner->endBox(); // stss 3009} 3010 3011void MPEG4Writer::Track::writeStszBox() { 3012 mOwner->beginBox("stsz"); 3013 mOwner->writeInt32(0); // version=0, flags=0 3014 mOwner->writeInt32(0); 3015 mStszTableEntries->write(mOwner); 3016 mOwner->endBox(); // stsz 3017} 3018 3019void MPEG4Writer::Track::writeStscBox() { 3020 mOwner->beginBox("stsc"); 3021 mOwner->writeInt32(0); // version=0, flags=0 3022 mStscTableEntries->write(mOwner); 3023 mOwner->endBox(); // stsc 3024} 3025 3026void MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) { 3027 mOwner->beginBox(use32BitOffset? "stco": "co64"); 3028 mOwner->writeInt32(0); // version=0, flags=0 3029 if (use32BitOffset) { 3030 mStcoTableEntries->write(mOwner); 3031 } else { 3032 mCo64TableEntries->write(mOwner); 3033 } 3034 mOwner->endBox(); // stco or co64 3035} 3036 3037void MPEG4Writer::writeUdtaBox() { 3038 beginBox("udta"); 3039 writeGeoDataBox(); 3040 endBox(); 3041} 3042 3043/* 3044 * Geodata is stored according to ISO-6709 standard. 3045 */ 3046void MPEG4Writer::writeGeoDataBox() { 3047 beginBox("\xA9xyz"); 3048 /* 3049 * For historical reasons, any user data start 3050 * with "\0xA9", must be followed by its assoicated 3051 * language code. 3052 * 0x0012: text string length 3053 * 0x15c7: lang (locale) code: en 3054 */ 3055 writeInt32(0x001215c7); 3056 writeLatitude(mLatitudex10000); 3057 writeLongitude(mLongitudex10000); 3058 writeInt8(0x2F); 3059 endBox(); 3060} 3061 3062} // namespace android 3063