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