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