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