MPEG4Writer.cpp revision 96bdf620189622005e83b4f1421c4f25b7fa1729
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 1932const uint8_t *MPEG4Writer::Track::parseParamSet( 1933 const uint8_t *data, size_t length, int type, size_t *paramSetLen) { 1934 1935 ALOGV("parseParamSet"); 1936 CHECK(type == kNalUnitTypeSeqParamSet || 1937 type == kNalUnitTypePicParamSet); 1938 1939 const uint8_t *nextStartCode = findNextNalStartCode(data, length); 1940 *paramSetLen = nextStartCode - data; 1941 if (*paramSetLen == 0) { 1942 ALOGE("Param set is malformed, since its length is 0"); 1943 return NULL; 1944 } 1945 1946 AVCParamSet paramSet(*paramSetLen, data); 1947 if (type == kNalUnitTypeSeqParamSet) { 1948 if (*paramSetLen < 4) { 1949 ALOGE("Seq parameter set malformed"); 1950 return NULL; 1951 } 1952 if (mSeqParamSets.empty()) { 1953 mProfileIdc = data[1]; 1954 mProfileCompatible = data[2]; 1955 mLevelIdc = data[3]; 1956 } else { 1957 if (mProfileIdc != data[1] || 1958 mProfileCompatible != data[2] || 1959 mLevelIdc != data[3]) { 1960 // COULD DO: set profile/level to the lowest required to support all SPSs 1961 ALOGE("Inconsistent profile/level found in seq parameter sets"); 1962 return NULL; 1963 } 1964 } 1965 mSeqParamSets.push_back(paramSet); 1966 } else { 1967 mPicParamSets.push_back(paramSet); 1968 } 1969 return nextStartCode; 1970} 1971 1972status_t MPEG4Writer::Track::copyAVCCodecSpecificData( 1973 const uint8_t *data, size_t size) { 1974 ALOGV("copyAVCCodecSpecificData"); 1975 1976 // 2 bytes for each of the parameter set length field 1977 // plus the 7 bytes for the header 1978 return copyCodecSpecificData(data, size, 4 + 7); 1979} 1980 1981status_t MPEG4Writer::Track::copyHEVCCodecSpecificData( 1982 const uint8_t *data, size_t size) { 1983 ALOGV("copyHEVCCodecSpecificData"); 1984 1985 // Min length of HEVC CSD is 23. (ISO/IEC 14496-15:2014 Chapter 8.3.3.1.2) 1986 return copyCodecSpecificData(data, size, 23); 1987} 1988 1989status_t MPEG4Writer::Track::copyCodecSpecificData( 1990 const uint8_t *data, size_t size, size_t minLength) { 1991 if (size < minLength) { 1992 ALOGE("Codec specific data length too short: %zu", size); 1993 return ERROR_MALFORMED; 1994 } 1995 1996 mCodecSpecificData = malloc(size); 1997 if (mCodecSpecificData == NULL) { 1998 ALOGE("Failed allocating codec specific data"); 1999 return NO_MEMORY; 2000 } 2001 mCodecSpecificDataSize = size; 2002 memcpy(mCodecSpecificData, data, size); 2003 return OK; 2004} 2005 2006status_t MPEG4Writer::Track::parseAVCCodecSpecificData( 2007 const uint8_t *data, size_t size) { 2008 2009 ALOGV("parseAVCCodecSpecificData"); 2010 // Data starts with a start code. 2011 // SPS and PPS are separated with start codes. 2012 // Also, SPS must come before PPS 2013 uint8_t type = kNalUnitTypeSeqParamSet; 2014 bool gotSps = false; 2015 bool gotPps = false; 2016 const uint8_t *tmp = data; 2017 const uint8_t *nextStartCode = data; 2018 size_t bytesLeft = size; 2019 size_t paramSetLen = 0; 2020 mCodecSpecificDataSize = 0; 2021 while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 2022 getNalUnitType(*(tmp + 4), &type); 2023 if (type == kNalUnitTypeSeqParamSet) { 2024 if (gotPps) { 2025 ALOGE("SPS must come before PPS"); 2026 return ERROR_MALFORMED; 2027 } 2028 if (!gotSps) { 2029 gotSps = true; 2030 } 2031 nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 2032 } else if (type == kNalUnitTypePicParamSet) { 2033 if (!gotSps) { 2034 ALOGE("SPS must come before PPS"); 2035 return ERROR_MALFORMED; 2036 } 2037 if (!gotPps) { 2038 gotPps = true; 2039 } 2040 nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 2041 } else { 2042 ALOGE("Only SPS and PPS Nal units are expected"); 2043 return ERROR_MALFORMED; 2044 } 2045 2046 if (nextStartCode == NULL) { 2047 return ERROR_MALFORMED; 2048 } 2049 2050 // Move on to find the next parameter set 2051 bytesLeft -= nextStartCode - tmp; 2052 tmp = nextStartCode; 2053 mCodecSpecificDataSize += (2 + paramSetLen); 2054 } 2055 2056 { 2057 // Check on the number of seq parameter sets 2058 size_t nSeqParamSets = mSeqParamSets.size(); 2059 if (nSeqParamSets == 0) { 2060 ALOGE("Cound not find sequence parameter set"); 2061 return ERROR_MALFORMED; 2062 } 2063 2064 if (nSeqParamSets > 0x1F) { 2065 ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets); 2066 return ERROR_MALFORMED; 2067 } 2068 } 2069 2070 { 2071 // Check on the number of pic parameter sets 2072 size_t nPicParamSets = mPicParamSets.size(); 2073 if (nPicParamSets == 0) { 2074 ALOGE("Cound not find picture parameter set"); 2075 return ERROR_MALFORMED; 2076 } 2077 if (nPicParamSets > 0xFF) { 2078 ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets); 2079 return ERROR_MALFORMED; 2080 } 2081 } 2082// FIXME: 2083// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above 2084// and remove #if 0 2085#if 0 2086 { 2087 // Check on the profiles 2088 // These profiles requires additional parameter set extensions 2089 if (mProfileIdc == 100 || mProfileIdc == 110 || 2090 mProfileIdc == 122 || mProfileIdc == 144) { 2091 ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc); 2092 return BAD_VALUE; 2093 } 2094 } 2095#endif 2096 return OK; 2097} 2098 2099status_t MPEG4Writer::Track::makeAVCCodecSpecificData( 2100 const uint8_t *data, size_t size) { 2101 2102 if (mCodecSpecificData != NULL) { 2103 ALOGE("Already have codec specific data"); 2104 return ERROR_MALFORMED; 2105 } 2106 2107 if (size < 4) { 2108 ALOGE("Codec specific data length too short: %zu", size); 2109 return ERROR_MALFORMED; 2110 } 2111 2112 // Data is in the form of AVCCodecSpecificData 2113 if (memcmp("\x00\x00\x00\x01", data, 4)) { 2114 return copyAVCCodecSpecificData(data, size); 2115 } 2116 2117 if (parseAVCCodecSpecificData(data, size) != OK) { 2118 return ERROR_MALFORMED; 2119 } 2120 2121 // ISO 14496-15: AVC file format 2122 mCodecSpecificDataSize += 7; // 7 more bytes in the header 2123 mCodecSpecificData = malloc(mCodecSpecificDataSize); 2124 if (mCodecSpecificData == NULL) { 2125 mCodecSpecificDataSize = 0; 2126 ALOGE("Failed allocating codec specific data"); 2127 return NO_MEMORY; 2128 } 2129 uint8_t *header = (uint8_t *)mCodecSpecificData; 2130 header[0] = 1; // version 2131 header[1] = mProfileIdc; // profile indication 2132 header[2] = mProfileCompatible; // profile compatibility 2133 header[3] = mLevelIdc; 2134 2135 // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne 2136 if (mOwner->useNalLengthFour()) { 2137 header[4] = 0xfc | 3; // length size == 4 bytes 2138 } else { 2139 header[4] = 0xfc | 1; // length size == 2 bytes 2140 } 2141 2142 // 3-bit '111' followed by 5-bit numSequenceParameterSets 2143 int nSequenceParamSets = mSeqParamSets.size(); 2144 header[5] = 0xe0 | nSequenceParamSets; 2145 header += 6; 2146 for (List<AVCParamSet>::iterator it = mSeqParamSets.begin(); 2147 it != mSeqParamSets.end(); ++it) { 2148 // 16-bit sequence parameter set length 2149 uint16_t seqParamSetLength = it->mLength; 2150 header[0] = seqParamSetLength >> 8; 2151 header[1] = seqParamSetLength & 0xff; 2152 2153 // SPS NAL unit (sequence parameter length bytes) 2154 memcpy(&header[2], it->mData, seqParamSetLength); 2155 header += (2 + seqParamSetLength); 2156 } 2157 2158 // 8-bit nPictureParameterSets 2159 int nPictureParamSets = mPicParamSets.size(); 2160 header[0] = nPictureParamSets; 2161 header += 1; 2162 for (List<AVCParamSet>::iterator it = mPicParamSets.begin(); 2163 it != mPicParamSets.end(); ++it) { 2164 // 16-bit picture parameter set length 2165 uint16_t picParamSetLength = it->mLength; 2166 header[0] = picParamSetLength >> 8; 2167 header[1] = picParamSetLength & 0xff; 2168 2169 // PPS Nal unit (picture parameter set length bytes) 2170 memcpy(&header[2], it->mData, picParamSetLength); 2171 header += (2 + picParamSetLength); 2172 } 2173 2174 return OK; 2175} 2176 2177 2178status_t MPEG4Writer::Track::parseHEVCCodecSpecificData( 2179 const uint8_t *data, size_t size, HevcParameterSets ¶mSets) { 2180 2181 ALOGV("parseHEVCCodecSpecificData"); 2182 const uint8_t *tmp = data; 2183 const uint8_t *nextStartCode = data; 2184 size_t bytesLeft = size; 2185 while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 2186 nextStartCode = findNextNalStartCode(tmp + 4, bytesLeft - 4); 2187 status_t err = paramSets.addNalUnit(tmp + 4, (nextStartCode - tmp) - 4); 2188 if (err != OK) { 2189 return ERROR_MALFORMED; 2190 } 2191 2192 // Move on to find the next parameter set 2193 bytesLeft -= nextStartCode - tmp; 2194 tmp = nextStartCode; 2195 } 2196 2197 size_t csdSize = 23; 2198 const size_t numNalUnits = paramSets.getNumNalUnits(); 2199 for (size_t i = 0; i < ARRAY_SIZE(kMandatoryHevcNalUnitTypes); ++i) { 2200 int type = kMandatoryHevcNalUnitTypes[i]; 2201 size_t numParamSets = paramSets.getNumNalUnitsOfType(type); 2202 if (numParamSets == 0) { 2203 ALOGE("Cound not find NAL unit of type %d", type); 2204 return ERROR_MALFORMED; 2205 } 2206 } 2207 for (size_t i = 0; i < ARRAY_SIZE(kHevcNalUnitTypes); ++i) { 2208 int type = kHevcNalUnitTypes[i]; 2209 size_t numParamSets = paramSets.getNumNalUnitsOfType(type); 2210 if (numParamSets > 0xffff) { 2211 ALOGE("Too many seq parameter sets (%zu) found", numParamSets); 2212 return ERROR_MALFORMED; 2213 } 2214 csdSize += 3; 2215 for (size_t j = 0; j < numNalUnits; ++j) { 2216 if (paramSets.getType(j) != type) { 2217 continue; 2218 } 2219 csdSize += 2 + paramSets.getSize(j); 2220 } 2221 } 2222 mCodecSpecificDataSize = csdSize; 2223 return OK; 2224} 2225 2226status_t MPEG4Writer::Track::makeHEVCCodecSpecificData( 2227 const uint8_t *data, size_t size) { 2228 2229 if (mCodecSpecificData != NULL) { 2230 ALOGE("Already have codec specific data"); 2231 return ERROR_MALFORMED; 2232 } 2233 2234 if (size < 4) { 2235 ALOGE("Codec specific data length too short: %zu", size); 2236 return ERROR_MALFORMED; 2237 } 2238 2239 // Data is in the form of HEVCCodecSpecificData 2240 if (memcmp("\x00\x00\x00\x01", data, 4)) { 2241 return copyHEVCCodecSpecificData(data, size); 2242 } 2243 2244 HevcParameterSets paramSets; 2245 if (parseHEVCCodecSpecificData(data, size, paramSets) != OK) { 2246 ALOGE("failed parsing codec specific data"); 2247 return ERROR_MALFORMED; 2248 } 2249 2250 mCodecSpecificData = malloc(mCodecSpecificDataSize); 2251 if (mCodecSpecificData == NULL) { 2252 mCodecSpecificDataSize = 0; 2253 ALOGE("Failed allocating codec specific data"); 2254 return NO_MEMORY; 2255 } 2256 status_t err = paramSets.makeHvcc((uint8_t *)mCodecSpecificData, 2257 &mCodecSpecificDataSize, mOwner->useNalLengthFour() ? 4 : 2); 2258 if (err != OK) { 2259 ALOGE("failed constructing HVCC atom"); 2260 return err; 2261 } 2262 2263 return OK; 2264} 2265 2266/* 2267 * Updates the drift time from the audio track so that 2268 * the video track can get the updated drift time information 2269 * from the file writer. The fluctuation of the drift time of the audio 2270 * encoding path is smoothed out with a simple filter by giving a larger 2271 * weight to more recently drift time. The filter coefficients, 0.5 and 0.5, 2272 * are heuristically determined. 2273 */ 2274void MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) { 2275 int64_t driftTimeUs = 0; 2276 if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) { 2277 int64_t prevDriftTimeUs = mOwner->getDriftTimeUs(); 2278 int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1; 2279 mOwner->setDriftTimeUs(timeUs); 2280 } 2281} 2282 2283status_t MPEG4Writer::Track::threadEntry() { 2284 int32_t count = 0; 2285 const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 2286 const bool hasMultipleTracks = (mOwner->numTracks() > 1); 2287 int64_t chunkTimestampUs = 0; 2288 int32_t nChunks = 0; 2289 int32_t nActualFrames = 0; // frames containing non-CSD data (non-0 length) 2290 int32_t nZeroLengthFrames = 0; 2291 int64_t lastTimestampUs = 0; // Previous sample time stamp 2292 int64_t lastDurationUs = 0; // Between the previous two samples 2293 int64_t currDurationTicks = 0; // Timescale based ticks 2294 int64_t lastDurationTicks = 0; // Timescale based ticks 2295 int32_t sampleCount = 1; // Sample count in the current stts table entry 2296 uint32_t previousSampleSize = 0; // Size of the previous sample 2297 int64_t previousPausedDurationUs = 0; 2298 int64_t timestampUs = 0; 2299 int64_t cttsOffsetTimeUs = 0; 2300 int64_t currCttsOffsetTimeTicks = 0; // Timescale based ticks 2301 int64_t lastCttsOffsetTimeTicks = -1; // Timescale based ticks 2302 int32_t cttsSampleCount = 0; // Sample count in the current ctts table entry 2303 uint32_t lastSamplesPerChunk = 0; 2304 2305 if (mIsAudio) { 2306 prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0); 2307 } else { 2308 prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0); 2309 } 2310 2311 if (mOwner->isRealTimeRecording()) { 2312 androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); 2313 } 2314 2315 sp<MetaData> meta_data; 2316 2317 status_t err = OK; 2318 MediaBuffer *buffer; 2319 const char *trackName = mIsAudio ? "Audio" : "Video"; 2320 while (!mDone && (err = mSource->read(&buffer)) == OK) { 2321 if (buffer->range_length() == 0) { 2322 buffer->release(); 2323 buffer = NULL; 2324 ++nZeroLengthFrames; 2325 continue; 2326 } 2327 2328 // If the codec specific data has not been received yet, delay pause. 2329 // After the codec specific data is received, discard what we received 2330 // when the track is to be paused. 2331 if (mPaused && !mResumed) { 2332 buffer->release(); 2333 buffer = NULL; 2334 continue; 2335 } 2336 2337 ++count; 2338 2339 int32_t isCodecConfig; 2340 if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 2341 && isCodecConfig) { 2342 // if config format (at track addition) already had CSD, keep that 2343 // UNLESS we have not received any frames yet. 2344 // TODO: for now the entire CSD has to come in one frame for encoders, even though 2345 // they need to be spread out for decoders. 2346 if (mGotAllCodecSpecificData && nActualFrames > 0) { 2347 ALOGI("ignoring additional CSD for video track after first frame"); 2348 } else { 2349 mMeta = mSource->getFormat(); // get output format after format change 2350 2351 if (mIsAvc) { 2352 status_t err = makeAVCCodecSpecificData( 2353 (const uint8_t *)buffer->data() 2354 + buffer->range_offset(), 2355 buffer->range_length()); 2356 CHECK_EQ((status_t)OK, err); 2357 } else if (mIsHevc) { 2358 status_t err = makeHEVCCodecSpecificData( 2359 (const uint8_t *)buffer->data() 2360 + buffer->range_offset(), 2361 buffer->range_length()); 2362 CHECK_EQ((status_t)OK, err); 2363 } else if (mIsMPEG4) { 2364 copyCodecSpecificData((const uint8_t *)buffer->data() + buffer->range_offset(), 2365 buffer->range_length()); 2366 } 2367 } 2368 2369 buffer->release(); 2370 buffer = NULL; 2371 2372 mGotAllCodecSpecificData = true; 2373 continue; 2374 } 2375 2376 ++nActualFrames; 2377 2378 // Make a deep copy of the MediaBuffer and Metadata and release 2379 // the original as soon as we can 2380 MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 2381 memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 2382 buffer->range_length()); 2383 copy->set_range(0, buffer->range_length()); 2384 meta_data = new MetaData(*buffer->meta_data().get()); 2385 buffer->release(); 2386 buffer = NULL; 2387 2388 if (mIsAvc || mIsHevc) StripStartcode(copy); 2389 2390 size_t sampleSize = copy->range_length(); 2391 if (mIsAvc || mIsHevc) { 2392 if (mOwner->useNalLengthFour()) { 2393 sampleSize += 4; 2394 } else { 2395 sampleSize += 2; 2396 } 2397 } 2398 2399 // Max file size or duration handling 2400 mMdatSizeBytes += sampleSize; 2401 updateTrackSizeEstimate(); 2402 2403 if (mOwner->exceedsFileSizeLimit()) { 2404 ALOGW("Recorded file size exceeds limit %" PRId64 "bytes", 2405 mOwner->mMaxFileSizeLimitBytes); 2406 mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 2407 break; 2408 } 2409 if (mOwner->exceedsFileDurationLimit()) { 2410 ALOGW("Recorded file duration exceeds limit %" PRId64 "microseconds", 2411 mOwner->mMaxFileDurationLimitUs); 2412 mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 2413 break; 2414 } 2415 2416 2417 int32_t isSync = false; 2418 meta_data->findInt32(kKeyIsSyncFrame, &isSync); 2419 CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 2420 2421//////////////////////////////////////////////////////////////////////////////// 2422 if (mStszTableEntries->count() == 0) { 2423 mFirstSampleTimeRealUs = systemTime() / 1000; 2424 mStartTimestampUs = timestampUs; 2425 mOwner->setStartTimestampUs(mStartTimestampUs); 2426 previousPausedDurationUs = mStartTimestampUs; 2427 } 2428 2429 if (mResumed) { 2430 int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs; 2431 if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) { 2432 copy->release(); 2433 return ERROR_MALFORMED; 2434 } 2435 2436 int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs; 2437 if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) { 2438 copy->release(); 2439 return ERROR_MALFORMED; 2440 } 2441 2442 previousPausedDurationUs += pausedDurationUs - lastDurationUs; 2443 mResumed = false; 2444 } 2445 2446 timestampUs -= previousPausedDurationUs; 2447 if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) { 2448 copy->release(); 2449 return ERROR_MALFORMED; 2450 } 2451 2452 if (!mIsAudio) { 2453 /* 2454 * Composition time: timestampUs 2455 * Decoding time: decodingTimeUs 2456 * Composition time offset = composition time - decoding time 2457 */ 2458 int64_t decodingTimeUs; 2459 CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs)); 2460 decodingTimeUs -= previousPausedDurationUs; 2461 cttsOffsetTimeUs = 2462 timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs; 2463 if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) { 2464 copy->release(); 2465 return ERROR_MALFORMED; 2466 } 2467 2468 timestampUs = decodingTimeUs; 2469 ALOGV("decoding time: %" PRId64 " and ctts offset time: %" PRId64, 2470 timestampUs, cttsOffsetTimeUs); 2471 2472 // Update ctts box table if necessary 2473 currCttsOffsetTimeTicks = 2474 (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL; 2475 if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) { 2476 copy->release(); 2477 return ERROR_MALFORMED; 2478 } 2479 2480 if (mStszTableEntries->count() == 0) { 2481 // Force the first ctts table entry to have one single entry 2482 // so that we can do adjustment for the initial track start 2483 // time offset easily in writeCttsBox(). 2484 lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 2485 addOneCttsTableEntry(1, currCttsOffsetTimeTicks); 2486 cttsSampleCount = 0; // No sample in ctts box is pending 2487 } else { 2488 if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) { 2489 addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 2490 lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 2491 cttsSampleCount = 1; // One sample in ctts box is pending 2492 } else { 2493 ++cttsSampleCount; 2494 } 2495 } 2496 2497 // Update ctts time offset range 2498 if (mStszTableEntries->count() == 0) { 2499 mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2500 mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2501 } else { 2502 if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) { 2503 mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2504 } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) { 2505 mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2506 } 2507 } 2508 2509 } 2510 2511 if (mOwner->isRealTimeRecording()) { 2512 if (mIsAudio) { 2513 updateDriftTime(meta_data); 2514 } 2515 } 2516 2517 if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) { 2518 copy->release(); 2519 return ERROR_MALFORMED; 2520 } 2521 2522 ALOGV("%s media time stamp: %" PRId64 " and previous paused duration %" PRId64, 2523 trackName, timestampUs, previousPausedDurationUs); 2524 if (timestampUs > mTrackDurationUs) { 2525 mTrackDurationUs = timestampUs; 2526 } 2527 2528 // We need to use the time scale based ticks, rather than the 2529 // timestamp itself to determine whether we have to use a new 2530 // stts entry, since we may have rounding errors. 2531 // The calculation is intended to reduce the accumulated 2532 // rounding errors. 2533 currDurationTicks = 2534 ((timestampUs * mTimeScale + 500000LL) / 1000000LL - 2535 (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL); 2536 if (currDurationTicks < 0ll) { 2537 ALOGE("do not support out of order frames (timestamp: %lld < last: %lld for %s track", 2538 (long long)timestampUs, (long long)lastTimestampUs, trackName); 2539 copy->release(); 2540 mSource->stop(); 2541 return UNKNOWN_ERROR; 2542 } 2543 2544 // if the duration is different for this sample, see if it is close enough to the previous 2545 // duration that we can fudge it and use the same value, to avoid filling the stts table 2546 // with lots of near-identical entries. 2547 // "close enough" here means that the current duration needs to be adjusted by less 2548 // than 0.1 milliseconds 2549 if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) { 2550 int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL 2551 + (mTimeScale / 2)) / mTimeScale; 2552 if (deltaUs > -100 && deltaUs < 100) { 2553 // use previous ticks, and adjust timestamp as if it was actually that number 2554 // of ticks 2555 currDurationTicks = lastDurationTicks; 2556 timestampUs += deltaUs; 2557 } 2558 } 2559 2560 mStszTableEntries->add(htonl(sampleSize)); 2561 if (mStszTableEntries->count() > 2) { 2562 2563 // Force the first sample to have its own stts entry so that 2564 // we can adjust its value later to maintain the A/V sync. 2565 if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) { 2566 addOneSttsTableEntry(sampleCount, lastDurationTicks); 2567 sampleCount = 1; 2568 } else { 2569 ++sampleCount; 2570 } 2571 2572 } 2573 if (mSamplesHaveSameSize) { 2574 if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) { 2575 mSamplesHaveSameSize = false; 2576 } 2577 previousSampleSize = sampleSize; 2578 } 2579 ALOGV("%s timestampUs/lastTimestampUs: %" PRId64 "/%" PRId64, 2580 trackName, timestampUs, lastTimestampUs); 2581 lastDurationUs = timestampUs - lastTimestampUs; 2582 lastDurationTicks = currDurationTicks; 2583 lastTimestampUs = timestampUs; 2584 2585 if (isSync != 0) { 2586 addOneStssTableEntry(mStszTableEntries->count()); 2587 } 2588 2589 if (mTrackingProgressStatus) { 2590 if (mPreviousTrackTimeUs <= 0) { 2591 mPreviousTrackTimeUs = mStartTimestampUs; 2592 } 2593 trackProgressStatus(timestampUs); 2594 } 2595 if (!hasMultipleTracks) { 2596 off64_t offset = (mIsAvc || mIsHevc) ? mOwner->addLengthPrefixedSample_l(copy) 2597 : mOwner->addSample_l(copy); 2598 2599 uint32_t count = (mOwner->use32BitFileOffset() 2600 ? mStcoTableEntries->count() 2601 : mCo64TableEntries->count()); 2602 2603 if (count == 0) { 2604 addChunkOffset(offset); 2605 } 2606 copy->release(); 2607 copy = NULL; 2608 continue; 2609 } 2610 2611 mChunkSamples.push_back(copy); 2612 if (interleaveDurationUs == 0) { 2613 addOneStscTableEntry(++nChunks, 1); 2614 bufferChunk(timestampUs); 2615 } else { 2616 if (chunkTimestampUs == 0) { 2617 chunkTimestampUs = timestampUs; 2618 } else { 2619 int64_t chunkDurationUs = timestampUs - chunkTimestampUs; 2620 if (chunkDurationUs > interleaveDurationUs) { 2621 if (chunkDurationUs > mMaxChunkDurationUs) { 2622 mMaxChunkDurationUs = chunkDurationUs; 2623 } 2624 ++nChunks; 2625 if (nChunks == 1 || // First chunk 2626 lastSamplesPerChunk != mChunkSamples.size()) { 2627 lastSamplesPerChunk = mChunkSamples.size(); 2628 addOneStscTableEntry(nChunks, lastSamplesPerChunk); 2629 } 2630 bufferChunk(timestampUs); 2631 chunkTimestampUs = timestampUs; 2632 } 2633 } 2634 } 2635 2636 } 2637 2638 if (isTrackMalFormed()) { 2639 err = ERROR_MALFORMED; 2640 } 2641 2642 mOwner->trackProgressStatus(mTrackId, -1, err); 2643 2644 // Last chunk 2645 if (!hasMultipleTracks) { 2646 addOneStscTableEntry(1, mStszTableEntries->count()); 2647 } else if (!mChunkSamples.empty()) { 2648 addOneStscTableEntry(++nChunks, mChunkSamples.size()); 2649 bufferChunk(timestampUs); 2650 } 2651 2652 // We don't really know how long the last frame lasts, since 2653 // there is no frame time after it, just repeat the previous 2654 // frame's duration. 2655 if (mStszTableEntries->count() == 1) { 2656 lastDurationUs = 0; // A single sample's duration 2657 lastDurationTicks = 0; 2658 } else { 2659 ++sampleCount; // Count for the last sample 2660 } 2661 2662 if (mStszTableEntries->count() <= 2) { 2663 addOneSttsTableEntry(1, lastDurationTicks); 2664 if (sampleCount - 1 > 0) { 2665 addOneSttsTableEntry(sampleCount - 1, lastDurationTicks); 2666 } 2667 } else { 2668 addOneSttsTableEntry(sampleCount, lastDurationTicks); 2669 } 2670 2671 // The last ctts box may not have been written yet, and this 2672 // is to make sure that we write out the last ctts box. 2673 if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) { 2674 if (cttsSampleCount > 0) { 2675 addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 2676 } 2677 } 2678 2679 mTrackDurationUs += lastDurationUs; 2680 mReachedEOS = true; 2681 2682 sendTrackSummary(hasMultipleTracks); 2683 2684 ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s", 2685 count, nZeroLengthFrames, mStszTableEntries->count(), trackName); 2686 if (mIsAudio) { 2687 ALOGI("Audio track drift time: %" PRId64 " us", mOwner->getDriftTimeUs()); 2688 } 2689 2690 if (err == ERROR_END_OF_STREAM) { 2691 return OK; 2692 } 2693 return err; 2694} 2695 2696bool MPEG4Writer::Track::isTrackMalFormed() const { 2697 if (mStszTableEntries->count() == 0) { // no samples written 2698 ALOGE("The number of recorded samples is 0"); 2699 return true; 2700 } 2701 2702 if (!mIsAudio && mStssTableEntries->count() == 0) { // no sync frames for video 2703 ALOGE("There are no sync frames for video track"); 2704 return true; 2705 } 2706 2707 if (OK != checkCodecSpecificData()) { // no codec specific data 2708 return true; 2709 } 2710 2711 return false; 2712} 2713 2714void MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) { 2715 2716 // Send track summary only if test mode is enabled. 2717 if (!isTestModeEnabled()) { 2718 return; 2719 } 2720 2721 int trackNum = (mTrackId << 28); 2722 2723 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2724 trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE, 2725 mIsAudio? 0: 1); 2726 2727 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2728 trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS, 2729 mTrackDurationUs / 1000); 2730 2731 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2732 trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES, 2733 mStszTableEntries->count()); 2734 2735 { 2736 // The system delay time excluding the requested initial delay that 2737 // is used to eliminate the recording sound. 2738 int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 2739 if (startTimeOffsetUs < 0) { // Start time offset was not set 2740 startTimeOffsetUs = kInitialDelayTimeUs; 2741 } 2742 int64_t initialDelayUs = 2743 mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs; 2744 2745 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2746 trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS, 2747 (initialDelayUs) / 1000); 2748 } 2749 2750 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2751 trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES, 2752 mMdatSizeBytes / 1024); 2753 2754 if (hasMultipleTracks) { 2755 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2756 trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS, 2757 mMaxChunkDurationUs / 1000); 2758 2759 int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 2760 if (mStartTimestampUs != moovStartTimeUs) { 2761 int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 2762 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2763 trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS, 2764 startTimeOffsetUs / 1000); 2765 } 2766 } 2767} 2768 2769void MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) { 2770 ALOGV("trackProgressStatus: %" PRId64 " us", timeUs); 2771 2772 if (mTrackEveryTimeDurationUs > 0 && 2773 timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 2774 ALOGV("Fire time tracking progress status at %" PRId64 " us", timeUs); 2775 mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err); 2776 mPreviousTrackTimeUs = timeUs; 2777 } 2778} 2779 2780void MPEG4Writer::trackProgressStatus( 2781 size_t trackId, int64_t timeUs, status_t err) { 2782 Mutex::Autolock lock(mLock); 2783 int32_t trackNum = (trackId << 28); 2784 2785 // Error notification 2786 // Do not consider ERROR_END_OF_STREAM an error 2787 if (err != OK && err != ERROR_END_OF_STREAM) { 2788 notify(MEDIA_RECORDER_TRACK_EVENT_ERROR, 2789 trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL, 2790 err); 2791 return; 2792 } 2793 2794 if (timeUs == -1) { 2795 // Send completion notification 2796 notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2797 trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, 2798 err); 2799 } else { 2800 // Send progress status 2801 notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2802 trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME, 2803 timeUs / 1000); 2804 } 2805} 2806 2807void MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) { 2808 ALOGV("setDriftTimeUs: %" PRId64 " us", driftTimeUs); 2809 Mutex::Autolock autolock(mLock); 2810 mDriftTimeUs = driftTimeUs; 2811} 2812 2813int64_t MPEG4Writer::getDriftTimeUs() { 2814 ALOGV("getDriftTimeUs: %" PRId64 " us", mDriftTimeUs); 2815 Mutex::Autolock autolock(mLock); 2816 return mDriftTimeUs; 2817} 2818 2819bool MPEG4Writer::isRealTimeRecording() const { 2820 return mIsRealTimeRecording; 2821} 2822 2823bool MPEG4Writer::useNalLengthFour() { 2824 return mUse4ByteNalLength; 2825} 2826 2827void MPEG4Writer::Track::bufferChunk(int64_t timestampUs) { 2828 ALOGV("bufferChunk"); 2829 2830 Chunk chunk(this, timestampUs, mChunkSamples); 2831 mOwner->bufferChunk(chunk); 2832 mChunkSamples.clear(); 2833} 2834 2835int64_t MPEG4Writer::Track::getDurationUs() const { 2836 return mTrackDurationUs; 2837} 2838 2839int64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 2840 return mEstimatedTrackSizeBytes; 2841} 2842 2843status_t MPEG4Writer::Track::checkCodecSpecificData() const { 2844 const char *mime; 2845 CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 2846 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) || 2847 !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) || 2848 !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime) || 2849 !strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) { 2850 if (!mCodecSpecificData || 2851 mCodecSpecificDataSize <= 0) { 2852 ALOGE("Missing codec specific data"); 2853 return ERROR_MALFORMED; 2854 } 2855 } else { 2856 if (mCodecSpecificData || 2857 mCodecSpecificDataSize > 0) { 2858 ALOGE("Unexepected codec specific data found"); 2859 return ERROR_MALFORMED; 2860 } 2861 } 2862 return OK; 2863} 2864 2865void MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) { 2866 2867 ALOGV("%s track time scale: %d", 2868 mIsAudio? "Audio": "Video", mTimeScale); 2869 2870 uint32_t now = getMpeg4Time(); 2871 mOwner->beginBox("trak"); 2872 writeTkhdBox(now); 2873 mOwner->beginBox("mdia"); 2874 writeMdhdBox(now); 2875 writeHdlrBox(); 2876 mOwner->beginBox("minf"); 2877 if (mIsAudio) { 2878 writeSmhdBox(); 2879 } else { 2880 writeVmhdBox(); 2881 } 2882 writeDinfBox(); 2883 writeStblBox(use32BitOffset); 2884 mOwner->endBox(); // minf 2885 mOwner->endBox(); // mdia 2886 mOwner->endBox(); // trak 2887} 2888 2889void MPEG4Writer::Track::writeStblBox(bool use32BitOffset) { 2890 mOwner->beginBox("stbl"); 2891 mOwner->beginBox("stsd"); 2892 mOwner->writeInt32(0); // version=0, flags=0 2893 mOwner->writeInt32(1); // entry count 2894 if (mIsAudio) { 2895 writeAudioFourCCBox(); 2896 } else { 2897 writeVideoFourCCBox(); 2898 } 2899 mOwner->endBox(); // stsd 2900 writeSttsBox(); 2901 writeCttsBox(); 2902 if (!mIsAudio) { 2903 writeStssBox(); 2904 } 2905 writeStszBox(); 2906 writeStscBox(); 2907 writeStcoBox(use32BitOffset); 2908 mOwner->endBox(); // stbl 2909} 2910 2911void MPEG4Writer::Track::writeVideoFourCCBox() { 2912 const char *mime; 2913 bool success = mMeta->findCString(kKeyMIMEType, &mime); 2914 CHECK(success); 2915 const char *fourcc = getFourCCForMime(mime); 2916 if (fourcc == NULL) { 2917 ALOGE("Unknown mime type '%s'.", mime); 2918 CHECK(!"should not be here, unknown mime type."); 2919 } 2920 2921 mOwner->beginBox(fourcc); // video format 2922 mOwner->writeInt32(0); // reserved 2923 mOwner->writeInt16(0); // reserved 2924 mOwner->writeInt16(1); // data ref index 2925 mOwner->writeInt16(0); // predefined 2926 mOwner->writeInt16(0); // reserved 2927 mOwner->writeInt32(0); // predefined 2928 mOwner->writeInt32(0); // predefined 2929 mOwner->writeInt32(0); // predefined 2930 2931 int32_t width, height; 2932 success = mMeta->findInt32(kKeyWidth, &width); 2933 success = success && mMeta->findInt32(kKeyHeight, &height); 2934 CHECK(success); 2935 2936 mOwner->writeInt16(width); 2937 mOwner->writeInt16(height); 2938 mOwner->writeInt32(0x480000); // horiz resolution 2939 mOwner->writeInt32(0x480000); // vert resolution 2940 mOwner->writeInt32(0); // reserved 2941 mOwner->writeInt16(1); // frame count 2942 mOwner->writeInt8(0); // compressor string length 2943 mOwner->write(" ", 31); 2944 mOwner->writeInt16(0x18); // depth 2945 mOwner->writeInt16(-1); // predefined 2946 2947 CHECK_LT(23 + mCodecSpecificDataSize, 128); 2948 2949 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2950 writeMp4vEsdsBox(); 2951 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2952 writeD263Box(); 2953 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2954 writeAvccBox(); 2955 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) { 2956 writeHvccBox(); 2957 } 2958 2959 writePaspBox(); 2960 writeColrBox(); 2961 mOwner->endBox(); // mp4v, s263 or avc1 2962} 2963 2964void MPEG4Writer::Track::writeColrBox() { 2965 ColorAspects aspects; 2966 memset(&aspects, 0, sizeof(aspects)); 2967 // TRICKY: using | instead of || because we want to execute all findInt32-s 2968 if (mMeta->findInt32(kKeyColorPrimaries, (int32_t*)&aspects.mPrimaries) 2969 | mMeta->findInt32(kKeyTransferFunction, (int32_t*)&aspects.mTransfer) 2970 | mMeta->findInt32(kKeyColorMatrix, (int32_t*)&aspects.mMatrixCoeffs) 2971 | mMeta->findInt32(kKeyColorRange, (int32_t*)&aspects.mRange)) { 2972 int32_t primaries, transfer, coeffs; 2973 bool fullRange; 2974 ColorUtils::convertCodecColorAspectsToIsoAspects( 2975 aspects, &primaries, &transfer, &coeffs, &fullRange); 2976 mOwner->beginBox("colr"); 2977 mOwner->writeFourcc("nclx"); 2978 mOwner->writeInt16(primaries); 2979 mOwner->writeInt16(transfer); 2980 mOwner->writeInt16(coeffs); 2981 mOwner->writeInt8(fullRange ? 128 : 0); 2982 mOwner->endBox(); // colr 2983 } 2984} 2985 2986void MPEG4Writer::Track::writeAudioFourCCBox() { 2987 const char *mime; 2988 bool success = mMeta->findCString(kKeyMIMEType, &mime); 2989 CHECK(success); 2990 const char *fourcc = getFourCCForMime(mime); 2991 if (fourcc == NULL) { 2992 ALOGE("Unknown mime type '%s'.", mime); 2993 CHECK(!"should not be here, unknown mime type."); 2994 } 2995 2996 mOwner->beginBox(fourcc); // audio format 2997 mOwner->writeInt32(0); // reserved 2998 mOwner->writeInt16(0); // reserved 2999 mOwner->writeInt16(0x1); // data ref index 3000 mOwner->writeInt32(0); // reserved 3001 mOwner->writeInt32(0); // reserved 3002 int32_t nChannels; 3003 CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 3004 mOwner->writeInt16(nChannels); // channel count 3005 mOwner->writeInt16(16); // sample size 3006 mOwner->writeInt16(0); // predefined 3007 mOwner->writeInt16(0); // reserved 3008 3009 int32_t samplerate; 3010 success = mMeta->findInt32(kKeySampleRate, &samplerate); 3011 CHECK(success); 3012 mOwner->writeInt32(samplerate << 16); 3013 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 3014 writeMp4aEsdsBox(); 3015 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) || 3016 !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 3017 writeDamrBox(); 3018 } 3019 mOwner->endBox(); 3020} 3021 3022void MPEG4Writer::Track::writeMp4aEsdsBox() { 3023 mOwner->beginBox("esds"); 3024 CHECK(mCodecSpecificData); 3025 CHECK_GT(mCodecSpecificDataSize, 0); 3026 3027 // Make sure all sizes encode to a single byte. 3028 CHECK_LT(mCodecSpecificDataSize + 23, 128); 3029 3030 mOwner->writeInt32(0); // version=0, flags=0 3031 mOwner->writeInt8(0x03); // ES_DescrTag 3032 mOwner->writeInt8(23 + mCodecSpecificDataSize); 3033 mOwner->writeInt16(0x0000);// ES_ID 3034 mOwner->writeInt8(0x00); 3035 3036 mOwner->writeInt8(0x04); // DecoderConfigDescrTag 3037 mOwner->writeInt8(15 + mCodecSpecificDataSize); 3038 mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 3039 mOwner->writeInt8(0x15); // streamType AudioStream 3040 3041 mOwner->writeInt16(0x03); // XXX 3042 mOwner->writeInt8(0x00); // buffer size 24-bit (0x300) 3043 3044 int32_t avgBitrate = 0; 3045 (void)mMeta->findInt32(kKeyBitRate, &avgBitrate); 3046 int32_t maxBitrate = 0; 3047 (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate); 3048 mOwner->writeInt32(maxBitrate); 3049 mOwner->writeInt32(avgBitrate); 3050 3051 mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 3052 mOwner->writeInt8(mCodecSpecificDataSize); 3053 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 3054 3055 static const uint8_t kData2[] = { 3056 0x06, // SLConfigDescriptorTag 3057 0x01, 3058 0x02 3059 }; 3060 mOwner->write(kData2, sizeof(kData2)); 3061 3062 mOwner->endBox(); // esds 3063} 3064 3065void MPEG4Writer::Track::writeMp4vEsdsBox() { 3066 CHECK(mCodecSpecificData); 3067 CHECK_GT(mCodecSpecificDataSize, 0); 3068 mOwner->beginBox("esds"); 3069 3070 mOwner->writeInt32(0); // version=0, flags=0 3071 3072 mOwner->writeInt8(0x03); // ES_DescrTag 3073 mOwner->writeInt8(23 + mCodecSpecificDataSize); 3074 mOwner->writeInt16(0x0000); // ES_ID 3075 mOwner->writeInt8(0x1f); 3076 3077 mOwner->writeInt8(0x04); // DecoderConfigDescrTag 3078 mOwner->writeInt8(15 + mCodecSpecificDataSize); 3079 mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 3080 mOwner->writeInt8(0x11); // streamType VisualStream 3081 3082 static const uint8_t kData[] = { 3083 0x01, 0x77, 0x00, // buffer size 96000 bytes 3084 }; 3085 mOwner->write(kData, sizeof(kData)); 3086 3087 int32_t avgBitrate = 0; 3088 (void)mMeta->findInt32(kKeyBitRate, &avgBitrate); 3089 int32_t maxBitrate = 0; 3090 (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate); 3091 mOwner->writeInt32(maxBitrate); 3092 mOwner->writeInt32(avgBitrate); 3093 3094 mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 3095 3096 mOwner->writeInt8(mCodecSpecificDataSize); 3097 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 3098 3099 static const uint8_t kData2[] = { 3100 0x06, // SLConfigDescriptorTag 3101 0x01, 3102 0x02 3103 }; 3104 mOwner->write(kData2, sizeof(kData2)); 3105 3106 mOwner->endBox(); // esds 3107} 3108 3109void MPEG4Writer::Track::writeTkhdBox(uint32_t now) { 3110 mOwner->beginBox("tkhd"); 3111 // Flags = 7 to indicate that the track is enabled, and 3112 // part of the presentation 3113 mOwner->writeInt32(0x07); // version=0, flags=7 3114 mOwner->writeInt32(now); // creation time 3115 mOwner->writeInt32(now); // modification time 3116 mOwner->writeInt32(mTrackId); // track id starts with 1 3117 mOwner->writeInt32(0); // reserved 3118 int64_t trakDurationUs = getDurationUs(); 3119 int32_t mvhdTimeScale = mOwner->getTimeScale(); 3120 int32_t tkhdDuration = 3121 (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 3122 mOwner->writeInt32(tkhdDuration); // in mvhd timescale 3123 mOwner->writeInt32(0); // reserved 3124 mOwner->writeInt32(0); // reserved 3125 mOwner->writeInt16(0); // layer 3126 mOwner->writeInt16(0); // alternate group 3127 mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume 3128 mOwner->writeInt16(0); // reserved 3129 3130 mOwner->writeCompositionMatrix(mRotation); // matrix 3131 3132 if (mIsAudio) { 3133 mOwner->writeInt32(0); 3134 mOwner->writeInt32(0); 3135 } else { 3136 int32_t width, height; 3137 bool success = mMeta->findInt32(kKeyWidth, &width); 3138 success = success && mMeta->findInt32(kKeyHeight, &height); 3139 CHECK(success); 3140 3141 mOwner->writeInt32(width << 16); // 32-bit fixed-point value 3142 mOwner->writeInt32(height << 16); // 32-bit fixed-point value 3143 } 3144 mOwner->endBox(); // tkhd 3145} 3146 3147void MPEG4Writer::Track::writeVmhdBox() { 3148 mOwner->beginBox("vmhd"); 3149 mOwner->writeInt32(0x01); // version=0, flags=1 3150 mOwner->writeInt16(0); // graphics mode 3151 mOwner->writeInt16(0); // opcolor 3152 mOwner->writeInt16(0); 3153 mOwner->writeInt16(0); 3154 mOwner->endBox(); 3155} 3156 3157void MPEG4Writer::Track::writeSmhdBox() { 3158 mOwner->beginBox("smhd"); 3159 mOwner->writeInt32(0); // version=0, flags=0 3160 mOwner->writeInt16(0); // balance 3161 mOwner->writeInt16(0); // reserved 3162 mOwner->endBox(); 3163} 3164 3165void MPEG4Writer::Track::writeHdlrBox() { 3166 mOwner->beginBox("hdlr"); 3167 mOwner->writeInt32(0); // version=0, flags=0 3168 mOwner->writeInt32(0); // component type: should be mhlr 3169 mOwner->writeFourcc(mIsAudio ? "soun" : "vide"); // component subtype 3170 mOwner->writeInt32(0); // reserved 3171 mOwner->writeInt32(0); // reserved 3172 mOwner->writeInt32(0); // reserved 3173 // Removing "r" for the name string just makes the string 4 byte aligned 3174 mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle"); // name 3175 mOwner->endBox(); 3176} 3177 3178void MPEG4Writer::Track::writeMdhdBox(uint32_t now) { 3179 int64_t trakDurationUs = getDurationUs(); 3180 mOwner->beginBox("mdhd"); 3181 mOwner->writeInt32(0); // version=0, flags=0 3182 mOwner->writeInt32(now); // creation time 3183 mOwner->writeInt32(now); // modification time 3184 mOwner->writeInt32(mTimeScale); // media timescale 3185 int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6; 3186 mOwner->writeInt32(mdhdDuration); // use media timescale 3187 // Language follows the three letter standard ISO-639-2/T 3188 // 'e', 'n', 'g' for "English", for instance. 3189 // Each character is packed as the difference between its ASCII value and 0x60. 3190 // For "English", these are 00101, 01110, 00111. 3191 // XXX: Where is the padding bit located: 0x15C7? 3192 mOwner->writeInt16(0); // language code 3193 mOwner->writeInt16(0); // predefined 3194 mOwner->endBox(); 3195} 3196 3197void MPEG4Writer::Track::writeDamrBox() { 3198 // 3gpp2 Spec AMRSampleEntry fields 3199 mOwner->beginBox("damr"); 3200 mOwner->writeCString(" "); // vendor: 4 bytes 3201 mOwner->writeInt8(0); // decoder version 3202 mOwner->writeInt16(0x83FF); // mode set: all enabled 3203 mOwner->writeInt8(0); // mode change period 3204 mOwner->writeInt8(1); // frames per sample 3205 mOwner->endBox(); 3206} 3207 3208void MPEG4Writer::Track::writeUrlBox() { 3209 // The table index here refers to the sample description index 3210 // in the sample table entries. 3211 mOwner->beginBox("url "); 3212 mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 3213 mOwner->endBox(); // url 3214} 3215 3216void MPEG4Writer::Track::writeDrefBox() { 3217 mOwner->beginBox("dref"); 3218 mOwner->writeInt32(0); // version=0, flags=0 3219 mOwner->writeInt32(1); // entry count (either url or urn) 3220 writeUrlBox(); 3221 mOwner->endBox(); // dref 3222} 3223 3224void MPEG4Writer::Track::writeDinfBox() { 3225 mOwner->beginBox("dinf"); 3226 writeDrefBox(); 3227 mOwner->endBox(); // dinf 3228} 3229 3230void MPEG4Writer::Track::writeAvccBox() { 3231 CHECK(mCodecSpecificData); 3232 CHECK_GE(mCodecSpecificDataSize, 5); 3233 3234 // Patch avcc's lengthSize field to match the number 3235 // of bytes we use to indicate the size of a nal unit. 3236 uint8_t *ptr = (uint8_t *)mCodecSpecificData; 3237 ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); 3238 mOwner->beginBox("avcC"); 3239 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 3240 mOwner->endBox(); // avcC 3241} 3242 3243 3244void MPEG4Writer::Track::writeHvccBox() { 3245 CHECK(mCodecSpecificData); 3246 CHECK_GE(mCodecSpecificDataSize, 5); 3247 3248 // Patch avcc's lengthSize field to match the number 3249 // of bytes we use to indicate the size of a nal unit. 3250 uint8_t *ptr = (uint8_t *)mCodecSpecificData; 3251 ptr[21] = (ptr[21] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); 3252 mOwner->beginBox("hvcC"); 3253 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 3254 mOwner->endBox(); // hvcC 3255} 3256 3257void MPEG4Writer::Track::writeD263Box() { 3258 mOwner->beginBox("d263"); 3259 mOwner->writeInt32(0); // vendor 3260 mOwner->writeInt8(0); // decoder version 3261 mOwner->writeInt8(10); // level: 10 3262 mOwner->writeInt8(0); // profile: 0 3263 mOwner->endBox(); // d263 3264} 3265 3266// This is useful if the pixel is not square 3267void MPEG4Writer::Track::writePaspBox() { 3268 mOwner->beginBox("pasp"); 3269 mOwner->writeInt32(1 << 16); // hspacing 3270 mOwner->writeInt32(1 << 16); // vspacing 3271 mOwner->endBox(); // pasp 3272} 3273 3274int32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const { 3275 int64_t trackStartTimeOffsetUs = 0; 3276 int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 3277 if (mStartTimestampUs != moovStartTimeUs) { 3278 CHECK_GT(mStartTimestampUs, moovStartTimeUs); 3279 trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 3280 } 3281 return (trackStartTimeOffsetUs * mTimeScale + 500000LL) / 1000000LL; 3282} 3283 3284void MPEG4Writer::Track::writeSttsBox() { 3285 mOwner->beginBox("stts"); 3286 mOwner->writeInt32(0); // version=0, flags=0 3287 uint32_t duration; 3288 CHECK(mSttsTableEntries->get(duration, 1)); 3289 duration = htonl(duration); // Back to host byte order 3290 mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1); 3291 mSttsTableEntries->write(mOwner); 3292 mOwner->endBox(); // stts 3293} 3294 3295void MPEG4Writer::Track::writeCttsBox() { 3296 if (mIsAudio) { // ctts is not for audio 3297 return; 3298 } 3299 3300 // There is no B frame at all 3301 if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) { 3302 return; 3303 } 3304 3305 // Do not write ctts box when there is no need to have it. 3306 if (mCttsTableEntries->count() == 0) { 3307 return; 3308 } 3309 3310 ALOGV("ctts box has %d entries with range [%" PRId64 ", %" PRId64 "]", 3311 mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs); 3312 3313 mOwner->beginBox("ctts"); 3314 mOwner->writeInt32(0); // version=0, flags=0 3315 uint32_t duration; 3316 CHECK(mCttsTableEntries->get(duration, 1)); 3317 duration = htonl(duration); // Back host byte order 3318 mCttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime() - mMinCttsOffsetTimeUs), 1); 3319 mCttsTableEntries->write(mOwner); 3320 mOwner->endBox(); // ctts 3321} 3322 3323void MPEG4Writer::Track::writeStssBox() { 3324 mOwner->beginBox("stss"); 3325 mOwner->writeInt32(0); // version=0, flags=0 3326 mStssTableEntries->write(mOwner); 3327 mOwner->endBox(); // stss 3328} 3329 3330void MPEG4Writer::Track::writeStszBox() { 3331 mOwner->beginBox("stsz"); 3332 mOwner->writeInt32(0); // version=0, flags=0 3333 mOwner->writeInt32(0); 3334 mStszTableEntries->write(mOwner); 3335 mOwner->endBox(); // stsz 3336} 3337 3338void MPEG4Writer::Track::writeStscBox() { 3339 mOwner->beginBox("stsc"); 3340 mOwner->writeInt32(0); // version=0, flags=0 3341 mStscTableEntries->write(mOwner); 3342 mOwner->endBox(); // stsc 3343} 3344 3345void MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) { 3346 mOwner->beginBox(use32BitOffset? "stco": "co64"); 3347 mOwner->writeInt32(0); // version=0, flags=0 3348 if (use32BitOffset) { 3349 mStcoTableEntries->write(mOwner); 3350 } else { 3351 mCo64TableEntries->write(mOwner); 3352 } 3353 mOwner->endBox(); // stco or co64 3354} 3355 3356void MPEG4Writer::writeUdtaBox() { 3357 beginBox("udta"); 3358 writeGeoDataBox(); 3359 endBox(); 3360} 3361 3362void MPEG4Writer::writeHdlr() { 3363 beginBox("hdlr"); 3364 writeInt32(0); // Version, Flags 3365 writeInt32(0); // Predefined 3366 writeFourcc("mdta"); 3367 writeInt32(0); // Reserved[0] 3368 writeInt32(0); // Reserved[1] 3369 writeInt32(0); // Reserved[2] 3370 writeInt8(0); // Name (empty) 3371 endBox(); 3372} 3373 3374void MPEG4Writer::writeKeys() { 3375 size_t count = mMetaKeys->countEntries(); 3376 3377 beginBox("keys"); 3378 writeInt32(0); // Version, Flags 3379 writeInt32(count); // Entry_count 3380 for (size_t i = 0; i < count; i++) { 3381 AMessage::Type type; 3382 const char *key = mMetaKeys->getEntryNameAt(i, &type); 3383 size_t n = strlen(key); 3384 writeInt32(n + 8); 3385 writeFourcc("mdta"); 3386 write(key, n); // write without the \0 3387 } 3388 endBox(); 3389} 3390 3391void MPEG4Writer::writeIlst() { 3392 size_t count = mMetaKeys->countEntries(); 3393 3394 beginBox("ilst"); 3395 for (size_t i = 0; i < count; i++) { 3396 beginBox(i + 1); // key id (1-based) 3397 beginBox("data"); 3398 AMessage::Type type; 3399 const char *key = mMetaKeys->getEntryNameAt(i, &type); 3400 switch (type) { 3401 case AMessage::kTypeString: 3402 { 3403 AString val; 3404 CHECK(mMetaKeys->findString(key, &val)); 3405 writeInt32(1); // type = UTF8 3406 writeInt32(0); // default country/language 3407 write(val.c_str(), strlen(val.c_str())); // write without \0 3408 break; 3409 } 3410 3411 case AMessage::kTypeFloat: 3412 { 3413 float val; 3414 CHECK(mMetaKeys->findFloat(key, &val)); 3415 writeInt32(23); // type = float32 3416 writeInt32(0); // default country/language 3417 writeInt32(*reinterpret_cast<int32_t *>(&val)); 3418 break; 3419 } 3420 3421 case AMessage::kTypeInt32: 3422 { 3423 int32_t val; 3424 CHECK(mMetaKeys->findInt32(key, &val)); 3425 writeInt32(67); // type = signed int32 3426 writeInt32(0); // default country/language 3427 writeInt32(val); 3428 break; 3429 } 3430 3431 default: 3432 { 3433 ALOGW("Unsupported key type, writing 0 instead"); 3434 writeInt32(77); // type = unsigned int32 3435 writeInt32(0); // default country/language 3436 writeInt32(0); 3437 break; 3438 } 3439 } 3440 endBox(); // data 3441 endBox(); // key id 3442 } 3443 endBox(); // ilst 3444} 3445 3446void MPEG4Writer::writeMetaBox() { 3447 size_t count = mMetaKeys->countEntries(); 3448 if (count == 0) { 3449 return; 3450 } 3451 3452 beginBox("meta"); 3453 writeHdlr(); 3454 writeKeys(); 3455 writeIlst(); 3456 endBox(); 3457} 3458 3459/* 3460 * Geodata is stored according to ISO-6709 standard. 3461 */ 3462void MPEG4Writer::writeGeoDataBox() { 3463 beginBox("\xA9xyz"); 3464 /* 3465 * For historical reasons, any user data start 3466 * with "\0xA9", must be followed by its assoicated 3467 * language code. 3468 * 0x0012: text string length 3469 * 0x15c7: lang (locale) code: en 3470 */ 3471 writeInt32(0x001215c7); 3472 writeLatitude(mLatitudex10000); 3473 writeLongitude(mLongitudex10000); 3474 writeInt8(0x2F); 3475 endBox(); 3476} 3477 3478} // namespace android 3479