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