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