MPEG4Writer.cpp revision 71ee06d081d814b079ed22d2e1a50e1a0bbb490e
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 = 2000000LL, // 2 seconds 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 copyCodecSpecificData((uint8_t*)data, size) == OK) { 1866 mGotAllCodecSpecificData = true; 1867 } 1868 return; 1869 } 1870 } 1871 if (data != NULL && copyCodecSpecificData((uint8_t *)data, size) == OK) { 1872 mGotAllCodecSpecificData = true; 1873 } 1874} 1875 1876MPEG4Writer::Track::~Track() { 1877 stop(); 1878 1879 delete mStszTableEntries; 1880 delete mStcoTableEntries; 1881 delete mCo64TableEntries; 1882 delete mStscTableEntries; 1883 delete mSttsTableEntries; 1884 delete mStssTableEntries; 1885 delete mCttsTableEntries; 1886 1887 mStszTableEntries = NULL; 1888 mStcoTableEntries = NULL; 1889 mCo64TableEntries = NULL; 1890 mStscTableEntries = NULL; 1891 mSttsTableEntries = NULL; 1892 mStssTableEntries = NULL; 1893 mCttsTableEntries = NULL; 1894 1895 if (mCodecSpecificData != NULL) { 1896 free(mCodecSpecificData); 1897 mCodecSpecificData = NULL; 1898 } 1899} 1900 1901void MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) { 1902 ALOGV("initTrackingProgressStatus"); 1903 mPreviousTrackTimeUs = -1; 1904 mTrackingProgressStatus = false; 1905 mTrackEveryTimeDurationUs = 0; 1906 { 1907 int64_t timeUs; 1908 if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) { 1909 ALOGV("Receive request to track progress status for every %" PRId64 " us", timeUs); 1910 mTrackEveryTimeDurationUs = timeUs; 1911 mTrackingProgressStatus = true; 1912 } 1913 } 1914} 1915 1916// static 1917void *MPEG4Writer::ThreadWrapper(void *me) { 1918 ALOGV("ThreadWrapper: %p", me); 1919 MPEG4Writer *writer = static_cast<MPEG4Writer *>(me); 1920 writer->threadFunc(); 1921 return NULL; 1922} 1923 1924void MPEG4Writer::bufferChunk(const Chunk& chunk) { 1925 ALOGV("bufferChunk: %p", chunk.mTrack); 1926 Mutex::Autolock autolock(mLock); 1927 CHECK_EQ(mDone, false); 1928 1929 for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 1930 it != mChunkInfos.end(); ++it) { 1931 1932 if (chunk.mTrack == it->mTrack) { // Found owner 1933 it->mChunks.push_back(chunk); 1934 mChunkReadyCondition.signal(); 1935 return; 1936 } 1937 } 1938 1939 CHECK(!"Received a chunk for a unknown track"); 1940} 1941 1942void MPEG4Writer::writeChunkToFile(Chunk* chunk) { 1943 ALOGV("writeChunkToFile: %" PRId64 " from %s track", 1944 chunk->mTimeStampUs, chunk->mTrack->getTrackType()); 1945 1946 int32_t isFirstSample = true; 1947 while (!chunk->mSamples.empty()) { 1948 List<MediaBuffer *>::iterator it = chunk->mSamples.begin(); 1949 1950 off64_t offset = (chunk->mTrack->isAvc() || chunk->mTrack->isHevc()) 1951 ? addMultipleLengthPrefixedSamples_l(*it) 1952 : addSample_l(*it); 1953 1954 if (isFirstSample) { 1955 chunk->mTrack->addChunkOffset(offset); 1956 isFirstSample = false; 1957 } 1958 1959 (*it)->release(); 1960 (*it) = NULL; 1961 chunk->mSamples.erase(it); 1962 } 1963 chunk->mSamples.clear(); 1964} 1965 1966void MPEG4Writer::writeAllChunks() { 1967 ALOGV("writeAllChunks"); 1968 size_t outstandingChunks = 0; 1969 Chunk chunk; 1970 while (findChunkToWrite(&chunk)) { 1971 writeChunkToFile(&chunk); 1972 ++outstandingChunks; 1973 } 1974 1975 sendSessionSummary(); 1976 1977 mChunkInfos.clear(); 1978 ALOGD("%zu chunks are written in the last batch", outstandingChunks); 1979} 1980 1981bool MPEG4Writer::findChunkToWrite(Chunk *chunk) { 1982 ALOGV("findChunkToWrite"); 1983 1984 int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL; 1985 Track *track = NULL; 1986 for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 1987 it != mChunkInfos.end(); ++it) { 1988 if (!it->mChunks.empty()) { 1989 List<Chunk>::iterator chunkIt = it->mChunks.begin(); 1990 if (chunkIt->mTimeStampUs < minTimestampUs) { 1991 minTimestampUs = chunkIt->mTimeStampUs; 1992 track = it->mTrack; 1993 } 1994 } 1995 } 1996 1997 if (track == NULL) { 1998 ALOGV("Nothing to be written after all"); 1999 return false; 2000 } 2001 2002 if (mIsFirstChunk) { 2003 mIsFirstChunk = false; 2004 } 2005 2006 for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 2007 it != mChunkInfos.end(); ++it) { 2008 if (it->mTrack == track) { 2009 *chunk = *(it->mChunks.begin()); 2010 it->mChunks.erase(it->mChunks.begin()); 2011 CHECK_EQ(chunk->mTrack, track); 2012 2013 int64_t interChunkTimeUs = 2014 chunk->mTimeStampUs - it->mPrevChunkTimestampUs; 2015 if (interChunkTimeUs > it->mPrevChunkTimestampUs) { 2016 it->mMaxInterChunkDurUs = interChunkTimeUs; 2017 } 2018 2019 return true; 2020 } 2021 } 2022 2023 return false; 2024} 2025 2026void MPEG4Writer::threadFunc() { 2027 ALOGV("threadFunc"); 2028 2029 prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0); 2030 2031 Mutex::Autolock autoLock(mLock); 2032 while (!mDone) { 2033 Chunk chunk; 2034 bool chunkFound = false; 2035 2036 while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) { 2037 mChunkReadyCondition.wait(mLock); 2038 } 2039 2040 // In real time recording mode, write without holding the lock in order 2041 // to reduce the blocking time for media track threads. 2042 // Otherwise, hold the lock until the existing chunks get written to the 2043 // file. 2044 if (chunkFound) { 2045 if (mIsRealTimeRecording) { 2046 mLock.unlock(); 2047 } 2048 writeChunkToFile(&chunk); 2049 if (mIsRealTimeRecording) { 2050 mLock.lock(); 2051 } 2052 } 2053 } 2054 2055 writeAllChunks(); 2056} 2057 2058status_t MPEG4Writer::startWriterThread() { 2059 ALOGV("startWriterThread"); 2060 2061 mDone = false; 2062 mIsFirstChunk = true; 2063 mDriftTimeUs = 0; 2064 for (List<Track *>::iterator it = mTracks.begin(); 2065 it != mTracks.end(); ++it) { 2066 ChunkInfo info; 2067 info.mTrack = *it; 2068 info.mPrevChunkTimestampUs = 0; 2069 info.mMaxInterChunkDurUs = 0; 2070 mChunkInfos.push_back(info); 2071 } 2072 2073 pthread_attr_t attr; 2074 pthread_attr_init(&attr); 2075 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 2076 pthread_create(&mThread, &attr, ThreadWrapper, this); 2077 pthread_attr_destroy(&attr); 2078 mWriterThreadStarted = true; 2079 return OK; 2080} 2081 2082 2083status_t MPEG4Writer::Track::start(MetaData *params) { 2084 if (!mDone && mPaused) { 2085 mPaused = false; 2086 mResumed = true; 2087 return OK; 2088 } 2089 2090 int64_t startTimeUs; 2091 if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) { 2092 startTimeUs = 0; 2093 } 2094 mStartTimeRealUs = startTimeUs; 2095 2096 int32_t rotationDegrees; 2097 if (mIsVideo && params && params->findInt32(kKeyRotation, &rotationDegrees)) { 2098 mRotation = rotationDegrees; 2099 } 2100 2101 initTrackingProgressStatus(params); 2102 2103 sp<MetaData> meta = new MetaData; 2104 if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) { 2105 /* 2106 * This extra delay of accepting incoming audio/video signals 2107 * helps to align a/v start time at the beginning of a recording 2108 * session, and it also helps eliminate the "recording" sound for 2109 * camcorder applications. 2110 * 2111 * If client does not set the start time offset, we fall back to 2112 * use the default initial delay value. 2113 */ 2114 int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 2115 if (startTimeOffsetUs < 0) { // Start time offset was not set 2116 startTimeOffsetUs = kInitialDelayTimeUs; 2117 } 2118 startTimeUs += startTimeOffsetUs; 2119 ALOGI("Start time offset: %" PRId64 " us", startTimeOffsetUs); 2120 } 2121 2122 meta->setInt64(kKeyTime, startTimeUs); 2123 2124 status_t err = mSource->start(meta.get()); 2125 if (err != OK) { 2126 mDone = mReachedEOS = true; 2127 return err; 2128 } 2129 2130 pthread_attr_t attr; 2131 pthread_attr_init(&attr); 2132 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 2133 2134 mDone = false; 2135 mStarted = true; 2136 mTrackDurationUs = 0; 2137 mReachedEOS = false; 2138 mEstimatedTrackSizeBytes = 0; 2139 mMdatSizeBytes = 0; 2140 mMaxChunkDurationUs = 0; 2141 mLastDecodingTimeUs = -1; 2142 2143 pthread_create(&mThread, &attr, ThreadWrapper, this); 2144 pthread_attr_destroy(&attr); 2145 2146 return OK; 2147} 2148 2149status_t MPEG4Writer::Track::pause() { 2150 mPaused = true; 2151 return OK; 2152} 2153 2154status_t MPEG4Writer::Track::stop(bool stopSource) { 2155 ALOGD("%s track stopping. %s source", getTrackType(), stopSource ? "Stop" : "Not Stop"); 2156 if (!mStarted) { 2157 ALOGE("Stop() called but track is not started"); 2158 return ERROR_END_OF_STREAM; 2159 } 2160 2161 if (mDone) { 2162 return OK; 2163 } 2164 2165 if (stopSource) { 2166 ALOGD("%s track source stopping", getTrackType()); 2167 mSource->stop(); 2168 ALOGD("%s track source stopped", getTrackType()); 2169 } 2170 2171 // Set mDone to be true after sucessfully stop mSource as mSource may be still outputting 2172 // buffers to the writer. 2173 mDone = true; 2174 2175 void *dummy; 2176 pthread_join(mThread, &dummy); 2177 status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); 2178 2179 ALOGD("%s track stopped. %s source", getTrackType(), stopSource ? "Stop" : "Not Stop"); 2180 return err; 2181} 2182 2183bool MPEG4Writer::Track::reachedEOS() { 2184 return mReachedEOS; 2185} 2186 2187// static 2188void *MPEG4Writer::Track::ThreadWrapper(void *me) { 2189 Track *track = static_cast<Track *>(me); 2190 2191 status_t err = track->threadEntry(); 2192 return (void *)(uintptr_t)err; 2193} 2194 2195static void getNalUnitType(uint8_t byte, uint8_t* type) { 2196 ALOGV("getNalUnitType: %d", byte); 2197 2198 // nal_unit_type: 5-bit unsigned integer 2199 *type = (byte & 0x1F); 2200} 2201 2202const uint8_t *MPEG4Writer::Track::parseParamSet( 2203 const uint8_t *data, size_t length, int type, size_t *paramSetLen) { 2204 2205 ALOGV("parseParamSet"); 2206 CHECK(type == kNalUnitTypeSeqParamSet || 2207 type == kNalUnitTypePicParamSet); 2208 2209 const uint8_t *nextStartCode = findNextNalStartCode(data, length); 2210 *paramSetLen = nextStartCode - data; 2211 if (*paramSetLen == 0) { 2212 ALOGE("Param set is malformed, since its length is 0"); 2213 return NULL; 2214 } 2215 2216 AVCParamSet paramSet(*paramSetLen, data); 2217 if (type == kNalUnitTypeSeqParamSet) { 2218 if (*paramSetLen < 4) { 2219 ALOGE("Seq parameter set malformed"); 2220 return NULL; 2221 } 2222 if (mSeqParamSets.empty()) { 2223 mProfileIdc = data[1]; 2224 mProfileCompatible = data[2]; 2225 mLevelIdc = data[3]; 2226 } else { 2227 if (mProfileIdc != data[1] || 2228 mProfileCompatible != data[2] || 2229 mLevelIdc != data[3]) { 2230 // COULD DO: set profile/level to the lowest required to support all SPSs 2231 ALOGE("Inconsistent profile/level found in seq parameter sets"); 2232 return NULL; 2233 } 2234 } 2235 mSeqParamSets.push_back(paramSet); 2236 } else { 2237 mPicParamSets.push_back(paramSet); 2238 } 2239 return nextStartCode; 2240} 2241 2242status_t MPEG4Writer::Track::copyAVCCodecSpecificData( 2243 const uint8_t *data, size_t size) { 2244 ALOGV("copyAVCCodecSpecificData"); 2245 2246 // 2 bytes for each of the parameter set length field 2247 // plus the 7 bytes for the header 2248 return copyCodecSpecificData(data, size, 4 + 7); 2249} 2250 2251status_t MPEG4Writer::Track::copyHEVCCodecSpecificData( 2252 const uint8_t *data, size_t size) { 2253 ALOGV("copyHEVCCodecSpecificData"); 2254 2255 // Min length of HEVC CSD is 23. (ISO/IEC 14496-15:2014 Chapter 8.3.3.1.2) 2256 return copyCodecSpecificData(data, size, 23); 2257} 2258 2259status_t MPEG4Writer::Track::copyCodecSpecificData( 2260 const uint8_t *data, size_t size, size_t minLength) { 2261 if (size < minLength) { 2262 ALOGE("Codec specific data length too short: %zu", size); 2263 return ERROR_MALFORMED; 2264 } 2265 2266 mCodecSpecificData = malloc(size); 2267 if (mCodecSpecificData == NULL) { 2268 ALOGE("Failed allocating codec specific data"); 2269 return NO_MEMORY; 2270 } 2271 mCodecSpecificDataSize = size; 2272 memcpy(mCodecSpecificData, data, size); 2273 return OK; 2274} 2275 2276status_t MPEG4Writer::Track::parseAVCCodecSpecificData( 2277 const uint8_t *data, size_t size) { 2278 2279 ALOGV("parseAVCCodecSpecificData"); 2280 // Data starts with a start code. 2281 // SPS and PPS are separated with start codes. 2282 // Also, SPS must come before PPS 2283 uint8_t type = kNalUnitTypeSeqParamSet; 2284 bool gotSps = false; 2285 bool gotPps = false; 2286 const uint8_t *tmp = data; 2287 const uint8_t *nextStartCode = data; 2288 size_t bytesLeft = size; 2289 size_t paramSetLen = 0; 2290 mCodecSpecificDataSize = 0; 2291 while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 2292 getNalUnitType(*(tmp + 4), &type); 2293 if (type == kNalUnitTypeSeqParamSet) { 2294 if (gotPps) { 2295 ALOGE("SPS must come before PPS"); 2296 return ERROR_MALFORMED; 2297 } 2298 if (!gotSps) { 2299 gotSps = true; 2300 } 2301 nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 2302 } else if (type == kNalUnitTypePicParamSet) { 2303 if (!gotSps) { 2304 ALOGE("SPS must come before PPS"); 2305 return ERROR_MALFORMED; 2306 } 2307 if (!gotPps) { 2308 gotPps = true; 2309 } 2310 nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 2311 } else { 2312 ALOGE("Only SPS and PPS Nal units are expected"); 2313 return ERROR_MALFORMED; 2314 } 2315 2316 if (nextStartCode == NULL) { 2317 return ERROR_MALFORMED; 2318 } 2319 2320 // Move on to find the next parameter set 2321 bytesLeft -= nextStartCode - tmp; 2322 tmp = nextStartCode; 2323 mCodecSpecificDataSize += (2 + paramSetLen); 2324 } 2325 2326 { 2327 // Check on the number of seq parameter sets 2328 size_t nSeqParamSets = mSeqParamSets.size(); 2329 if (nSeqParamSets == 0) { 2330 ALOGE("Cound not find sequence parameter set"); 2331 return ERROR_MALFORMED; 2332 } 2333 2334 if (nSeqParamSets > 0x1F) { 2335 ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets); 2336 return ERROR_MALFORMED; 2337 } 2338 } 2339 2340 { 2341 // Check on the number of pic parameter sets 2342 size_t nPicParamSets = mPicParamSets.size(); 2343 if (nPicParamSets == 0) { 2344 ALOGE("Cound not find picture parameter set"); 2345 return ERROR_MALFORMED; 2346 } 2347 if (nPicParamSets > 0xFF) { 2348 ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets); 2349 return ERROR_MALFORMED; 2350 } 2351 } 2352// FIXME: 2353// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above 2354// and remove #if 0 2355#if 0 2356 { 2357 // Check on the profiles 2358 // These profiles requires additional parameter set extensions 2359 if (mProfileIdc == 100 || mProfileIdc == 110 || 2360 mProfileIdc == 122 || mProfileIdc == 144) { 2361 ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc); 2362 return BAD_VALUE; 2363 } 2364 } 2365#endif 2366 return OK; 2367} 2368 2369status_t MPEG4Writer::Track::makeAVCCodecSpecificData( 2370 const uint8_t *data, size_t size) { 2371 2372 if (mCodecSpecificData != NULL) { 2373 ALOGE("Already have codec specific data"); 2374 return ERROR_MALFORMED; 2375 } 2376 2377 if (size < 4) { 2378 ALOGE("Codec specific data length too short: %zu", size); 2379 return ERROR_MALFORMED; 2380 } 2381 2382 // Data is in the form of AVCCodecSpecificData 2383 if (memcmp("\x00\x00\x00\x01", data, 4)) { 2384 return copyAVCCodecSpecificData(data, size); 2385 } 2386 2387 if (parseAVCCodecSpecificData(data, size) != OK) { 2388 return ERROR_MALFORMED; 2389 } 2390 2391 // ISO 14496-15: AVC file format 2392 mCodecSpecificDataSize += 7; // 7 more bytes in the header 2393 mCodecSpecificData = malloc(mCodecSpecificDataSize); 2394 if (mCodecSpecificData == NULL) { 2395 mCodecSpecificDataSize = 0; 2396 ALOGE("Failed allocating codec specific data"); 2397 return NO_MEMORY; 2398 } 2399 uint8_t *header = (uint8_t *)mCodecSpecificData; 2400 header[0] = 1; // version 2401 header[1] = mProfileIdc; // profile indication 2402 header[2] = mProfileCompatible; // profile compatibility 2403 header[3] = mLevelIdc; 2404 2405 // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne 2406 if (mOwner->useNalLengthFour()) { 2407 header[4] = 0xfc | 3; // length size == 4 bytes 2408 } else { 2409 header[4] = 0xfc | 1; // length size == 2 bytes 2410 } 2411 2412 // 3-bit '111' followed by 5-bit numSequenceParameterSets 2413 int nSequenceParamSets = mSeqParamSets.size(); 2414 header[5] = 0xe0 | nSequenceParamSets; 2415 header += 6; 2416 for (List<AVCParamSet>::iterator it = mSeqParamSets.begin(); 2417 it != mSeqParamSets.end(); ++it) { 2418 // 16-bit sequence parameter set length 2419 uint16_t seqParamSetLength = it->mLength; 2420 header[0] = seqParamSetLength >> 8; 2421 header[1] = seqParamSetLength & 0xff; 2422 2423 // SPS NAL unit (sequence parameter length bytes) 2424 memcpy(&header[2], it->mData, seqParamSetLength); 2425 header += (2 + seqParamSetLength); 2426 } 2427 2428 // 8-bit nPictureParameterSets 2429 int nPictureParamSets = mPicParamSets.size(); 2430 header[0] = nPictureParamSets; 2431 header += 1; 2432 for (List<AVCParamSet>::iterator it = mPicParamSets.begin(); 2433 it != mPicParamSets.end(); ++it) { 2434 // 16-bit picture parameter set length 2435 uint16_t picParamSetLength = it->mLength; 2436 header[0] = picParamSetLength >> 8; 2437 header[1] = picParamSetLength & 0xff; 2438 2439 // PPS Nal unit (picture parameter set length bytes) 2440 memcpy(&header[2], it->mData, picParamSetLength); 2441 header += (2 + picParamSetLength); 2442 } 2443 2444 return OK; 2445} 2446 2447 2448status_t MPEG4Writer::Track::parseHEVCCodecSpecificData( 2449 const uint8_t *data, size_t size, HevcParameterSets ¶mSets) { 2450 2451 ALOGV("parseHEVCCodecSpecificData"); 2452 const uint8_t *tmp = data; 2453 const uint8_t *nextStartCode = data; 2454 size_t bytesLeft = size; 2455 while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 2456 nextStartCode = findNextNalStartCode(tmp + 4, bytesLeft - 4); 2457 status_t err = paramSets.addNalUnit(tmp + 4, (nextStartCode - tmp) - 4); 2458 if (err != OK) { 2459 return ERROR_MALFORMED; 2460 } 2461 2462 // Move on to find the next parameter set 2463 bytesLeft -= nextStartCode - tmp; 2464 tmp = nextStartCode; 2465 } 2466 2467 size_t csdSize = 23; 2468 const size_t numNalUnits = paramSets.getNumNalUnits(); 2469 for (size_t i = 0; i < ARRAY_SIZE(kMandatoryHevcNalUnitTypes); ++i) { 2470 int type = kMandatoryHevcNalUnitTypes[i]; 2471 size_t numParamSets = paramSets.getNumNalUnitsOfType(type); 2472 if (numParamSets == 0) { 2473 ALOGE("Cound not find NAL unit of type %d", type); 2474 return ERROR_MALFORMED; 2475 } 2476 } 2477 for (size_t i = 0; i < ARRAY_SIZE(kHevcNalUnitTypes); ++i) { 2478 int type = kHevcNalUnitTypes[i]; 2479 size_t numParamSets = paramSets.getNumNalUnitsOfType(type); 2480 if (numParamSets > 0xffff) { 2481 ALOGE("Too many seq parameter sets (%zu) found", numParamSets); 2482 return ERROR_MALFORMED; 2483 } 2484 csdSize += 3; 2485 for (size_t j = 0; j < numNalUnits; ++j) { 2486 if (paramSets.getType(j) != type) { 2487 continue; 2488 } 2489 csdSize += 2 + paramSets.getSize(j); 2490 } 2491 } 2492 mCodecSpecificDataSize = csdSize; 2493 return OK; 2494} 2495 2496status_t MPEG4Writer::Track::makeHEVCCodecSpecificData( 2497 const uint8_t *data, size_t size) { 2498 2499 if (mCodecSpecificData != NULL) { 2500 ALOGE("Already have codec specific data"); 2501 return ERROR_MALFORMED; 2502 } 2503 2504 if (size < 4) { 2505 ALOGE("Codec specific data length too short: %zu", size); 2506 return ERROR_MALFORMED; 2507 } 2508 2509 // Data is in the form of HEVCCodecSpecificData 2510 if (memcmp("\x00\x00\x00\x01", data, 4)) { 2511 return copyHEVCCodecSpecificData(data, size); 2512 } 2513 2514 HevcParameterSets paramSets; 2515 if (parseHEVCCodecSpecificData(data, size, paramSets) != OK) { 2516 ALOGE("failed parsing codec specific data"); 2517 return ERROR_MALFORMED; 2518 } 2519 2520 mCodecSpecificData = malloc(mCodecSpecificDataSize); 2521 if (mCodecSpecificData == NULL) { 2522 mCodecSpecificDataSize = 0; 2523 ALOGE("Failed allocating codec specific data"); 2524 return NO_MEMORY; 2525 } 2526 status_t err = paramSets.makeHvcc((uint8_t *)mCodecSpecificData, 2527 &mCodecSpecificDataSize, mOwner->useNalLengthFour() ? 4 : 2); 2528 if (err != OK) { 2529 ALOGE("failed constructing HVCC atom"); 2530 return err; 2531 } 2532 2533 return OK; 2534} 2535 2536/* 2537 * Updates the drift time from the audio track so that 2538 * the video track can get the updated drift time information 2539 * from the file writer. The fluctuation of the drift time of the audio 2540 * encoding path is smoothed out with a simple filter by giving a larger 2541 * weight to more recently drift time. The filter coefficients, 0.5 and 0.5, 2542 * are heuristically determined. 2543 */ 2544void MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) { 2545 int64_t driftTimeUs = 0; 2546 if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) { 2547 int64_t prevDriftTimeUs = mOwner->getDriftTimeUs(); 2548 int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1; 2549 mOwner->setDriftTimeUs(timeUs); 2550 } 2551} 2552 2553void MPEG4Writer::Track::dumpTimeStamps() { 2554 ALOGE("Dumping %s track's last 10 frames timestamp and frame type ", getTrackType()); 2555 std::string timeStampString; 2556 for (std::list<TimestampDebugHelperEntry>::iterator entry = mTimestampDebugHelper.begin(); 2557 entry != mTimestampDebugHelper.end(); ++entry) { 2558 timeStampString += "(" + std::to_string(entry->pts)+ 2559 "us, " + std::to_string(entry->dts) + "us " + entry->frameType + ") "; 2560 } 2561 ALOGE("%s", timeStampString.c_str()); 2562} 2563 2564status_t MPEG4Writer::Track::threadEntry() { 2565 int32_t count = 0; 2566 const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 2567 const bool hasMultipleTracks = (mOwner->numTracks() > 1); 2568 int64_t chunkTimestampUs = 0; 2569 int32_t nChunks = 0; 2570 int32_t nActualFrames = 0; // frames containing non-CSD data (non-0 length) 2571 int32_t nZeroLengthFrames = 0; 2572 int64_t lastTimestampUs = 0; // Previous sample time stamp 2573 int64_t lastDurationUs = 0; // Between the previous two samples 2574 int64_t currDurationTicks = 0; // Timescale based ticks 2575 int64_t lastDurationTicks = 0; // Timescale based ticks 2576 int32_t sampleCount = 1; // Sample count in the current stts table entry 2577 uint32_t previousSampleSize = 0; // Size of the previous sample 2578 int64_t previousPausedDurationUs = 0; 2579 int64_t timestampUs = 0; 2580 int64_t cttsOffsetTimeUs = 0; 2581 int64_t currCttsOffsetTimeTicks = 0; // Timescale based ticks 2582 int64_t lastCttsOffsetTimeTicks = -1; // Timescale based ticks 2583 int32_t cttsSampleCount = 0; // Sample count in the current ctts table entry 2584 uint32_t lastSamplesPerChunk = 0; 2585 2586 if (mIsAudio) { 2587 prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0); 2588 } else if (mIsVideo) { 2589 prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0); 2590 } else { 2591 prctl(PR_SET_NAME, (unsigned long)"MetadataTrackEncoding", 0, 0, 0); 2592 } 2593 2594 if (mOwner->isRealTimeRecording()) { 2595 androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); 2596 } 2597 2598 sp<MetaData> meta_data; 2599 2600 status_t err = OK; 2601 MediaBuffer *buffer; 2602 const char *trackName = getTrackType(); 2603 while (!mDone && (err = mSource->read(&buffer)) == OK) { 2604 if (buffer->range_length() == 0) { 2605 buffer->release(); 2606 buffer = NULL; 2607 ++nZeroLengthFrames; 2608 continue; 2609 } 2610 2611 // If the codec specific data has not been received yet, delay pause. 2612 // After the codec specific data is received, discard what we received 2613 // when the track is to be paused. 2614 if (mPaused && !mResumed) { 2615 buffer->release(); 2616 buffer = NULL; 2617 continue; 2618 } 2619 2620 ++count; 2621 2622 int32_t isCodecConfig; 2623 if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 2624 && isCodecConfig) { 2625 // if config format (at track addition) already had CSD, keep that 2626 // UNLESS we have not received any frames yet. 2627 // TODO: for now the entire CSD has to come in one frame for encoders, even though 2628 // they need to be spread out for decoders. 2629 if (mGotAllCodecSpecificData && nActualFrames > 0) { 2630 ALOGI("ignoring additional CSD for video track after first frame"); 2631 } else { 2632 mMeta = mSource->getFormat(); // get output format after format change 2633 status_t err; 2634 if (mIsAvc) { 2635 err = makeAVCCodecSpecificData( 2636 (const uint8_t *)buffer->data() 2637 + buffer->range_offset(), 2638 buffer->range_length()); 2639 } else if (mIsHevc) { 2640 err = makeHEVCCodecSpecificData( 2641 (const uint8_t *)buffer->data() 2642 + buffer->range_offset(), 2643 buffer->range_length()); 2644 } else if (mIsMPEG4) { 2645 copyCodecSpecificData((const uint8_t *)buffer->data() + buffer->range_offset(), 2646 buffer->range_length()); 2647 } 2648 } 2649 2650 buffer->release(); 2651 buffer = NULL; 2652 if (OK != err) { 2653 mSource->stop(); 2654 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_ERROR, 2655 mTrackId | MEDIA_RECORDER_TRACK_ERROR_GENERAL, err); 2656 break; 2657 } 2658 2659 mGotAllCodecSpecificData = true; 2660 continue; 2661 } 2662 2663 // Per-frame metadata sample's size must be smaller than max allowed. 2664 if (!mIsVideo && !mIsAudio && buffer->range_length() >= kMaxMetadataSize) { 2665 ALOGW("Buffer size is %zu. Maximum metadata buffer size is %lld for %s track", 2666 buffer->range_length(), (long long)kMaxMetadataSize, trackName); 2667 buffer->release(); 2668 mSource->stop(); 2669 mIsMalformed = true; 2670 break; 2671 } 2672 2673 ++nActualFrames; 2674 2675 // Make a deep copy of the MediaBuffer and Metadata and release 2676 // the original as soon as we can 2677 MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 2678 memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 2679 buffer->range_length()); 2680 copy->set_range(0, buffer->range_length()); 2681 meta_data = new MetaData(*buffer->meta_data().get()); 2682 buffer->release(); 2683 buffer = NULL; 2684 2685 if (mIsAvc || mIsHevc) StripStartcode(copy); 2686 2687 size_t sampleSize = copy->range_length(); 2688 if (mIsAvc || mIsHevc) { 2689 if (mOwner->useNalLengthFour()) { 2690 sampleSize += 4; 2691 } else { 2692 sampleSize += 2; 2693 } 2694 } 2695 2696 // Max file size or duration handling 2697 mMdatSizeBytes += sampleSize; 2698 updateTrackSizeEstimate(); 2699 2700 if (mOwner->exceedsFileSizeLimit()) { 2701 if (mOwner->switchFd() != OK) { 2702 ALOGW("Recorded file size exceeds limit %" PRId64 "bytes", 2703 mOwner->mMaxFileSizeLimitBytes); 2704 mSource->stop(); 2705 mOwner->notify( 2706 MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 2707 } else { 2708 ALOGV("%s Current recorded file size exceeds limit %" PRId64 "bytes. Switching output", 2709 getTrackType(), mOwner->mMaxFileSizeLimitBytes); 2710 } 2711 copy->release(); 2712 break; 2713 } 2714 2715 if (mOwner->exceedsFileDurationLimit()) { 2716 ALOGW("Recorded file duration exceeds limit %" PRId64 "microseconds", 2717 mOwner->mMaxFileDurationLimitUs); 2718 mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 2719 copy->release(); 2720 mSource->stop(); 2721 break; 2722 } 2723 2724 if (mOwner->approachingFileSizeLimit()) { 2725 mOwner->notifyApproachingLimit(); 2726 } 2727 2728 int32_t isSync = false; 2729 meta_data->findInt32(kKeyIsSyncFrame, &isSync); 2730 CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 2731 2732 // For video, skip the first several non-key frames until getting the first key frame. 2733 if (mIsVideo && !mGotStartKeyFrame && !isSync) { 2734 ALOGD("Video skip non-key frame"); 2735 copy->release(); 2736 continue; 2737 } 2738 if (mIsVideo && isSync) { 2739 mGotStartKeyFrame = true; 2740 } 2741//////////////////////////////////////////////////////////////////////////////// 2742 if (mStszTableEntries->count() == 0) { 2743 mFirstSampleTimeRealUs = systemTime() / 1000; 2744 mStartTimestampUs = timestampUs; 2745 mOwner->setStartTimestampUs(mStartTimestampUs); 2746 previousPausedDurationUs = mStartTimestampUs; 2747 } 2748 2749 if (mResumed) { 2750 int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs; 2751 if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) { 2752 copy->release(); 2753 mSource->stop(); 2754 mIsMalformed = true; 2755 break; 2756 } 2757 2758 int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs; 2759 if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) { 2760 copy->release(); 2761 mSource->stop(); 2762 mIsMalformed = true; 2763 break; 2764 } 2765 2766 previousPausedDurationUs += pausedDurationUs - lastDurationUs; 2767 mResumed = false; 2768 } 2769 TimestampDebugHelperEntry timestampDebugEntry; 2770 timestampUs -= previousPausedDurationUs; 2771 timestampDebugEntry.pts = timestampUs; 2772 if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) { 2773 copy->release(); 2774 mSource->stop(); 2775 mIsMalformed = true; 2776 break; 2777 } 2778 2779 if (mIsVideo) { 2780 /* 2781 * Composition time: timestampUs 2782 * Decoding time: decodingTimeUs 2783 * Composition time offset = composition time - decoding time 2784 */ 2785 int64_t decodingTimeUs; 2786 CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs)); 2787 decodingTimeUs -= previousPausedDurationUs; 2788 2789 // ensure non-negative, monotonic decoding time 2790 if (mLastDecodingTimeUs < 0) { 2791 decodingTimeUs = std::max((int64_t)0, decodingTimeUs); 2792 } else { 2793 // increase decoding time by at least the larger vaule of 1 tick and 2794 // 0.1 milliseconds. This needs to take into account the possible 2795 // delta adjustment in DurationTicks in below. 2796 decodingTimeUs = std::max(mLastDecodingTimeUs + 2797 std::max(100, divUp(1000000, mTimeScale)), decodingTimeUs); 2798 } 2799 2800 mLastDecodingTimeUs = decodingTimeUs; 2801 timestampDebugEntry.dts = decodingTimeUs; 2802 timestampDebugEntry.frameType = isSync ? "Key frame" : "Non-Key frame"; 2803 // Insert the timestamp into the mTimestampDebugHelper 2804 if (mTimestampDebugHelper.size() >= kTimestampDebugCount) { 2805 mTimestampDebugHelper.pop_front(); 2806 } 2807 mTimestampDebugHelper.push_back(timestampDebugEntry); 2808 2809 cttsOffsetTimeUs = 2810 timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs; 2811 if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) { 2812 copy->release(); 2813 mSource->stop(); 2814 mIsMalformed = true; 2815 break; 2816 } 2817 2818 timestampUs = decodingTimeUs; 2819 ALOGV("decoding time: %" PRId64 " and ctts offset time: %" PRId64, 2820 timestampUs, cttsOffsetTimeUs); 2821 2822 // Update ctts box table if necessary 2823 currCttsOffsetTimeTicks = 2824 (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL; 2825 if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) { 2826 copy->release(); 2827 mSource->stop(); 2828 mIsMalformed = true; 2829 break; 2830 } 2831 2832 if (mStszTableEntries->count() == 0) { 2833 // Force the first ctts table entry to have one single entry 2834 // so that we can do adjustment for the initial track start 2835 // time offset easily in writeCttsBox(). 2836 lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 2837 addOneCttsTableEntry(1, currCttsOffsetTimeTicks); 2838 cttsSampleCount = 0; // No sample in ctts box is pending 2839 } else { 2840 if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) { 2841 addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 2842 lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 2843 cttsSampleCount = 1; // One sample in ctts box is pending 2844 } else { 2845 ++cttsSampleCount; 2846 } 2847 } 2848 2849 // Update ctts time offset range 2850 if (mStszTableEntries->count() == 0) { 2851 mMinCttsOffsetTicks = currCttsOffsetTimeTicks; 2852 mMaxCttsOffsetTicks = currCttsOffsetTimeTicks; 2853 } else { 2854 if (currCttsOffsetTimeTicks > mMaxCttsOffsetTicks) { 2855 mMaxCttsOffsetTicks = currCttsOffsetTimeTicks; 2856 } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTicks) { 2857 mMinCttsOffsetTicks = currCttsOffsetTimeTicks; 2858 mMinCttsOffsetTimeUs = cttsOffsetTimeUs; 2859 } 2860 } 2861 } 2862 2863 if (mOwner->isRealTimeRecording()) { 2864 if (mIsAudio) { 2865 updateDriftTime(meta_data); 2866 } 2867 } 2868 2869 if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) { 2870 copy->release(); 2871 mSource->stop(); 2872 mIsMalformed = true; 2873 break; 2874 } 2875 2876 ALOGV("%s media time stamp: %" PRId64 " and previous paused duration %" PRId64, 2877 trackName, timestampUs, previousPausedDurationUs); 2878 if (timestampUs > mTrackDurationUs) { 2879 mTrackDurationUs = timestampUs; 2880 } 2881 2882 // We need to use the time scale based ticks, rather than the 2883 // timestamp itself to determine whether we have to use a new 2884 // stts entry, since we may have rounding errors. 2885 // The calculation is intended to reduce the accumulated 2886 // rounding errors. 2887 currDurationTicks = 2888 ((timestampUs * mTimeScale + 500000LL) / 1000000LL - 2889 (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL); 2890 if (currDurationTicks < 0ll) { 2891 ALOGE("do not support out of order frames (timestamp: %lld < last: %lld for %s track", 2892 (long long)timestampUs, (long long)lastTimestampUs, trackName); 2893 copy->release(); 2894 mSource->stop(); 2895 mIsMalformed = true; 2896 break; 2897 } 2898 2899 // if the duration is different for this sample, see if it is close enough to the previous 2900 // duration that we can fudge it and use the same value, to avoid filling the stts table 2901 // with lots of near-identical entries. 2902 // "close enough" here means that the current duration needs to be adjusted by less 2903 // than 0.1 milliseconds 2904 if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) { 2905 int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL 2906 + (mTimeScale / 2)) / mTimeScale; 2907 if (deltaUs > -100 && deltaUs < 100) { 2908 // use previous ticks, and adjust timestamp as if it was actually that number 2909 // of ticks 2910 currDurationTicks = lastDurationTicks; 2911 timestampUs += deltaUs; 2912 } 2913 } 2914 mStszTableEntries->add(htonl(sampleSize)); 2915 if (mStszTableEntries->count() > 2) { 2916 2917 // Force the first sample to have its own stts entry so that 2918 // we can adjust its value later to maintain the A/V sync. 2919 if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) { 2920 addOneSttsTableEntry(sampleCount, lastDurationTicks); 2921 sampleCount = 1; 2922 } else { 2923 ++sampleCount; 2924 } 2925 2926 } 2927 if (mSamplesHaveSameSize) { 2928 if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) { 2929 mSamplesHaveSameSize = false; 2930 } 2931 previousSampleSize = sampleSize; 2932 } 2933 ALOGV("%s timestampUs/lastTimestampUs: %" PRId64 "/%" PRId64, 2934 trackName, timestampUs, lastTimestampUs); 2935 lastDurationUs = timestampUs - lastTimestampUs; 2936 lastDurationTicks = currDurationTicks; 2937 lastTimestampUs = timestampUs; 2938 2939 if (isSync != 0) { 2940 addOneStssTableEntry(mStszTableEntries->count()); 2941 } 2942 2943 if (mTrackingProgressStatus) { 2944 if (mPreviousTrackTimeUs <= 0) { 2945 mPreviousTrackTimeUs = mStartTimestampUs; 2946 } 2947 trackProgressStatus(timestampUs); 2948 } 2949 if (!hasMultipleTracks) { 2950 off64_t offset = (mIsAvc || mIsHevc) ? mOwner->addMultipleLengthPrefixedSamples_l(copy) 2951 : mOwner->addSample_l(copy); 2952 2953 uint32_t count = (mOwner->use32BitFileOffset() 2954 ? mStcoTableEntries->count() 2955 : mCo64TableEntries->count()); 2956 2957 if (count == 0) { 2958 addChunkOffset(offset); 2959 } 2960 copy->release(); 2961 copy = NULL; 2962 continue; 2963 } 2964 2965 mChunkSamples.push_back(copy); 2966 if (interleaveDurationUs == 0) { 2967 addOneStscTableEntry(++nChunks, 1); 2968 bufferChunk(timestampUs); 2969 } else { 2970 if (chunkTimestampUs == 0) { 2971 chunkTimestampUs = timestampUs; 2972 } else { 2973 int64_t chunkDurationUs = timestampUs - chunkTimestampUs; 2974 if (chunkDurationUs > interleaveDurationUs) { 2975 if (chunkDurationUs > mMaxChunkDurationUs) { 2976 mMaxChunkDurationUs = chunkDurationUs; 2977 } 2978 ++nChunks; 2979 if (nChunks == 1 || // First chunk 2980 lastSamplesPerChunk != mChunkSamples.size()) { 2981 lastSamplesPerChunk = mChunkSamples.size(); 2982 addOneStscTableEntry(nChunks, lastSamplesPerChunk); 2983 } 2984 bufferChunk(timestampUs); 2985 chunkTimestampUs = timestampUs; 2986 } 2987 } 2988 } 2989 2990 } 2991 2992 if (isTrackMalFormed()) { 2993 dumpTimeStamps(); 2994 err = ERROR_MALFORMED; 2995 } 2996 2997 mOwner->trackProgressStatus(mTrackId, -1, err); 2998 2999 // Last chunk 3000 if (!hasMultipleTracks) { 3001 addOneStscTableEntry(1, mStszTableEntries->count()); 3002 } else if (!mChunkSamples.empty()) { 3003 addOneStscTableEntry(++nChunks, mChunkSamples.size()); 3004 bufferChunk(timestampUs); 3005 } 3006 3007 // We don't really know how long the last frame lasts, since 3008 // there is no frame time after it, just repeat the previous 3009 // frame's duration. 3010 if (mStszTableEntries->count() == 1) { 3011 lastDurationUs = 0; // A single sample's duration 3012 lastDurationTicks = 0; 3013 } else { 3014 ++sampleCount; // Count for the last sample 3015 } 3016 3017 if (mStszTableEntries->count() <= 2) { 3018 addOneSttsTableEntry(1, lastDurationTicks); 3019 if (sampleCount - 1 > 0) { 3020 addOneSttsTableEntry(sampleCount - 1, lastDurationTicks); 3021 } 3022 } else { 3023 addOneSttsTableEntry(sampleCount, lastDurationTicks); 3024 } 3025 3026 // The last ctts box may not have been written yet, and this 3027 // is to make sure that we write out the last ctts box. 3028 if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) { 3029 if (cttsSampleCount > 0) { 3030 addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 3031 } 3032 } 3033 3034 mTrackDurationUs += lastDurationUs; 3035 mReachedEOS = true; 3036 3037 sendTrackSummary(hasMultipleTracks); 3038 3039 ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s", 3040 count, nZeroLengthFrames, mStszTableEntries->count(), trackName); 3041 if (mIsAudio) { 3042 ALOGI("Audio track drift time: %" PRId64 " us", mOwner->getDriftTimeUs()); 3043 } 3044 3045 if (err == ERROR_END_OF_STREAM) { 3046 return OK; 3047 } 3048 return err; 3049} 3050 3051bool MPEG4Writer::Track::isTrackMalFormed() const { 3052 if (mIsMalformed) { 3053 return true; 3054 } 3055 3056 if (mStszTableEntries->count() == 0) { // no samples written 3057 ALOGE("The number of recorded samples is 0"); 3058 return true; 3059 } 3060 3061 if (mIsVideo && mStssTableEntries->count() == 0) { // no sync frames for video 3062 ALOGE("There are no sync frames for video track"); 3063 return true; 3064 } 3065 3066 if (OK != checkCodecSpecificData()) { // no codec specific data 3067 return true; 3068 } 3069 3070 return false; 3071} 3072 3073void MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) { 3074 3075 // Send track summary only if test mode is enabled. 3076 if (!isTestModeEnabled()) { 3077 return; 3078 } 3079 3080 int trackNum = (mTrackId << 28); 3081 3082 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 3083 trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE, 3084 mIsAudio ? 0: 1); 3085 3086 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 3087 trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS, 3088 mTrackDurationUs / 1000); 3089 3090 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 3091 trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES, 3092 mStszTableEntries->count()); 3093 3094 { 3095 // The system delay time excluding the requested initial delay that 3096 // is used to eliminate the recording sound. 3097 int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 3098 if (startTimeOffsetUs < 0) { // Start time offset was not set 3099 startTimeOffsetUs = kInitialDelayTimeUs; 3100 } 3101 int64_t initialDelayUs = 3102 mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs; 3103 3104 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 3105 trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS, 3106 (initialDelayUs) / 1000); 3107 } 3108 3109 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 3110 trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES, 3111 mMdatSizeBytes / 1024); 3112 3113 if (hasMultipleTracks) { 3114 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 3115 trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS, 3116 mMaxChunkDurationUs / 1000); 3117 3118 int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 3119 if (mStartTimestampUs != moovStartTimeUs) { 3120 int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 3121 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 3122 trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS, 3123 startTimeOffsetUs / 1000); 3124 } 3125 } 3126} 3127 3128void MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) { 3129 ALOGV("trackProgressStatus: %" PRId64 " us", timeUs); 3130 3131 if (mTrackEveryTimeDurationUs > 0 && 3132 timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 3133 ALOGV("Fire time tracking progress status at %" PRId64 " us", timeUs); 3134 mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err); 3135 mPreviousTrackTimeUs = timeUs; 3136 } 3137} 3138 3139void MPEG4Writer::trackProgressStatus( 3140 size_t trackId, int64_t timeUs, status_t err) { 3141 Mutex::Autolock lock(mLock); 3142 int32_t trackNum = (trackId << 28); 3143 3144 // Error notification 3145 // Do not consider ERROR_END_OF_STREAM an error 3146 if (err != OK && err != ERROR_END_OF_STREAM) { 3147 notify(MEDIA_RECORDER_TRACK_EVENT_ERROR, 3148 trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL, 3149 err); 3150 return; 3151 } 3152 3153 if (timeUs == -1) { 3154 // Send completion notification 3155 notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 3156 trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, 3157 err); 3158 } else { 3159 // Send progress status 3160 notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 3161 trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME, 3162 timeUs / 1000); 3163 } 3164} 3165 3166void MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) { 3167 ALOGV("setDriftTimeUs: %" PRId64 " us", driftTimeUs); 3168 Mutex::Autolock autolock(mLock); 3169 mDriftTimeUs = driftTimeUs; 3170} 3171 3172int64_t MPEG4Writer::getDriftTimeUs() { 3173 ALOGV("getDriftTimeUs: %" PRId64 " us", mDriftTimeUs); 3174 Mutex::Autolock autolock(mLock); 3175 return mDriftTimeUs; 3176} 3177 3178bool MPEG4Writer::isRealTimeRecording() const { 3179 return mIsRealTimeRecording; 3180} 3181 3182bool MPEG4Writer::useNalLengthFour() { 3183 return mUse4ByteNalLength; 3184} 3185 3186void MPEG4Writer::Track::bufferChunk(int64_t timestampUs) { 3187 ALOGV("bufferChunk"); 3188 3189 Chunk chunk(this, timestampUs, mChunkSamples); 3190 mOwner->bufferChunk(chunk); 3191 mChunkSamples.clear(); 3192} 3193 3194int64_t MPEG4Writer::Track::getDurationUs() const { 3195 return mTrackDurationUs + getStartTimeOffsetTimeUs(); 3196} 3197 3198int64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 3199 return mEstimatedTrackSizeBytes; 3200} 3201 3202status_t MPEG4Writer::Track::checkCodecSpecificData() const { 3203 const char *mime; 3204 CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 3205 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) || 3206 !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) || 3207 !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime) || 3208 !strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) { 3209 if (!mCodecSpecificData || 3210 mCodecSpecificDataSize <= 0) { 3211 ALOGE("Missing codec specific data"); 3212 return ERROR_MALFORMED; 3213 } 3214 } else { 3215 if (mCodecSpecificData || 3216 mCodecSpecificDataSize > 0) { 3217 ALOGE("Unexepected codec specific data found"); 3218 return ERROR_MALFORMED; 3219 } 3220 } 3221 return OK; 3222} 3223 3224const char *MPEG4Writer::Track::getTrackType() const { 3225 return mIsAudio ? "Audio" : (mIsVideo ? "Video" : "Metadata"); 3226} 3227 3228void MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) { 3229 uint32_t now = getMpeg4Time(); 3230 mOwner->beginBox("trak"); 3231 writeTkhdBox(now); 3232 mOwner->beginBox("mdia"); 3233 writeMdhdBox(now); 3234 writeHdlrBox(); 3235 mOwner->beginBox("minf"); 3236 if (mIsAudio) { 3237 writeSmhdBox(); 3238 } else if (mIsVideo) { 3239 writeVmhdBox(); 3240 } else { 3241 writeNmhdBox(); 3242 } 3243 writeDinfBox(); 3244 writeStblBox(use32BitOffset); 3245 mOwner->endBox(); // minf 3246 mOwner->endBox(); // mdia 3247 mOwner->endBox(); // trak 3248} 3249 3250int64_t MPEG4Writer::Track::getMinCttsOffsetTimeUs() { 3251 // For video tracks with ctts table, this should return the minimum ctts 3252 // offset in the table. For non-video tracks or video tracks without ctts 3253 // table, this will return kMaxCttsOffsetTimeUs. 3254 if (mMinCttsOffsetTicks == mMaxCttsOffsetTicks) { 3255 return kMaxCttsOffsetTimeUs; 3256 } 3257 return mMinCttsOffsetTimeUs; 3258} 3259 3260void MPEG4Writer::Track::writeStblBox(bool use32BitOffset) { 3261 mOwner->beginBox("stbl"); 3262 mOwner->beginBox("stsd"); 3263 mOwner->writeInt32(0); // version=0, flags=0 3264 mOwner->writeInt32(1); // entry count 3265 if (mIsAudio) { 3266 writeAudioFourCCBox(); 3267 } else if (mIsVideo) { 3268 writeVideoFourCCBox(); 3269 } else { 3270 writeMetadataFourCCBox(); 3271 } 3272 mOwner->endBox(); // stsd 3273 writeSttsBox(); 3274 if (mIsVideo) { 3275 writeCttsBox(); 3276 writeStssBox(); 3277 } 3278 writeStszBox(); 3279 writeStscBox(); 3280 writeStcoBox(use32BitOffset); 3281 mOwner->endBox(); // stbl 3282} 3283 3284void MPEG4Writer::Track::writeMetadataFourCCBox() { 3285 const char *mime; 3286 bool success = mMeta->findCString(kKeyMIMEType, &mime); 3287 CHECK(success); 3288 const char *fourcc = getFourCCForMime(mime); 3289 if (fourcc == NULL) { 3290 ALOGE("Unknown mime type '%s'.", mime); 3291 TRESPASS(); 3292 } 3293 mOwner->beginBox(fourcc); // TextMetaDataSampleEntry 3294 mOwner->writeCString(mime); // metadata mime_format 3295 mOwner->endBox(); // mett 3296} 3297 3298void MPEG4Writer::Track::writeVideoFourCCBox() { 3299 const char *mime; 3300 bool success = mMeta->findCString(kKeyMIMEType, &mime); 3301 CHECK(success); 3302 const char *fourcc = getFourCCForMime(mime); 3303 if (fourcc == NULL) { 3304 ALOGE("Unknown mime type '%s'.", mime); 3305 TRESPASS(); 3306 } 3307 3308 mOwner->beginBox(fourcc); // video format 3309 mOwner->writeInt32(0); // reserved 3310 mOwner->writeInt16(0); // reserved 3311 mOwner->writeInt16(1); // data ref index 3312 mOwner->writeInt16(0); // predefined 3313 mOwner->writeInt16(0); // reserved 3314 mOwner->writeInt32(0); // predefined 3315 mOwner->writeInt32(0); // predefined 3316 mOwner->writeInt32(0); // predefined 3317 3318 int32_t width, height; 3319 success = mMeta->findInt32(kKeyWidth, &width); 3320 success = success && mMeta->findInt32(kKeyHeight, &height); 3321 CHECK(success); 3322 3323 mOwner->writeInt16(width); 3324 mOwner->writeInt16(height); 3325 mOwner->writeInt32(0x480000); // horiz resolution 3326 mOwner->writeInt32(0x480000); // vert resolution 3327 mOwner->writeInt32(0); // reserved 3328 mOwner->writeInt16(1); // frame count 3329 mOwner->writeInt8(0); // compressor string length 3330 mOwner->write(" ", 31); 3331 mOwner->writeInt16(0x18); // depth 3332 mOwner->writeInt16(-1); // predefined 3333 3334 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 3335 writeMp4vEsdsBox(); 3336 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 3337 writeD263Box(); 3338 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 3339 writeAvccBox(); 3340 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) { 3341 writeHvccBox(); 3342 } 3343 3344 writePaspBox(); 3345 writeColrBox(); 3346 mOwner->endBox(); // mp4v, s263 or avc1 3347} 3348 3349void MPEG4Writer::Track::writeColrBox() { 3350 ColorAspects aspects; 3351 memset(&aspects, 0, sizeof(aspects)); 3352 // TRICKY: using | instead of || because we want to execute all findInt32-s 3353 if (mMeta->findInt32(kKeyColorPrimaries, (int32_t*)&aspects.mPrimaries) 3354 | mMeta->findInt32(kKeyTransferFunction, (int32_t*)&aspects.mTransfer) 3355 | mMeta->findInt32(kKeyColorMatrix, (int32_t*)&aspects.mMatrixCoeffs) 3356 | mMeta->findInt32(kKeyColorRange, (int32_t*)&aspects.mRange)) { 3357 int32_t primaries, transfer, coeffs; 3358 bool fullRange; 3359 ColorUtils::convertCodecColorAspectsToIsoAspects( 3360 aspects, &primaries, &transfer, &coeffs, &fullRange); 3361 mOwner->beginBox("colr"); 3362 mOwner->writeFourcc("nclx"); 3363 mOwner->writeInt16(primaries); 3364 mOwner->writeInt16(transfer); 3365 mOwner->writeInt16(coeffs); 3366 mOwner->writeInt8(int8_t(fullRange ? 0x80 : 0x0)); 3367 mOwner->endBox(); // colr 3368 } 3369} 3370 3371void MPEG4Writer::Track::writeAudioFourCCBox() { 3372 const char *mime; 3373 bool success = mMeta->findCString(kKeyMIMEType, &mime); 3374 CHECK(success); 3375 const char *fourcc = getFourCCForMime(mime); 3376 if (fourcc == NULL) { 3377 ALOGE("Unknown mime type '%s'.", mime); 3378 TRESPASS(); 3379 } 3380 3381 mOwner->beginBox(fourcc); // audio format 3382 mOwner->writeInt32(0); // reserved 3383 mOwner->writeInt16(0); // reserved 3384 mOwner->writeInt16(0x1); // data ref index 3385 mOwner->writeInt32(0); // reserved 3386 mOwner->writeInt32(0); // reserved 3387 int32_t nChannels; 3388 CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 3389 mOwner->writeInt16(nChannels); // channel count 3390 mOwner->writeInt16(16); // sample size 3391 mOwner->writeInt16(0); // predefined 3392 mOwner->writeInt16(0); // reserved 3393 3394 int32_t samplerate; 3395 success = mMeta->findInt32(kKeySampleRate, &samplerate); 3396 CHECK(success); 3397 mOwner->writeInt32(samplerate << 16); 3398 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 3399 writeMp4aEsdsBox(); 3400 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) || 3401 !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 3402 writeDamrBox(); 3403 } 3404 mOwner->endBox(); 3405} 3406 3407void MPEG4Writer::Track::writeMp4aEsdsBox() { 3408 mOwner->beginBox("esds"); 3409 CHECK(mCodecSpecificData); 3410 CHECK_GT(mCodecSpecificDataSize, 0u); 3411 3412 // Make sure all sizes encode to a single byte. 3413 CHECK_LT(mCodecSpecificDataSize + 23, 128u); 3414 3415 mOwner->writeInt32(0); // version=0, flags=0 3416 mOwner->writeInt8(0x03); // ES_DescrTag 3417 mOwner->writeInt8(23 + mCodecSpecificDataSize); 3418 mOwner->writeInt16(0x0000);// ES_ID 3419 mOwner->writeInt8(0x00); 3420 3421 mOwner->writeInt8(0x04); // DecoderConfigDescrTag 3422 mOwner->writeInt8(15 + mCodecSpecificDataSize); 3423 mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 3424 mOwner->writeInt8(0x15); // streamType AudioStream 3425 3426 mOwner->writeInt16(0x03); // XXX 3427 mOwner->writeInt8(0x00); // buffer size 24-bit (0x300) 3428 3429 int32_t avgBitrate = 0; 3430 (void)mMeta->findInt32(kKeyBitRate, &avgBitrate); 3431 int32_t maxBitrate = 0; 3432 (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate); 3433 mOwner->writeInt32(maxBitrate); 3434 mOwner->writeInt32(avgBitrate); 3435 3436 mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 3437 mOwner->writeInt8(mCodecSpecificDataSize); 3438 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 3439 3440 static const uint8_t kData2[] = { 3441 0x06, // SLConfigDescriptorTag 3442 0x01, 3443 0x02 3444 }; 3445 mOwner->write(kData2, sizeof(kData2)); 3446 3447 mOwner->endBox(); // esds 3448} 3449 3450void MPEG4Writer::Track::writeMp4vEsdsBox() { 3451 CHECK(mCodecSpecificData); 3452 CHECK_GT(mCodecSpecificDataSize, 0u); 3453 3454 // Make sure all sizes encode to a single byte. 3455 CHECK_LT(23 + mCodecSpecificDataSize, 128u); 3456 3457 mOwner->beginBox("esds"); 3458 3459 mOwner->writeInt32(0); // version=0, flags=0 3460 3461 mOwner->writeInt8(0x03); // ES_DescrTag 3462 mOwner->writeInt8(23 + mCodecSpecificDataSize); 3463 mOwner->writeInt16(0x0000); // ES_ID 3464 mOwner->writeInt8(0x1f); 3465 3466 mOwner->writeInt8(0x04); // DecoderConfigDescrTag 3467 mOwner->writeInt8(15 + mCodecSpecificDataSize); 3468 mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 3469 mOwner->writeInt8(0x11); // streamType VisualStream 3470 3471 static const uint8_t kData[] = { 3472 0x01, 0x77, 0x00, // buffer size 96000 bytes 3473 }; 3474 mOwner->write(kData, sizeof(kData)); 3475 3476 int32_t avgBitrate = 0; 3477 (void)mMeta->findInt32(kKeyBitRate, &avgBitrate); 3478 int32_t maxBitrate = 0; 3479 (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate); 3480 mOwner->writeInt32(maxBitrate); 3481 mOwner->writeInt32(avgBitrate); 3482 3483 mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 3484 3485 mOwner->writeInt8(mCodecSpecificDataSize); 3486 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 3487 3488 static const uint8_t kData2[] = { 3489 0x06, // SLConfigDescriptorTag 3490 0x01, 3491 0x02 3492 }; 3493 mOwner->write(kData2, sizeof(kData2)); 3494 3495 mOwner->endBox(); // esds 3496} 3497 3498void MPEG4Writer::Track::writeTkhdBox(uint32_t now) { 3499 mOwner->beginBox("tkhd"); 3500 // Flags = 7 to indicate that the track is enabled, and 3501 // part of the presentation 3502 mOwner->writeInt32(0x07); // version=0, flags=7 3503 mOwner->writeInt32(now); // creation time 3504 mOwner->writeInt32(now); // modification time 3505 mOwner->writeInt32(mTrackId); // track id starts with 1 3506 mOwner->writeInt32(0); // reserved 3507 int64_t trakDurationUs = getDurationUs(); 3508 int32_t mvhdTimeScale = mOwner->getTimeScale(); 3509 int32_t tkhdDuration = 3510 (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 3511 mOwner->writeInt32(tkhdDuration); // in mvhd timescale 3512 mOwner->writeInt32(0); // reserved 3513 mOwner->writeInt32(0); // reserved 3514 mOwner->writeInt16(0); // layer 3515 mOwner->writeInt16(0); // alternate group 3516 mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume 3517 mOwner->writeInt16(0); // reserved 3518 3519 mOwner->writeCompositionMatrix(mRotation); // matrix 3520 3521 if (!mIsVideo) { 3522 mOwner->writeInt32(0); 3523 mOwner->writeInt32(0); 3524 } else { 3525 int32_t width, height; 3526 bool success = mMeta->findInt32(kKeyDisplayWidth, &width); 3527 success = success && mMeta->findInt32(kKeyDisplayHeight, &height); 3528 3529 // Use width/height if display width/height are not present. 3530 if (!success) { 3531 success = mMeta->findInt32(kKeyWidth, &width); 3532 success = success && mMeta->findInt32(kKeyHeight, &height); 3533 } 3534 CHECK(success); 3535 3536 mOwner->writeInt32(width << 16); // 32-bit fixed-point value 3537 mOwner->writeInt32(height << 16); // 32-bit fixed-point value 3538 } 3539 mOwner->endBox(); // tkhd 3540} 3541 3542void MPEG4Writer::Track::writeVmhdBox() { 3543 mOwner->beginBox("vmhd"); 3544 mOwner->writeInt32(0x01); // version=0, flags=1 3545 mOwner->writeInt16(0); // graphics mode 3546 mOwner->writeInt16(0); // opcolor 3547 mOwner->writeInt16(0); 3548 mOwner->writeInt16(0); 3549 mOwner->endBox(); 3550} 3551 3552void MPEG4Writer::Track::writeSmhdBox() { 3553 mOwner->beginBox("smhd"); 3554 mOwner->writeInt32(0); // version=0, flags=0 3555 mOwner->writeInt16(0); // balance 3556 mOwner->writeInt16(0); // reserved 3557 mOwner->endBox(); 3558} 3559 3560void MPEG4Writer::Track::writeNmhdBox() { 3561 mOwner->beginBox("nmhd"); 3562 mOwner->writeInt32(0); // version=0, flags=0 3563 mOwner->endBox(); 3564} 3565 3566void MPEG4Writer::Track::writeHdlrBox() { 3567 mOwner->beginBox("hdlr"); 3568 mOwner->writeInt32(0); // version=0, flags=0 3569 mOwner->writeInt32(0); // component type: should be mhlr 3570 mOwner->writeFourcc(mIsAudio ? "soun" : (mIsVideo ? "vide" : "meta")); // component subtype 3571 mOwner->writeInt32(0); // reserved 3572 mOwner->writeInt32(0); // reserved 3573 mOwner->writeInt32(0); // reserved 3574 // Removing "r" for the name string just makes the string 4 byte aligned 3575 mOwner->writeCString(mIsAudio ? "SoundHandle": (mIsVideo ? "VideoHandle" : "MetadHandle")); 3576 mOwner->endBox(); 3577} 3578 3579void MPEG4Writer::Track::writeMdhdBox(uint32_t now) { 3580 int64_t trakDurationUs = getDurationUs(); 3581 int64_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6; 3582 mOwner->beginBox("mdhd"); 3583 3584 if (mdhdDuration > UINT32_MAX) { 3585 mOwner->writeInt32((1 << 24)); // version=1, flags=0 3586 mOwner->writeInt64((int64_t)now); // creation time 3587 mOwner->writeInt64((int64_t)now); // modification time 3588 mOwner->writeInt32(mTimeScale); // media timescale 3589 mOwner->writeInt64(mdhdDuration); // media timescale 3590 } else { 3591 mOwner->writeInt32(0); // version=0, flags=0 3592 mOwner->writeInt32(now); // creation time 3593 mOwner->writeInt32(now); // modification time 3594 mOwner->writeInt32(mTimeScale); // media timescale 3595 mOwner->writeInt32((int32_t)mdhdDuration); // use media timescale 3596 } 3597 // Language follows the three letter standard ISO-639-2/T 3598 // 'e', 'n', 'g' for "English", for instance. 3599 // Each character is packed as the difference between its ASCII value and 0x60. 3600 // For "English", these are 00101, 01110, 00111. 3601 // XXX: Where is the padding bit located: 0x15C7? 3602 const char *lang = NULL; 3603 int16_t langCode = 0; 3604 if (mMeta->findCString(kKeyMediaLanguage, &lang) && lang && strnlen(lang, 3) > 2) { 3605 langCode = ((lang[0] & 0x1f) << 10) | ((lang[1] & 0x1f) << 5) | (lang[2] & 0x1f); 3606 } 3607 mOwner->writeInt16(langCode); // language code 3608 mOwner->writeInt16(0); // predefined 3609 mOwner->endBox(); 3610} 3611 3612void MPEG4Writer::Track::writeDamrBox() { 3613 // 3gpp2 Spec AMRSampleEntry fields 3614 mOwner->beginBox("damr"); 3615 mOwner->writeCString(" "); // vendor: 4 bytes 3616 mOwner->writeInt8(0); // decoder version 3617 mOwner->writeInt16(0x83FF); // mode set: all enabled 3618 mOwner->writeInt8(0); // mode change period 3619 mOwner->writeInt8(1); // frames per sample 3620 mOwner->endBox(); 3621} 3622 3623void MPEG4Writer::Track::writeUrlBox() { 3624 // The table index here refers to the sample description index 3625 // in the sample table entries. 3626 mOwner->beginBox("url "); 3627 mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 3628 mOwner->endBox(); // url 3629} 3630 3631void MPEG4Writer::Track::writeDrefBox() { 3632 mOwner->beginBox("dref"); 3633 mOwner->writeInt32(0); // version=0, flags=0 3634 mOwner->writeInt32(1); // entry count (either url or urn) 3635 writeUrlBox(); 3636 mOwner->endBox(); // dref 3637} 3638 3639void MPEG4Writer::Track::writeDinfBox() { 3640 mOwner->beginBox("dinf"); 3641 writeDrefBox(); 3642 mOwner->endBox(); // dinf 3643} 3644 3645void MPEG4Writer::Track::writeAvccBox() { 3646 CHECK(mCodecSpecificData); 3647 CHECK_GE(mCodecSpecificDataSize, 5u); 3648 3649 // Patch avcc's lengthSize field to match the number 3650 // of bytes we use to indicate the size of a nal unit. 3651 uint8_t *ptr = (uint8_t *)mCodecSpecificData; 3652 ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); 3653 mOwner->beginBox("avcC"); 3654 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 3655 mOwner->endBox(); // avcC 3656} 3657 3658 3659void MPEG4Writer::Track::writeHvccBox() { 3660 CHECK(mCodecSpecificData); 3661 CHECK_GE(mCodecSpecificDataSize, 5u); 3662 3663 // Patch avcc's lengthSize field to match the number 3664 // of bytes we use to indicate the size of a nal unit. 3665 uint8_t *ptr = (uint8_t *)mCodecSpecificData; 3666 ptr[21] = (ptr[21] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); 3667 mOwner->beginBox("hvcC"); 3668 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 3669 mOwner->endBox(); // hvcC 3670} 3671 3672void MPEG4Writer::Track::writeD263Box() { 3673 mOwner->beginBox("d263"); 3674 mOwner->writeInt32(0); // vendor 3675 mOwner->writeInt8(0); // decoder version 3676 mOwner->writeInt8(10); // level: 10 3677 mOwner->writeInt8(0); // profile: 0 3678 mOwner->endBox(); // d263 3679} 3680 3681// This is useful if the pixel is not square 3682void MPEG4Writer::Track::writePaspBox() { 3683 mOwner->beginBox("pasp"); 3684 mOwner->writeInt32(1 << 16); // hspacing 3685 mOwner->writeInt32(1 << 16); // vspacing 3686 mOwner->endBox(); // pasp 3687} 3688 3689int64_t MPEG4Writer::Track::getStartTimeOffsetTimeUs() const { 3690 int64_t trackStartTimeOffsetUs = 0; 3691 int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 3692 if (mStartTimestampUs != -1 && mStartTimestampUs != moovStartTimeUs) { 3693 CHECK_GT(mStartTimestampUs, moovStartTimeUs); 3694 trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 3695 } 3696 return trackStartTimeOffsetUs; 3697} 3698 3699int32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const { 3700 return (getStartTimeOffsetTimeUs() * mTimeScale + 500000LL) / 1000000LL; 3701} 3702 3703void MPEG4Writer::Track::writeSttsBox() { 3704 mOwner->beginBox("stts"); 3705 mOwner->writeInt32(0); // version=0, flags=0 3706 if (mMinCttsOffsetTicks == mMaxCttsOffsetTicks) { 3707 // For non-vdeio tracks or video tracks without ctts table, 3708 // adjust duration of first sample for tracks to account for 3709 // first sample not starting at the media start time. 3710 // TODO: consider signaling this using some offset 3711 // as this is not quite correct. 3712 uint32_t duration; 3713 CHECK(mSttsTableEntries->get(duration, 1)); 3714 duration = htonl(duration); // Back to host byte order 3715 mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1); 3716 } 3717 mSttsTableEntries->write(mOwner); 3718 mOwner->endBox(); // stts 3719} 3720 3721void MPEG4Writer::Track::writeCttsBox() { 3722 // There is no B frame at all 3723 if (mMinCttsOffsetTicks == mMaxCttsOffsetTicks) { 3724 return; 3725 } 3726 3727 // Do not write ctts box when there is no need to have it. 3728 if (mCttsTableEntries->count() == 0) { 3729 return; 3730 } 3731 3732 ALOGV("ctts box has %d entries with range [%" PRId64 ", %" PRId64 "]", 3733 mCttsTableEntries->count(), mMinCttsOffsetTicks, mMaxCttsOffsetTicks); 3734 3735 mOwner->beginBox("ctts"); 3736 mOwner->writeInt32(0); // version=0, flags=0 3737 int64_t deltaTimeUs = kMaxCttsOffsetTimeUs - getStartTimeOffsetTimeUs(); 3738 int64_t delta = (deltaTimeUs * mTimeScale + 500000LL) / 1000000LL; 3739 mCttsTableEntries->adjustEntries([delta](size_t /* ix */, uint32_t (&value)[2]) { 3740 // entries are <count, ctts> pairs; adjust only ctts 3741 uint32_t duration = htonl(value[1]); // back to host byte order 3742 // Prevent overflow and underflow 3743 if (delta > duration) { 3744 duration = 0; 3745 } else if (delta < 0 && UINT32_MAX + delta < duration) { 3746 duration = UINT32_MAX; 3747 } else { 3748 duration -= delta; 3749 } 3750 value[1] = htonl(duration); 3751 }); 3752 mCttsTableEntries->write(mOwner); 3753 mOwner->endBox(); // ctts 3754} 3755 3756void MPEG4Writer::Track::writeStssBox() { 3757 mOwner->beginBox("stss"); 3758 mOwner->writeInt32(0); // version=0, flags=0 3759 mStssTableEntries->write(mOwner); 3760 mOwner->endBox(); // stss 3761} 3762 3763void MPEG4Writer::Track::writeStszBox() { 3764 mOwner->beginBox("stsz"); 3765 mOwner->writeInt32(0); // version=0, flags=0 3766 mOwner->writeInt32(0); 3767 mStszTableEntries->write(mOwner); 3768 mOwner->endBox(); // stsz 3769} 3770 3771void MPEG4Writer::Track::writeStscBox() { 3772 mOwner->beginBox("stsc"); 3773 mOwner->writeInt32(0); // version=0, flags=0 3774 mStscTableEntries->write(mOwner); 3775 mOwner->endBox(); // stsc 3776} 3777 3778void MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) { 3779 mOwner->beginBox(use32BitOffset? "stco": "co64"); 3780 mOwner->writeInt32(0); // version=0, flags=0 3781 if (use32BitOffset) { 3782 mStcoTableEntries->write(mOwner); 3783 } else { 3784 mCo64TableEntries->write(mOwner); 3785 } 3786 mOwner->endBox(); // stco or co64 3787} 3788 3789void MPEG4Writer::writeUdtaBox() { 3790 beginBox("udta"); 3791 writeGeoDataBox(); 3792 endBox(); 3793} 3794 3795void MPEG4Writer::writeHdlr() { 3796 beginBox("hdlr"); 3797 writeInt32(0); // Version, Flags 3798 writeInt32(0); // Predefined 3799 writeFourcc("mdta"); 3800 writeInt32(0); // Reserved[0] 3801 writeInt32(0); // Reserved[1] 3802 writeInt32(0); // Reserved[2] 3803 writeInt8(0); // Name (empty) 3804 endBox(); 3805} 3806 3807void MPEG4Writer::writeKeys() { 3808 size_t count = mMetaKeys->countEntries(); 3809 3810 beginBox("keys"); 3811 writeInt32(0); // Version, Flags 3812 writeInt32(count); // Entry_count 3813 for (size_t i = 0; i < count; i++) { 3814 AMessage::Type type; 3815 const char *key = mMetaKeys->getEntryNameAt(i, &type); 3816 size_t n = strlen(key); 3817 writeInt32(n + 8); 3818 writeFourcc("mdta"); 3819 write(key, n); // write without the \0 3820 } 3821 endBox(); 3822} 3823 3824void MPEG4Writer::writeIlst() { 3825 size_t count = mMetaKeys->countEntries(); 3826 3827 beginBox("ilst"); 3828 for (size_t i = 0; i < count; i++) { 3829 beginBox(i + 1); // key id (1-based) 3830 beginBox("data"); 3831 AMessage::Type type; 3832 const char *key = mMetaKeys->getEntryNameAt(i, &type); 3833 switch (type) { 3834 case AMessage::kTypeString: 3835 { 3836 AString val; 3837 CHECK(mMetaKeys->findString(key, &val)); 3838 writeInt32(1); // type = UTF8 3839 writeInt32(0); // default country/language 3840 write(val.c_str(), strlen(val.c_str())); // write without \0 3841 break; 3842 } 3843 3844 case AMessage::kTypeFloat: 3845 { 3846 float val; 3847 CHECK(mMetaKeys->findFloat(key, &val)); 3848 writeInt32(23); // type = float32 3849 writeInt32(0); // default country/language 3850 writeInt32(*reinterpret_cast<int32_t *>(&val)); 3851 break; 3852 } 3853 3854 case AMessage::kTypeInt32: 3855 { 3856 int32_t val; 3857 CHECK(mMetaKeys->findInt32(key, &val)); 3858 writeInt32(67); // type = signed int32 3859 writeInt32(0); // default country/language 3860 writeInt32(val); 3861 break; 3862 } 3863 3864 default: 3865 { 3866 ALOGW("Unsupported key type, writing 0 instead"); 3867 writeInt32(77); // type = unsigned int32 3868 writeInt32(0); // default country/language 3869 writeInt32(0); 3870 break; 3871 } 3872 } 3873 endBox(); // data 3874 endBox(); // key id 3875 } 3876 endBox(); // ilst 3877} 3878 3879void MPEG4Writer::writeMetaBox() { 3880 size_t count = mMetaKeys->countEntries(); 3881 if (count == 0) { 3882 return; 3883 } 3884 3885 beginBox("meta"); 3886 writeHdlr(); 3887 writeKeys(); 3888 writeIlst(); 3889 endBox(); 3890} 3891 3892/* 3893 * Geodata is stored according to ISO-6709 standard. 3894 */ 3895void MPEG4Writer::writeGeoDataBox() { 3896 beginBox("\xA9xyz"); 3897 /* 3898 * For historical reasons, any user data start 3899 * with "\0xA9", must be followed by its assoicated 3900 * language code. 3901 * 0x0012: text string length 3902 * 0x15c7: lang (locale) code: en 3903 */ 3904 writeInt32(0x001215c7); 3905 writeLatitude(mLatitudex10000); 3906 writeLongitude(mLongitudex10000); 3907 writeInt8(0x2F); 3908 endBox(); 3909} 3910 3911} // namespace android 3912