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