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