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