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