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