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