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