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