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