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