MPEG4Writer.cpp revision 1f90c4b3fda9dbd2824d67fd679f850572f114dc
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#include <utils/Log.h> 20 21#include <arpa/inet.h> 22 23#include <ctype.h> 24#include <pthread.h> 25 26#include <media/stagefright/MPEG4Writer.h> 27#include <media/stagefright/MediaBuffer.h> 28#include <media/stagefright/MetaData.h> 29#include <media/stagefright/MediaDebug.h> 30#include <media/stagefright/MediaDefs.h> 31#include <media/stagefright/MediaErrors.h> 32#include <media/stagefright/MediaSource.h> 33#include <media/stagefright/Utils.h> 34#include <media/mediarecorder.h> 35#include <cutils/properties.h> 36 37#include "include/ESDS.h" 38 39namespace android { 40 41static const int64_t kMax32BitFileSize = 0x007fffffffLL; 42static const uint8_t kNalUnitTypeSeqParamSet = 0x07; 43static const uint8_t kNalUnitTypePicParamSet = 0x08; 44 45class MPEG4Writer::Track { 46public: 47 Track(MPEG4Writer *owner, const sp<MediaSource> &source); 48 49 ~Track(); 50 51 status_t start(MetaData *params); 52 status_t stop(); 53 status_t pause(); 54 bool reachedEOS(); 55 56 int64_t getDurationUs() const; 57 int64_t getEstimatedTrackSizeBytes() const; 58 void writeTrackHeader(int32_t trackID, bool use32BitOffset = true); 59 void bufferChunk(int64_t timestampUs); 60 bool isAvc() const { return mIsAvc; } 61 bool isAudio() const { return mIsAudio; } 62 bool isMPEG4() const { return mIsMPEG4; } 63 void addChunkOffset(off_t offset); 64 status_t dump(int fd, const Vector<String16>& args) const; 65 66private: 67 MPEG4Writer *mOwner; 68 sp<MetaData> mMeta; 69 sp<MediaSource> mSource; 70 volatile bool mDone; 71 volatile bool mPaused; 72 volatile bool mResumed; 73 bool mIsAvc; 74 bool mIsAudio; 75 bool mIsMPEG4; 76 int64_t mTrackDurationUs; 77 78 // For realtime applications, we need to adjust the media clock 79 // for video track based on the audio media clock 80 bool mIsRealTimeRecording; 81 int64_t mMaxTimeStampUs; 82 int64_t mEstimatedTrackSizeBytes; 83 int64_t mMdatSizeBytes; 84 int32_t mTimeScale; 85 86 pthread_t mThread; 87 88 // mNumSamples is used to track how many samples in mSampleSizes List. 89 // This is to reduce the cost associated with mSampleSizes.size() call, 90 // since it is O(n). Ideally, the fix should be in List class. 91 size_t mNumSamples; 92 List<size_t> mSampleSizes; 93 bool mSamplesHaveSameSize; 94 95 List<MediaBuffer *> mChunkSamples; 96 97 size_t mNumStcoTableEntries; 98 List<off_t> mChunkOffsets; 99 100 size_t mNumStscTableEntries; 101 struct StscTableEntry { 102 103 StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id) 104 : firstChunk(chunk), 105 samplesPerChunk(samples), 106 sampleDescriptionId(id) {} 107 108 uint32_t firstChunk; 109 uint32_t samplesPerChunk; 110 uint32_t sampleDescriptionId; 111 }; 112 List<StscTableEntry> mStscTableEntries; 113 114 size_t mNumStssTableEntries; 115 List<int32_t> mStssTableEntries; 116 List<int64_t> mChunkDurations; 117 118 size_t mNumSttsTableEntries; 119 struct SttsTableEntry { 120 121 SttsTableEntry(uint32_t count, uint32_t durationUs) 122 : sampleCount(count), sampleDurationUs(durationUs) {} 123 124 uint32_t sampleCount; 125 uint32_t sampleDurationUs; 126 }; 127 List<SttsTableEntry> mSttsTableEntries; 128 129 // Sequence parameter set or picture parameter set 130 struct AVCParamSet { 131 AVCParamSet(uint16_t length, const uint8_t *data) 132 : mLength(length), mData(data) {} 133 134 uint16_t mLength; 135 const uint8_t *mData; 136 }; 137 List<AVCParamSet> mSeqParamSets; 138 List<AVCParamSet> mPicParamSets; 139 uint8_t mProfileIdc; 140 uint8_t mProfileCompatible; 141 uint8_t mLevelIdc; 142 143 void *mCodecSpecificData; 144 size_t mCodecSpecificDataSize; 145 bool mGotAllCodecSpecificData; 146 bool mTrackingProgressStatus; 147 148 bool mReachedEOS; 149 int64_t mStartTimestampUs; 150 int64_t mPreviousTrackTimeUs; 151 int64_t mTrackEveryTimeDurationUs; 152 153 static void *ThreadWrapper(void *me); 154 status_t threadEntry(); 155 156 const uint8_t *parseParamSet( 157 const uint8_t *data, size_t length, int type, size_t *paramSetLen); 158 159 status_t makeAVCCodecSpecificData( 160 const uint8_t *data, size_t size); 161 status_t copyAVCCodecSpecificData( 162 const uint8_t *data, size_t size); 163 status_t parseAVCCodecSpecificData( 164 const uint8_t *data, size_t size); 165 166 // Track authoring progress status 167 void trackProgressStatus(int64_t timeUs, status_t err = OK); 168 void initTrackingProgressStatus(MetaData *params); 169 170 // Utilities for collecting statistical data 171 void logStatisticalData(bool isAudio); 172 void findMinAvgMaxSampleDurationMs( 173 int32_t *min, int32_t *avg, int32_t *max); 174 void findMinMaxChunkDurations(int64_t *min, int64_t *max); 175 176 void getCodecSpecificDataFromInputFormatIfPossible(); 177 178 // Determine the track time scale 179 // If it is an audio track, try to use the sampling rate as 180 // the time scale; however, if user chooses the overwrite 181 // value, the user-supplied time scale will be used. 182 void setTimeScale(); 183 184 // Simple validation on the codec specific data 185 status_t checkCodecSpecificData() const; 186 187 void updateTrackSizeEstimate(); 188 void addOneStscTableEntry(size_t chunkId, size_t sampleId); 189 void addOneStssTableEntry(size_t sampleId); 190 void addOneSttsTableEntry(size_t sampleCount, int64_t durationUs); 191 192 Track(const Track &); 193 Track &operator=(const Track &); 194}; 195 196#define USE_NALLEN_FOUR 1 197 198MPEG4Writer::MPEG4Writer(const char *filename) 199 : mFile(fopen(filename, "wb")), 200 mUse32BitOffset(true), 201 mPaused(false), 202 mStarted(false), 203 mOffset(0), 204 mMdatOffset(0), 205 mEstimatedMoovBoxSize(0), 206 mInterleaveDurationUs(1000000) { 207 CHECK(mFile != NULL); 208} 209 210MPEG4Writer::MPEG4Writer(int fd) 211 : mFile(fdopen(fd, "wb")), 212 mUse32BitOffset(true), 213 mPaused(false), 214 mStarted(false), 215 mOffset(0), 216 mMdatOffset(0), 217 mEstimatedMoovBoxSize(0), 218 mInterleaveDurationUs(1000000) { 219 CHECK(mFile != NULL); 220} 221 222MPEG4Writer::~MPEG4Writer() { 223 stop(); 224 225 while (!mTracks.empty()) { 226 List<Track *>::iterator it = mTracks.begin(); 227 delete *it; 228 (*it) = NULL; 229 mTracks.erase(it); 230 } 231 mTracks.clear(); 232} 233 234status_t MPEG4Writer::dump( 235 int fd, const Vector<String16>& args) { 236 const size_t SIZE = 256; 237 char buffer[SIZE]; 238 String8 result; 239 snprintf(buffer, SIZE, " MPEG4Writer %p\n", this); 240 result.append(buffer); 241 snprintf(buffer, SIZE, " mStarted: %s\n", mStarted? "true": "false"); 242 result.append(buffer); 243 ::write(fd, result.string(), result.size()); 244 for (List<Track *>::iterator it = mTracks.begin(); 245 it != mTracks.end(); ++it) { 246 (*it)->dump(fd, args); 247 } 248 return OK; 249} 250 251status_t MPEG4Writer::Track::dump( 252 int fd, const Vector<String16>& args) const { 253 const size_t SIZE = 256; 254 char buffer[SIZE]; 255 String8 result; 256 snprintf(buffer, SIZE, " %s track\n", mIsAudio? "Audio": "Video"); 257 result.append(buffer); 258 snprintf(buffer, SIZE, " reached EOS: %s\n", 259 mReachedEOS? "true": "false"); 260 result.append(buffer); 261 ::write(fd, result.string(), result.size()); 262 return OK; 263} 264 265status_t MPEG4Writer::addSource(const sp<MediaSource> &source) { 266 Track *track = new Track(this, source); 267 mTracks.push_back(track); 268 269 return OK; 270} 271 272status_t MPEG4Writer::startTracks(MetaData *params) { 273 for (List<Track *>::iterator it = mTracks.begin(); 274 it != mTracks.end(); ++it) { 275 status_t err = (*it)->start(params); 276 277 if (err != OK) { 278 for (List<Track *>::iterator it2 = mTracks.begin(); 279 it2 != it; ++it2) { 280 (*it2)->stop(); 281 } 282 283 return err; 284 } 285 } 286 return OK; 287} 288 289int64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) { 290 // This implementation is highly experimental/heurisitic. 291 // 292 // Statistical analysis shows that metadata usually accounts 293 // for a small portion of the total file size, usually < 0.6%. 294 // Currently, lets set to 0.4% for now. 295 296 // The default MIN_MOOV_BOX_SIZE is set to 0.4% x 1MB, 297 // where 1MB is the common file size limit for MMS application. 298 // The default MAX _MOOV_BOX_SIZE value is based on about 4 299 // minute video recording with a bit rate about 3 Mbps, because 300 // statistics also show that most of the video captured are going 301 // to be less than 3 minutes. 302 303 // If the estimation is wrong, we will pay the price of wasting 304 // some reserved space. This should not happen so often statistically. 305 static const int32_t factor = mUse32BitOffset? 1: 2; 306 static const int64_t MIN_MOOV_BOX_SIZE = 4 * 1024; // 4 KB 307 static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000); 308 int64_t size = MIN_MOOV_BOX_SIZE; 309 310 if (mMaxFileSizeLimitBytes != 0) { 311 size = mMaxFileSizeLimitBytes * 4 / 1000; 312 } else if (mMaxFileDurationLimitUs != 0) { 313 if (bitRate <= 0) { 314 // We could not estimate the file size since bitRate is not set. 315 size = MIN_MOOV_BOX_SIZE; 316 } else { 317 size = ((mMaxFileDurationLimitUs * bitRate * 4) / 1000 / 8000000); 318 } 319 } 320 if (size < MIN_MOOV_BOX_SIZE) { 321 size = MIN_MOOV_BOX_SIZE; 322 } 323 324 // Any long duration recording will be probably end up with 325 // non-streamable mp4 file. 326 if (size > MAX_MOOV_BOX_SIZE) { 327 size = MAX_MOOV_BOX_SIZE; 328 } 329 330 LOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated" 331 " moov size %lld bytes", 332 mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size); 333 return factor * size; 334} 335 336status_t MPEG4Writer::start(MetaData *param) { 337 if (mFile == NULL) { 338 return UNKNOWN_ERROR; 339 } 340 341 int32_t use64BitOffset; 342 if (param && 343 param->findInt32(kKey64BitFileOffset, &use64BitOffset) && 344 use64BitOffset) { 345 mUse32BitOffset = false; 346 } 347 348 if (mUse32BitOffset) { 349 // Implicit 32 bit file size limit 350 if (mMaxFileSizeLimitBytes == 0) { 351 mMaxFileSizeLimitBytes = kMax32BitFileSize; 352 } 353 354 // If file size is set to be larger than the 32 bit file 355 // size limit, treat it as an error. 356 if (mMaxFileSizeLimitBytes > kMax32BitFileSize) { 357 LOGE("32-bit file size limit too big: %lld bytes", 358 mMaxFileSizeLimitBytes); 359 return UNKNOWN_ERROR; 360 } 361 } 362 363 // System property can overwrite the file offset bits parameter 364 char value[PROPERTY_VALUE_MAX]; 365 if (property_get("media.stagefright.record-64bits", value, NULL) 366 && (!strcmp(value, "1") || !strcasecmp(value, "true"))) { 367 mUse32BitOffset = false; 368 } 369 370 mStartTimestampUs = -1; 371 372 if (mStarted) { 373 if (mPaused) { 374 mPaused = false; 375 return startTracks(param); 376 } 377 return OK; 378 } 379 380 if (!param || 381 !param->findInt32(kKeyTimeScale, &mTimeScale)) { 382 mTimeScale = 1000; 383 } 384 CHECK(mTimeScale > 0); 385 LOGV("movie time scale: %d", mTimeScale); 386 387 mStreamableFile = true; 388 mWriteMoovBoxToMemory = false; 389 mMoovBoxBuffer = NULL; 390 mMoovBoxBufferOffset = 0; 391 392 beginBox("ftyp"); 393 { 394 int32_t fileType; 395 if (param && param->findInt32(kKeyFileType, &fileType) && 396 fileType != OUTPUT_FORMAT_MPEG_4) { 397 writeFourcc("3gp4"); 398 } else { 399 writeFourcc("isom"); 400 } 401 } 402 writeInt32(0); 403 writeFourcc("isom"); 404 writeFourcc("3gp4"); 405 endBox(); 406 407 mFreeBoxOffset = mOffset; 408 409 if (mEstimatedMoovBoxSize == 0) { 410 int32_t bitRate = -1; 411 if (param) { 412 param->findInt32(kKeyBitRate, &bitRate); 413 } 414 mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate); 415 } 416 CHECK(mEstimatedMoovBoxSize >= 8); 417 fseeko(mFile, mFreeBoxOffset, SEEK_SET); 418 writeInt32(mEstimatedMoovBoxSize); 419 write("free", 4); 420 421 mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; 422 mOffset = mMdatOffset; 423 fseeko(mFile, mMdatOffset, SEEK_SET); 424 if (mUse32BitOffset) { 425 write("????mdat", 8); 426 } else { 427 write("\x00\x00\x00\x01mdat????????", 16); 428 } 429 430 status_t err = startWriterThread(); 431 if (err != OK) { 432 return err; 433 } 434 435 err = startTracks(param); 436 if (err != OK) { 437 return err; 438 } 439 440 mStarted = true; 441 return OK; 442} 443 444bool MPEG4Writer::use32BitFileOffset() const { 445 return mUse32BitOffset; 446} 447 448status_t MPEG4Writer::pause() { 449 if (mFile == NULL) { 450 return OK; 451 } 452 mPaused = true; 453 status_t err = OK; 454 for (List<Track *>::iterator it = mTracks.begin(); 455 it != mTracks.end(); ++it) { 456 status_t status = (*it)->pause(); 457 if (status != OK) { 458 err = status; 459 } 460 } 461 return err; 462} 463 464void MPEG4Writer::stopWriterThread() { 465 LOGV("stopWriterThread"); 466 467 { 468 Mutex::Autolock autolock(mLock); 469 470 mDone = true; 471 mChunkReadyCondition.signal(); 472 } 473 474 void *dummy; 475 pthread_join(mThread, &dummy); 476} 477 478status_t MPEG4Writer::stop() { 479 if (mFile == NULL) { 480 return OK; 481 } 482 483 status_t err = OK; 484 int64_t maxDurationUs = 0; 485 for (List<Track *>::iterator it = mTracks.begin(); 486 it != mTracks.end(); ++it) { 487 status_t status = (*it)->stop(); 488 if (err == OK && status != OK) { 489 err = status; 490 } 491 492 int64_t durationUs = (*it)->getDurationUs(); 493 if (durationUs > maxDurationUs) { 494 maxDurationUs = durationUs; 495 } 496 } 497 498 stopWriterThread(); 499 500 // Do not write out movie header on error. 501 if (err != OK) { 502 fflush(mFile); 503 fclose(mFile); 504 mFile = NULL; 505 mStarted = false; 506 return err; 507 } 508 509 // Fix up the size of the 'mdat' chunk. 510 if (mUse32BitOffset) { 511 fseeko(mFile, mMdatOffset, SEEK_SET); 512 int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset)); 513 fwrite(&size, 1, 4, mFile); 514 } else { 515 fseeko(mFile, mMdatOffset + 8, SEEK_SET); 516 int64_t size = mOffset - mMdatOffset; 517 size = hton64(size); 518 fwrite(&size, 1, 8, mFile); 519 } 520 fseeko(mFile, mOffset, SEEK_SET); 521 522 time_t now = time(NULL); 523 const off_t moovOffset = mOffset; 524 mWriteMoovBoxToMemory = true; 525 mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); 526 mMoovBoxBufferOffset = 0; 527 CHECK(mMoovBoxBuffer != NULL); 528 int32_t duration = (maxDurationUs * mTimeScale + 5E5) / 1E6; 529 530 beginBox("moov"); 531 532 beginBox("mvhd"); 533 writeInt32(0); // version=0, flags=0 534 writeInt32(now); // creation time 535 writeInt32(now); // modification time 536 writeInt32(mTimeScale); // mvhd timescale 537 writeInt32(duration); 538 writeInt32(0x10000); // rate: 1.0 539 writeInt16(0x100); // volume 540 writeInt16(0); // reserved 541 writeInt32(0); // reserved 542 writeInt32(0); // reserved 543 writeInt32(0x10000); // matrix 544 writeInt32(0); 545 writeInt32(0); 546 writeInt32(0); 547 writeInt32(0x10000); 548 writeInt32(0); 549 writeInt32(0); 550 writeInt32(0); 551 writeInt32(0x40000000); 552 writeInt32(0); // predefined 553 writeInt32(0); // predefined 554 writeInt32(0); // predefined 555 writeInt32(0); // predefined 556 writeInt32(0); // predefined 557 writeInt32(0); // predefined 558 writeInt32(mTracks.size() + 1); // nextTrackID 559 endBox(); // mvhd 560 561 int32_t id = 1; 562 for (List<Track *>::iterator it = mTracks.begin(); 563 it != mTracks.end(); ++it, ++id) { 564 (*it)->writeTrackHeader(id, mUse32BitOffset); 565 } 566 endBox(); // moov 567 568 mWriteMoovBoxToMemory = false; 569 if (mStreamableFile) { 570 CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize); 571 572 // Moov box 573 fseeko(mFile, mFreeBoxOffset, SEEK_SET); 574 mOffset = mFreeBoxOffset; 575 write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile); 576 577 // Free box 578 fseeko(mFile, mOffset, SEEK_SET); 579 writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); 580 write("free", 4); 581 582 // Free temp memory 583 free(mMoovBoxBuffer); 584 mMoovBoxBuffer = NULL; 585 mMoovBoxBufferOffset = 0; 586 } else { 587 LOGI("The mp4 file will not be streamable."); 588 } 589 590 CHECK(mBoxes.empty()); 591 592 fflush(mFile); 593 fclose(mFile); 594 mFile = NULL; 595 mStarted = false; 596 return err; 597} 598 599status_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 600 mInterleaveDurationUs = durationUs; 601 return OK; 602} 603 604void MPEG4Writer::lock() { 605 mLock.lock(); 606} 607 608void MPEG4Writer::unlock() { 609 mLock.unlock(); 610} 611 612off_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { 613 off_t old_offset = mOffset; 614 615 fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 616 1, buffer->range_length(), mFile); 617 618 mOffset += buffer->range_length(); 619 620 return old_offset; 621} 622 623static void StripStartcode(MediaBuffer *buffer) { 624 if (buffer->range_length() < 4) { 625 return; 626 } 627 628 const uint8_t *ptr = 629 (const uint8_t *)buffer->data() + buffer->range_offset(); 630 631 if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 632 buffer->set_range( 633 buffer->range_offset() + 4, buffer->range_length() - 4); 634 } 635} 636 637off_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 638 off_t old_offset = mOffset; 639 640 size_t length = buffer->range_length(); 641 642#if USE_NALLEN_FOUR 643 uint8_t x = length >> 24; 644 fwrite(&x, 1, 1, mFile); 645 x = (length >> 16) & 0xff; 646 fwrite(&x, 1, 1, mFile); 647 x = (length >> 8) & 0xff; 648 fwrite(&x, 1, 1, mFile); 649 x = length & 0xff; 650 fwrite(&x, 1, 1, mFile); 651#else 652 CHECK(length < 65536); 653 654 uint8_t x = length >> 8; 655 fwrite(&x, 1, 1, mFile); 656 x = length & 0xff; 657 fwrite(&x, 1, 1, mFile); 658#endif 659 660 fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 661 1, length, mFile); 662 663#if USE_NALLEN_FOUR 664 mOffset += length + 4; 665#else 666 mOffset += length + 2; 667#endif 668 669 return old_offset; 670} 671 672size_t MPEG4Writer::write( 673 const void *ptr, size_t size, size_t nmemb, FILE *stream) { 674 675 const size_t bytes = size * nmemb; 676 if (mWriteMoovBoxToMemory) { 677 off_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes; 678 if (moovBoxSize > mEstimatedMoovBoxSize) { 679 for (List<off_t>::iterator it = mBoxes.begin(); 680 it != mBoxes.end(); ++it) { 681 (*it) += mOffset; 682 } 683 fseeko(mFile, mOffset, SEEK_SET); 684 fwrite(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, stream); 685 fwrite(ptr, size, nmemb, stream); 686 mOffset += (bytes + mMoovBoxBufferOffset); 687 free(mMoovBoxBuffer); 688 mMoovBoxBuffer = NULL; 689 mMoovBoxBufferOffset = 0; 690 mWriteMoovBoxToMemory = false; 691 mStreamableFile = false; 692 } else { 693 memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); 694 mMoovBoxBufferOffset += bytes; 695 } 696 } else { 697 fwrite(ptr, size, nmemb, stream); 698 mOffset += bytes; 699 } 700 return bytes; 701} 702 703void MPEG4Writer::beginBox(const char *fourcc) { 704 CHECK_EQ(strlen(fourcc), 4); 705 706 mBoxes.push_back(mWriteMoovBoxToMemory? 707 mMoovBoxBufferOffset: mOffset); 708 709 writeInt32(0); 710 writeFourcc(fourcc); 711} 712 713void MPEG4Writer::endBox() { 714 CHECK(!mBoxes.empty()); 715 716 off_t offset = *--mBoxes.end(); 717 mBoxes.erase(--mBoxes.end()); 718 719 if (mWriteMoovBoxToMemory) { 720 int32_t x = htonl(mMoovBoxBufferOffset - offset); 721 memcpy(mMoovBoxBuffer + offset, &x, 4); 722 } else { 723 fseeko(mFile, offset, SEEK_SET); 724 writeInt32(mOffset - offset); 725 mOffset -= 4; 726 fseeko(mFile, mOffset, SEEK_SET); 727 } 728} 729 730void MPEG4Writer::writeInt8(int8_t x) { 731 write(&x, 1, 1, mFile); 732} 733 734void MPEG4Writer::writeInt16(int16_t x) { 735 x = htons(x); 736 write(&x, 1, 2, mFile); 737} 738 739void MPEG4Writer::writeInt32(int32_t x) { 740 x = htonl(x); 741 write(&x, 1, 4, mFile); 742} 743 744void MPEG4Writer::writeInt64(int64_t x) { 745 x = hton64(x); 746 write(&x, 1, 8, mFile); 747} 748 749void MPEG4Writer::writeCString(const char *s) { 750 size_t n = strlen(s); 751 write(s, 1, n + 1, mFile); 752} 753 754void MPEG4Writer::writeFourcc(const char *s) { 755 CHECK_EQ(strlen(s), 4); 756 write(s, 1, 4, mFile); 757} 758 759void MPEG4Writer::write(const void *data, size_t size) { 760 write(data, 1, size, mFile); 761} 762 763bool MPEG4Writer::exceedsFileSizeLimit() { 764 // No limit 765 if (mMaxFileSizeLimitBytes == 0) { 766 return false; 767 } 768 769 int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 770 for (List<Track *>::iterator it = mTracks.begin(); 771 it != mTracks.end(); ++it) { 772 nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 773 } 774 775 return (nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes); 776} 777 778bool MPEG4Writer::exceedsFileDurationLimit() { 779 // No limit 780 if (mMaxFileDurationLimitUs == 0) { 781 return false; 782 } 783 784 for (List<Track *>::iterator it = mTracks.begin(); 785 it != mTracks.end(); ++it) { 786 if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { 787 return true; 788 } 789 } 790 return false; 791} 792 793bool MPEG4Writer::reachedEOS() { 794 bool allDone = true; 795 for (List<Track *>::iterator it = mTracks.begin(); 796 it != mTracks.end(); ++it) { 797 if (!(*it)->reachedEOS()) { 798 allDone = false; 799 break; 800 } 801 } 802 803 return allDone; 804} 805 806void MPEG4Writer::setStartTimestampUs(int64_t timeUs) { 807 LOGI("setStartTimestampUs: %lld", timeUs); 808 CHECK(timeUs >= 0); 809 Mutex::Autolock autoLock(mLock); 810 if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) { 811 mStartTimestampUs = timeUs; 812 LOGI("Earliest track starting time: %lld", mStartTimestampUs); 813 } 814} 815 816int64_t MPEG4Writer::getStartTimestampUs() { 817 Mutex::Autolock autoLock(mLock); 818 return mStartTimestampUs; 819} 820 821size_t MPEG4Writer::numTracks() { 822 Mutex::Autolock autolock(mLock); 823 return mTracks.size(); 824} 825 826//////////////////////////////////////////////////////////////////////////////// 827 828MPEG4Writer::Track::Track( 829 MPEG4Writer *owner, const sp<MediaSource> &source) 830 : mOwner(owner), 831 mMeta(source->getFormat()), 832 mSource(source), 833 mDone(false), 834 mPaused(false), 835 mResumed(false), 836 mTrackDurationUs(0), 837 mEstimatedTrackSizeBytes(0), 838 mSamplesHaveSameSize(true), 839 mCodecSpecificData(NULL), 840 mCodecSpecificDataSize(0), 841 mGotAllCodecSpecificData(false), 842 mReachedEOS(false) { 843 getCodecSpecificDataFromInputFormatIfPossible(); 844 845 const char *mime; 846 mMeta->findCString(kKeyMIMEType, &mime); 847 mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 848 mIsAudio = !strncasecmp(mime, "audio/", 6); 849 mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 850 !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 851 852 setTimeScale(); 853} 854 855void MPEG4Writer::Track::updateTrackSizeEstimate() { 856 857 int64_t stcoBoxSizeBytes = mOwner->use32BitFileOffset() 858 ? mNumStcoTableEntries * 4 859 : mNumStcoTableEntries * 8; 860 861 int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mNumSamples * 4); 862 863 mEstimatedTrackSizeBytes = mMdatSizeBytes + // media data size 864 mNumStscTableEntries * 12 + // stsc box size 865 mNumStssTableEntries * 4 + // stss box size 866 mNumSttsTableEntries * 8 + // stts box size 867 stcoBoxSizeBytes + // stco box size 868 stszBoxSizeBytes; // stsz box size 869} 870 871void MPEG4Writer::Track::addOneStscTableEntry( 872 size_t chunkId, size_t sampleId) { 873 874 StscTableEntry stscEntry(chunkId, sampleId, 1); 875 mStscTableEntries.push_back(stscEntry); 876 ++mNumStscTableEntries; 877} 878 879void MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) { 880 mStssTableEntries.push_back(sampleId); 881 ++mNumStssTableEntries; 882} 883 884void MPEG4Writer::Track::addOneSttsTableEntry( 885 size_t sampleCount, int64_t durationUs) { 886 887 SttsTableEntry sttsEntry(sampleCount, durationUs); 888 mSttsTableEntries.push_back(sttsEntry); 889 ++mNumSttsTableEntries; 890} 891 892void MPEG4Writer::Track::addChunkOffset(off_t offset) { 893 ++mNumStcoTableEntries; 894 mChunkOffsets.push_back(offset); 895} 896 897void MPEG4Writer::Track::setTimeScale() { 898 LOGV("setTimeScale"); 899 // Default time scale 900 mTimeScale = 90000; 901 902 if (mIsAudio) { 903 // Use the sampling rate as the default time scale for audio track. 904 int32_t sampleRate; 905 bool success = mMeta->findInt32(kKeySampleRate, &sampleRate); 906 CHECK(success); 907 mTimeScale = sampleRate; 908 } 909 910 // If someone would like to overwrite the timescale, use user-supplied value. 911 int32_t timeScale; 912 if (mMeta->findInt32(kKeyTimeScale, &timeScale)) { 913 mTimeScale = timeScale; 914 } 915 916 CHECK(mTimeScale > 0); 917} 918 919void MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() { 920 const char *mime; 921 CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 922 923 if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 924 uint32_t type; 925 const void *data; 926 size_t size; 927 if (mMeta->findData(kKeyAVCC, &type, &data, &size)) { 928 mCodecSpecificData = malloc(size); 929 mCodecSpecificDataSize = size; 930 memcpy(mCodecSpecificData, data, size); 931 mGotAllCodecSpecificData = true; 932 } 933 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 934 || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 935 uint32_t type; 936 const void *data; 937 size_t size; 938 if (mMeta->findData(kKeyESDS, &type, &data, &size)) { 939 ESDS esds(data, size); 940 if (esds.getCodecSpecificInfo(&data, &size) == OK) { 941 mCodecSpecificData = malloc(size); 942 mCodecSpecificDataSize = size; 943 memcpy(mCodecSpecificData, data, size); 944 mGotAllCodecSpecificData = true; 945 } 946 } 947 } 948} 949 950MPEG4Writer::Track::~Track() { 951 stop(); 952 953 if (mCodecSpecificData != NULL) { 954 free(mCodecSpecificData); 955 mCodecSpecificData = NULL; 956 } 957} 958 959void MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) { 960 LOGV("initTrackingProgressStatus"); 961 mPreviousTrackTimeUs = -1; 962 mTrackingProgressStatus = false; 963 mTrackEveryTimeDurationUs = 0; 964 { 965 int64_t timeUs; 966 if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) { 967 LOGV("Receive request to track progress status for every %lld us", timeUs); 968 mTrackEveryTimeDurationUs = timeUs; 969 mTrackingProgressStatus = true; 970 } 971 } 972} 973 974// static 975void *MPEG4Writer::ThreadWrapper(void *me) { 976 LOGV("ThreadWrapper: %p", me); 977 MPEG4Writer *writer = static_cast<MPEG4Writer *>(me); 978 writer->threadFunc(); 979 return NULL; 980} 981 982void MPEG4Writer::bufferChunk(const Chunk& chunk) { 983 LOGV("bufferChunk: %p", chunk.mTrack); 984 Mutex::Autolock autolock(mLock); 985 CHECK_EQ(mDone, false); 986 987 for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 988 it != mChunkInfos.end(); ++it) { 989 990 if (chunk.mTrack == it->mTrack) { // Found owner 991 it->mChunks.push_back(chunk); 992 mChunkReadyCondition.signal(); 993 return; 994 } 995 } 996 997 CHECK("Received a chunk for a unknown track" == 0); 998} 999 1000void MPEG4Writer::writeFirstChunk(ChunkInfo* info) { 1001 LOGV("writeFirstChunk: %p", info->mTrack); 1002 1003 List<Chunk>::iterator chunkIt = info->mChunks.begin(); 1004 for (List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin(); 1005 it != chunkIt->mSamples.end(); ++it) { 1006 1007 off_t offset = info->mTrack->isAvc() 1008 ? addLengthPrefixedSample_l(*it) 1009 : addSample_l(*it); 1010 if (it == chunkIt->mSamples.begin()) { 1011 info->mTrack->addChunkOffset(offset); 1012 } 1013 } 1014 1015 // Done with the current chunk. 1016 // Release all the samples in this chunk. 1017 while (!chunkIt->mSamples.empty()) { 1018 List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin(); 1019 (*it)->release(); 1020 (*it) = NULL; 1021 chunkIt->mSamples.erase(it); 1022 } 1023 chunkIt->mSamples.clear(); 1024 info->mChunks.erase(chunkIt); 1025} 1026 1027void MPEG4Writer::writeChunks() { 1028 LOGV("writeChunks"); 1029 size_t outstandingChunks = 0; 1030 while (!mChunkInfos.empty()) { 1031 List<ChunkInfo>::iterator it = mChunkInfos.begin(); 1032 while (!it->mChunks.empty()) { 1033 CHECK_EQ(OK, writeOneChunk()); 1034 ++outstandingChunks; 1035 } 1036 it->mTrack = NULL; 1037 mChunkInfos.erase(it); 1038 } 1039 mChunkInfos.clear(); 1040 LOGD("%d chunks are written in the last batch", outstandingChunks); 1041} 1042 1043status_t MPEG4Writer::writeOneChunk() { 1044 LOGV("writeOneChunk"); 1045 1046 // Find the smallest timestamp, and write that chunk out 1047 // XXX: What if some track is just too slow? 1048 int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL; 1049 Track *track = NULL; 1050 for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 1051 it != mChunkInfos.end(); ++it) { 1052 if (!it->mChunks.empty()) { 1053 List<Chunk>::iterator chunkIt = it->mChunks.begin(); 1054 if (chunkIt->mTimeStampUs < minTimestampUs) { 1055 minTimestampUs = chunkIt->mTimeStampUs; 1056 track = it->mTrack; 1057 } 1058 } 1059 } 1060 1061 if (track == NULL) { 1062 LOGV("Nothing to be written after all"); 1063 return OK; 1064 } 1065 1066 if (mIsFirstChunk) { 1067 mIsFirstChunk = false; 1068 } 1069 for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 1070 it != mChunkInfos.end(); ++it) { 1071 if (it->mTrack == track) { 1072 writeFirstChunk(&(*it)); 1073 } 1074 } 1075 return OK; 1076} 1077 1078void MPEG4Writer::threadFunc() { 1079 LOGV("threadFunc"); 1080 1081 while (!mDone) { 1082 { 1083 Mutex::Autolock autolock(mLock); 1084 mChunkReadyCondition.wait(mLock); 1085 CHECK_EQ(writeOneChunk(), OK); 1086 } 1087 } 1088 1089 { 1090 // Write ALL samples 1091 Mutex::Autolock autolock(mLock); 1092 writeChunks(); 1093 } 1094} 1095 1096status_t MPEG4Writer::startWriterThread() { 1097 LOGV("startWriterThread"); 1098 1099 mDone = false; 1100 mIsFirstChunk = true; 1101 mDriftTimeUs = 0; 1102 for (List<Track *>::iterator it = mTracks.begin(); 1103 it != mTracks.end(); ++it) { 1104 ChunkInfo info; 1105 info.mTrack = *it; 1106 mChunkInfos.push_back(info); 1107 } 1108 1109 pthread_attr_t attr; 1110 pthread_attr_init(&attr); 1111 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 1112 pthread_create(&mThread, &attr, ThreadWrapper, this); 1113 pthread_attr_destroy(&attr); 1114 return OK; 1115} 1116 1117 1118status_t MPEG4Writer::Track::start(MetaData *params) { 1119 if (!mDone && mPaused) { 1120 mPaused = false; 1121 mResumed = true; 1122 return OK; 1123 } 1124 1125 int64_t startTimeUs; 1126 if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) { 1127 startTimeUs = 0; 1128 } 1129 1130 mIsRealTimeRecording = true; 1131 { 1132 int32_t isNotRealTime; 1133 if (params && params->findInt32(kKeyNotRealTime, &isNotRealTime)) { 1134 mIsRealTimeRecording = (isNotRealTime == 0); 1135 } 1136 } 1137 1138 initTrackingProgressStatus(params); 1139 1140 sp<MetaData> meta = new MetaData; 1141 meta->setInt64(kKeyTime, startTimeUs); 1142 status_t err = mSource->start(meta.get()); 1143 if (err != OK) { 1144 mDone = mReachedEOS = true; 1145 return err; 1146 } 1147 1148 pthread_attr_t attr; 1149 pthread_attr_init(&attr); 1150 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 1151 1152 mDone = false; 1153 mTrackDurationUs = 0; 1154 mReachedEOS = false; 1155 mEstimatedTrackSizeBytes = 0; 1156 mNumStcoTableEntries = 0; 1157 mNumStssTableEntries = 0; 1158 mNumStscTableEntries = 0; 1159 mNumSttsTableEntries = 0; 1160 mMdatSizeBytes = 0; 1161 1162 pthread_create(&mThread, &attr, ThreadWrapper, this); 1163 pthread_attr_destroy(&attr); 1164 1165 return OK; 1166} 1167 1168status_t MPEG4Writer::Track::pause() { 1169 mPaused = true; 1170 return OK; 1171} 1172 1173status_t MPEG4Writer::Track::stop() { 1174 if (mDone) { 1175 return OK; 1176 } 1177 1178 mDone = true; 1179 1180 void *dummy; 1181 pthread_join(mThread, &dummy); 1182 1183 status_t err = (status_t) dummy; 1184 1185 { 1186 status_t status = mSource->stop(); 1187 if (err == OK && status != OK && status != ERROR_END_OF_STREAM) { 1188 err = status; 1189 } 1190 } 1191 1192 return err; 1193} 1194 1195bool MPEG4Writer::Track::reachedEOS() { 1196 return mReachedEOS; 1197} 1198 1199// static 1200void *MPEG4Writer::Track::ThreadWrapper(void *me) { 1201 Track *track = static_cast<Track *>(me); 1202 1203 status_t err = track->threadEntry(); 1204 return (void *) err; 1205} 1206 1207#include <ctype.h> 1208static void hexdump(const void *_data, size_t size) { 1209 const uint8_t *data = (const uint8_t *)_data; 1210 size_t offset = 0; 1211 while (offset < size) { 1212 printf("0x%04x ", offset); 1213 1214 size_t n = size - offset; 1215 if (n > 16) { 1216 n = 16; 1217 } 1218 1219 for (size_t i = 0; i < 16; ++i) { 1220 if (i == 8) { 1221 printf(" "); 1222 } 1223 1224 if (offset + i < size) { 1225 printf("%02x ", data[offset + i]); 1226 } else { 1227 printf(" "); 1228 } 1229 } 1230 1231 printf(" "); 1232 1233 for (size_t i = 0; i < n; ++i) { 1234 if (isprint(data[offset + i])) { 1235 printf("%c", data[offset + i]); 1236 } else { 1237 printf("."); 1238 } 1239 } 1240 1241 printf("\n"); 1242 1243 offset += 16; 1244 } 1245} 1246 1247static void getNalUnitType(uint8_t byte, uint8_t* type) { 1248 LOGV("getNalUnitType: %d", byte); 1249 1250 // nal_unit_type: 5-bit unsigned integer 1251 *type = (byte & 0x1F); 1252} 1253 1254static const uint8_t *findNextStartCode( 1255 const uint8_t *data, size_t length) { 1256 1257 LOGV("findNextStartCode: %p %d", data, length); 1258 1259 size_t bytesLeft = length; 1260 while (bytesLeft > 4 && 1261 memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) { 1262 --bytesLeft; 1263 } 1264 if (bytesLeft <= 4) { 1265 bytesLeft = 0; // Last parameter set 1266 } 1267 return &data[length - bytesLeft]; 1268} 1269 1270const uint8_t *MPEG4Writer::Track::parseParamSet( 1271 const uint8_t *data, size_t length, int type, size_t *paramSetLen) { 1272 1273 LOGV("parseParamSet"); 1274 CHECK(type == kNalUnitTypeSeqParamSet || 1275 type == kNalUnitTypePicParamSet); 1276 1277 const uint8_t *nextStartCode = findNextStartCode(data, length); 1278 *paramSetLen = nextStartCode - data; 1279 if (*paramSetLen == 0) { 1280 LOGE("Param set is malformed, since its length is 0"); 1281 return NULL; 1282 } 1283 1284 AVCParamSet paramSet(*paramSetLen, data); 1285 if (type == kNalUnitTypeSeqParamSet) { 1286 if (*paramSetLen < 4) { 1287 LOGE("Seq parameter set malformed"); 1288 return NULL; 1289 } 1290 if (mSeqParamSets.empty()) { 1291 mProfileIdc = data[1]; 1292 mProfileCompatible = data[2]; 1293 mLevelIdc = data[3]; 1294 } else { 1295 if (mProfileIdc != data[1] || 1296 mProfileCompatible != data[2] || 1297 mLevelIdc != data[3]) { 1298 LOGE("Inconsistent profile/level found in seq parameter sets"); 1299 return NULL; 1300 } 1301 } 1302 mSeqParamSets.push_back(paramSet); 1303 } else { 1304 mPicParamSets.push_back(paramSet); 1305 } 1306 return nextStartCode; 1307} 1308 1309status_t MPEG4Writer::Track::copyAVCCodecSpecificData( 1310 const uint8_t *data, size_t size) { 1311 LOGV("copyAVCCodecSpecificData"); 1312 1313 // 2 bytes for each of the parameter set length field 1314 // plus the 7 bytes for the header 1315 if (size < 4 + 7) { 1316 LOGE("Codec specific data length too short: %d", size); 1317 return ERROR_MALFORMED; 1318 } 1319 1320 mCodecSpecificDataSize = size; 1321 mCodecSpecificData = malloc(size); 1322 memcpy(mCodecSpecificData, data, size); 1323 return OK; 1324} 1325 1326status_t MPEG4Writer::Track::parseAVCCodecSpecificData( 1327 const uint8_t *data, size_t size) { 1328 1329 LOGV("parseAVCCodecSpecificData"); 1330 // Data starts with a start code. 1331 // SPS and PPS are separated with start codes. 1332 // Also, SPS must come before PPS 1333 uint8_t type = kNalUnitTypeSeqParamSet; 1334 bool gotSps = false; 1335 bool gotPps = false; 1336 const uint8_t *tmp = data; 1337 const uint8_t *nextStartCode = data; 1338 size_t bytesLeft = size; 1339 size_t paramSetLen = 0; 1340 mCodecSpecificDataSize = 0; 1341 while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 1342 getNalUnitType(*(tmp + 4), &type); 1343 if (type == kNalUnitTypeSeqParamSet) { 1344 if (gotPps) { 1345 LOGE("SPS must come before PPS"); 1346 return ERROR_MALFORMED; 1347 } 1348 if (!gotSps) { 1349 gotSps = true; 1350 } 1351 nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 1352 } else if (type == kNalUnitTypePicParamSet) { 1353 if (!gotSps) { 1354 LOGE("SPS must come before PPS"); 1355 return ERROR_MALFORMED; 1356 } 1357 if (!gotPps) { 1358 gotPps = true; 1359 } 1360 nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 1361 } else { 1362 LOGE("Only SPS and PPS Nal units are expected"); 1363 return ERROR_MALFORMED; 1364 } 1365 1366 if (nextStartCode == NULL) { 1367 return ERROR_MALFORMED; 1368 } 1369 1370 // Move on to find the next parameter set 1371 bytesLeft -= nextStartCode - tmp; 1372 tmp = nextStartCode; 1373 mCodecSpecificDataSize += (2 + paramSetLen); 1374 } 1375 1376 { 1377 // Check on the number of seq parameter sets 1378 size_t nSeqParamSets = mSeqParamSets.size(); 1379 if (nSeqParamSets == 0) { 1380 LOGE("Cound not find sequence parameter set"); 1381 return ERROR_MALFORMED; 1382 } 1383 1384 if (nSeqParamSets > 0x1F) { 1385 LOGE("Too many seq parameter sets (%d) found", nSeqParamSets); 1386 return ERROR_MALFORMED; 1387 } 1388 } 1389 1390 { 1391 // Check on the number of pic parameter sets 1392 size_t nPicParamSets = mPicParamSets.size(); 1393 if (nPicParamSets == 0) { 1394 LOGE("Cound not find picture parameter set"); 1395 return ERROR_MALFORMED; 1396 } 1397 if (nPicParamSets > 0xFF) { 1398 LOGE("Too many pic parameter sets (%d) found", nPicParamSets); 1399 return ERROR_MALFORMED; 1400 } 1401 } 1402 1403 { 1404 // Check on the profiles 1405 // These profiles requires additional parameter set extensions 1406 if (mProfileIdc == 100 || mProfileIdc == 110 || 1407 mProfileIdc == 122 || mProfileIdc == 144) { 1408 LOGE("Sorry, no support for profile_idc: %d!", mProfileIdc); 1409 return BAD_VALUE; 1410 } 1411 } 1412 1413 return OK; 1414} 1415 1416status_t MPEG4Writer::Track::makeAVCCodecSpecificData( 1417 const uint8_t *data, size_t size) { 1418 // hexdump(data, size); 1419 1420 if (mCodecSpecificData != NULL) { 1421 LOGE("Already have codec specific data"); 1422 return ERROR_MALFORMED; 1423 } 1424 1425 if (size < 4) { 1426 LOGE("Codec specific data length too short: %d", size); 1427 return ERROR_MALFORMED; 1428 } 1429 1430 // Data is in the form of AVCCodecSpecificData 1431 if (memcmp("\x00\x00\x00\x01", data, 4)) { 1432 return copyAVCCodecSpecificData(data, size); 1433 } 1434 1435 if (parseAVCCodecSpecificData(data, size) != OK) { 1436 return ERROR_MALFORMED; 1437 } 1438 1439 // ISO 14496-15: AVC file format 1440 mCodecSpecificDataSize += 7; // 7 more bytes in the header 1441 mCodecSpecificData = malloc(mCodecSpecificDataSize); 1442 uint8_t *header = (uint8_t *)mCodecSpecificData; 1443 header[0] = 1; // version 1444 header[1] = mProfileIdc; // profile indication 1445 header[2] = mProfileCompatible; // profile compatibility 1446 header[3] = mLevelIdc; 1447 1448 // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne 1449#if USE_NALLEN_FOUR 1450 header[4] = 0xfc | 3; // length size == 4 bytes 1451#else 1452 header[4] = 0xfc | 1; // length size == 2 bytes 1453#endif 1454 1455 // 3-bit '111' followed by 5-bit numSequenceParameterSets 1456 int nSequenceParamSets = mSeqParamSets.size(); 1457 header[5] = 0xe0 | nSequenceParamSets; 1458 header += 6; 1459 for (List<AVCParamSet>::iterator it = mSeqParamSets.begin(); 1460 it != mSeqParamSets.end(); ++it) { 1461 // 16-bit sequence parameter set length 1462 uint16_t seqParamSetLength = it->mLength; 1463 header[0] = seqParamSetLength >> 8; 1464 header[1] = seqParamSetLength & 0xff; 1465 1466 // SPS NAL unit (sequence parameter length bytes) 1467 memcpy(&header[2], it->mData, seqParamSetLength); 1468 header += (2 + seqParamSetLength); 1469 } 1470 1471 // 8-bit nPictureParameterSets 1472 int nPictureParamSets = mPicParamSets.size(); 1473 header[0] = nPictureParamSets; 1474 header += 1; 1475 for (List<AVCParamSet>::iterator it = mPicParamSets.begin(); 1476 it != mPicParamSets.end(); ++it) { 1477 // 16-bit picture parameter set length 1478 uint16_t picParamSetLength = it->mLength; 1479 header[0] = picParamSetLength >> 8; 1480 header[1] = picParamSetLength & 0xff; 1481 1482 // PPS Nal unit (picture parameter set length bytes) 1483 memcpy(&header[2], it->mData, picParamSetLength); 1484 header += (2 + picParamSetLength); 1485 } 1486 1487 return OK; 1488} 1489 1490static bool collectStatisticalData() { 1491 char value[PROPERTY_VALUE_MAX]; 1492 if (property_get("media.stagefright.record-stats", value, NULL) 1493 && (!strcmp(value, "1") || !strcasecmp(value, "true"))) { 1494 return true; 1495 } 1496 return false; 1497} 1498 1499status_t MPEG4Writer::Track::threadEntry() { 1500 int32_t count = 0; 1501 const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 1502 int64_t chunkTimestampUs = 0; 1503 int32_t nChunks = 0; 1504 int32_t nZeroLengthFrames = 0; 1505 int64_t lastTimestampUs = 0; // Previous sample time stamp in ms 1506 int64_t lastDurationUs = 0; // Between the previous two samples in ms 1507 int64_t currDurationTicks = 0; // Timescale based ticks 1508 int64_t lastDurationTicks = 0; // Timescale based ticks 1509 int32_t sampleCount = 1; // Sample count in the current stts table entry 1510 uint32_t previousSampleSize = 0; // Size of the previous sample 1511 int64_t previousPausedDurationUs = 0; 1512 int64_t timestampUs; 1513 1514 sp<MetaData> meta_data; 1515 bool collectStats = collectStatisticalData(); 1516 1517 mNumSamples = 0; 1518 status_t err = OK; 1519 MediaBuffer *buffer; 1520 while (!mDone && (err = mSource->read(&buffer)) == OK) { 1521 if (buffer->range_length() == 0) { 1522 buffer->release(); 1523 buffer = NULL; 1524 ++nZeroLengthFrames; 1525 continue; 1526 } 1527 1528 // If the codec specific data has not been received yet, delay pause. 1529 // After the codec specific data is received, discard what we received 1530 // when the track is to be paused. 1531 if (mPaused && !mResumed) { 1532 buffer->release(); 1533 buffer = NULL; 1534 continue; 1535 } 1536 1537 ++count; 1538 1539 int32_t isCodecConfig; 1540 if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 1541 && isCodecConfig) { 1542 CHECK(!mGotAllCodecSpecificData); 1543 1544 if (mIsAvc) { 1545 status_t err = makeAVCCodecSpecificData( 1546 (const uint8_t *)buffer->data() 1547 + buffer->range_offset(), 1548 buffer->range_length()); 1549 CHECK_EQ(OK, err); 1550 } else if (mIsMPEG4) { 1551 mCodecSpecificDataSize = buffer->range_length(); 1552 mCodecSpecificData = malloc(mCodecSpecificDataSize); 1553 memcpy(mCodecSpecificData, 1554 (const uint8_t *)buffer->data() 1555 + buffer->range_offset(), 1556 buffer->range_length()); 1557 } 1558 1559 buffer->release(); 1560 buffer = NULL; 1561 1562 mGotAllCodecSpecificData = true; 1563 continue; 1564 } 1565 1566 // Make a deep copy of the MediaBuffer and Metadata and release 1567 // the original as soon as we can 1568 MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 1569 memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 1570 buffer->range_length()); 1571 copy->set_range(0, buffer->range_length()); 1572 meta_data = new MetaData(*buffer->meta_data().get()); 1573 buffer->release(); 1574 buffer = NULL; 1575 1576 if (mIsAvc) StripStartcode(copy); 1577 1578 size_t sampleSize; 1579 sampleSize = mIsAvc 1580#if USE_NALLEN_FOUR 1581 ? copy->range_length() + 4 1582#else 1583 ? copy->range_length() + 2 1584#endif 1585 : copy->range_length(); 1586 1587 // Max file size or duration handling 1588 mMdatSizeBytes += sampleSize; 1589 updateTrackSizeEstimate(); 1590 1591 if (mOwner->exceedsFileSizeLimit()) { 1592 mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 1593 break; 1594 } 1595 if (mOwner->exceedsFileDurationLimit()) { 1596 mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 1597 break; 1598 } 1599 1600 1601 int32_t isSync = false; 1602 meta_data->findInt32(kKeyIsSyncFrame, &isSync); 1603 1604 CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 1605 1606//////////////////////////////////////////////////////////////////////////////// 1607 if (mSampleSizes.empty()) { 1608 mStartTimestampUs = timestampUs; 1609 mOwner->setStartTimestampUs(mStartTimestampUs); 1610 } 1611 1612 if (mResumed) { 1613 previousPausedDurationUs += (timestampUs - mTrackDurationUs - lastDurationUs); 1614 mResumed = false; 1615 } 1616 1617 timestampUs -= previousPausedDurationUs; 1618 if (mIsRealTimeRecording && !mIsAudio) { 1619 // The minor adjustment on the timestamp is heuristic/experimental 1620 // We are adjusting the timestamp to reduce the fluctuation of the duration 1621 // of neighboring samples. This in turn helps reduce the track header size, 1622 // especially, the number of entries in the "stts" box. 1623 if (mNumSamples > 1) { 1624 int64_t currDriftTimeUs = mOwner->getDriftTimeUs(); 1625 int64_t durationUs = timestampUs + currDriftTimeUs - lastTimestampUs; 1626 int64_t diffUs = (durationUs > lastDurationUs) 1627 ? durationUs - lastDurationUs 1628 : lastDurationUs - durationUs; 1629 if (diffUs <= 5000) { // XXX: Magic number 5ms 1630 timestampUs = lastTimestampUs + lastDurationUs; 1631 } else { 1632 timestampUs += currDriftTimeUs; 1633 } 1634 } 1635 } 1636 CHECK(timestampUs >= 0); 1637 if (mNumSamples > 1) { 1638 if (timestampUs <= lastTimestampUs) { 1639 LOGW("Frame arrives too late!"); 1640 // Don't drop the late frame, since dropping a frame may cause 1641 // problems later during playback 1642 1643 // The idea here is to avoid having two or more samples with the 1644 // same timestamp in the output file. 1645 if (mTimeScale >= 1000000LL) { 1646 timestampUs = lastTimestampUs + 1; 1647 } else { 1648 timestampUs = lastTimestampUs + (1000000LL + (mTimeScale >> 1)) / mTimeScale; 1649 } 1650 } 1651 } 1652 1653 LOGV("time stamp: %lld and previous paused duration %lld", 1654 timestampUs, previousPausedDurationUs); 1655 if (timestampUs > mTrackDurationUs) { 1656 mTrackDurationUs = timestampUs; 1657 } 1658 1659 mSampleSizes.push_back(sampleSize); 1660 ++mNumSamples; 1661 if (mNumSamples > 2) { 1662 // We need to use the time scale based ticks, rather than the 1663 // timestamp itself to determine whether we have to use a new 1664 // stts entry, since we may have rounding errors. 1665 // The calculation is intended to reduce the accumulated 1666 // rounding errors. 1667 currDurationTicks = 1668 ((timestampUs * mTimeScale + 500000LL) / 1000000LL - 1669 (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL); 1670 1671 if (currDurationTicks != lastDurationTicks) { 1672 addOneSttsTableEntry(sampleCount, lastDurationUs); 1673 sampleCount = 1; 1674 } else { 1675 ++sampleCount; 1676 } 1677 } 1678 if (mSamplesHaveSameSize) { 1679 if (mNumSamples >= 2 && previousSampleSize != sampleSize) { 1680 mSamplesHaveSameSize = false; 1681 } 1682 previousSampleSize = sampleSize; 1683 } 1684 lastDurationUs = timestampUs - lastTimestampUs; 1685 lastDurationTicks = currDurationTicks; 1686 lastTimestampUs = timestampUs; 1687 if (mIsRealTimeRecording && mIsAudio) { 1688 int64_t driftTimeUs = 0; 1689 if (meta_data->findInt64(kKeyDriftTime, &driftTimeUs)) { 1690 mOwner->setDriftTimeUs(driftTimeUs); 1691 } 1692 } 1693 1694 if (isSync != 0) { 1695 addOneStssTableEntry(mNumSamples); 1696 } 1697 1698 if (mTrackingProgressStatus) { 1699 if (mPreviousTrackTimeUs <= 0) { 1700 mPreviousTrackTimeUs = mStartTimestampUs; 1701 } 1702 trackProgressStatus(timestampUs); 1703 } 1704 if (mOwner->numTracks() == 1) { 1705 off_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy) 1706 : mOwner->addSample_l(copy); 1707 if (mChunkOffsets.empty()) { 1708 addChunkOffset(offset); 1709 } 1710 copy->release(); 1711 copy = NULL; 1712 continue; 1713 } 1714 1715 mChunkSamples.push_back(copy); 1716 if (interleaveDurationUs == 0) { 1717 addOneStscTableEntry(++nChunks, 1); 1718 bufferChunk(timestampUs); 1719 } else { 1720 if (chunkTimestampUs == 0) { 1721 chunkTimestampUs = timestampUs; 1722 } else { 1723 if (timestampUs - chunkTimestampUs > interleaveDurationUs) { 1724 ++nChunks; 1725 if (collectStats) { 1726 mChunkDurations.push_back(timestampUs - chunkTimestampUs); 1727 } 1728 if (nChunks == 1 || // First chunk 1729 (--(mStscTableEntries.end()))->samplesPerChunk != 1730 mChunkSamples.size()) { 1731 addOneStscTableEntry(nChunks, mChunkSamples.size()); 1732 } 1733 bufferChunk(timestampUs); 1734 chunkTimestampUs = timestampUs; 1735 } 1736 } 1737 } 1738 1739 } 1740 1741 if (mSampleSizes.empty()) { 1742 err = ERROR_MALFORMED; 1743 } else if (OK != checkCodecSpecificData()) { 1744 err = ERROR_MALFORMED; 1745 } 1746 mOwner->trackProgressStatus(this, -1, err); 1747 1748 // Last chunk 1749 if (mOwner->numTracks() == 1) { 1750 addOneStscTableEntry(1, mNumSamples); 1751 } else if (!mChunkSamples.empty()) { 1752 addOneStscTableEntry(++nChunks, mChunkSamples.size()); 1753 bufferChunk(timestampUs); 1754 } 1755 1756 // We don't really know how long the last frame lasts, since 1757 // there is no frame time after it, just repeat the previous 1758 // frame's duration. 1759 if (mNumSamples == 1) { 1760 lastDurationUs = 0; // A single sample's duration 1761 } else { 1762 ++sampleCount; // Count for the last sample 1763 } 1764 addOneSttsTableEntry(sampleCount, lastDurationUs); 1765 mTrackDurationUs += lastDurationUs; 1766 mReachedEOS = true; 1767 LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s", 1768 count, nZeroLengthFrames, mNumSamples, mIsAudio? "audio": "video"); 1769 1770 logStatisticalData(mIsAudio); 1771 if (err == ERROR_END_OF_STREAM) { 1772 return OK; 1773 } 1774 return err; 1775} 1776 1777void MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) { 1778 LOGV("trackProgressStatus: %lld us", timeUs); 1779 if (mTrackEveryTimeDurationUs > 0 && 1780 timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 1781 LOGV("Fire time tracking progress status at %lld us", timeUs); 1782 mOwner->trackProgressStatus(this, timeUs - mPreviousTrackTimeUs, err); 1783 mPreviousTrackTimeUs = timeUs; 1784 } 1785} 1786 1787void MPEG4Writer::trackProgressStatus( 1788 const MPEG4Writer::Track* track, int64_t timeUs, status_t err) { 1789 Mutex::Autolock lock(mLock); 1790 int32_t nTracks = mTracks.size(); 1791 CHECK(nTracks >= 1); 1792 CHECK(nTracks < 64); // Arbitrary number 1793 1794 int32_t trackNum = 0; 1795#if 0 1796 // In the worst case, we can put the trackNum 1797 // along with MEDIA_RECORDER_INFO_COMPLETION_STATUS 1798 // to report the progress. 1799 for (List<Track *>::iterator it = mTracks.begin(); 1800 it != mTracks.end(); ++it, ++trackNum) { 1801 if (track == (*it)) { 1802 break; 1803 } 1804 } 1805#endif 1806 CHECK(trackNum < nTracks); 1807 trackNum <<= 16; 1808 1809 // Error notification 1810 // Do not consider ERROR_END_OF_STREAM an error 1811 if (err != OK && err != ERROR_END_OF_STREAM) { 1812 notify(MEDIA_RECORDER_EVENT_ERROR, 1813 trackNum | MEDIA_RECORDER_ERROR_UNKNOWN, 1814 err); 1815 return; 1816 } 1817 1818 if (timeUs == -1) { 1819 // Send completion notification 1820 notify(MEDIA_RECORDER_EVENT_INFO, 1821 trackNum | MEDIA_RECORDER_INFO_COMPLETION_STATUS, 1822 err); 1823 return; 1824 } else { 1825 // Send progress status 1826 notify(MEDIA_RECORDER_EVENT_INFO, 1827 trackNum | MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS, 1828 timeUs / 1000); 1829 } 1830} 1831 1832void MPEG4Writer::Track::findMinAvgMaxSampleDurationMs( 1833 int32_t *min, int32_t *avg, int32_t *max) { 1834 CHECK(!mSampleSizes.empty()); 1835 int32_t avgSampleDurationMs = mTrackDurationUs / 1000 / mNumSamples; 1836 int32_t minSampleDurationMs = 0x7FFFFFFF; 1837 int32_t maxSampleDurationMs = 0; 1838 for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin(); 1839 it != mSttsTableEntries.end(); ++it) { 1840 int32_t sampleDurationMs = 1841 (static_cast<int32_t>(it->sampleDurationUs) + 500) / 1000; 1842 if (sampleDurationMs > maxSampleDurationMs) { 1843 maxSampleDurationMs = sampleDurationMs; 1844 } else if (sampleDurationMs < minSampleDurationMs) { 1845 minSampleDurationMs = sampleDurationMs; 1846 } 1847 LOGI("sample duration: %d ms", sampleDurationMs); 1848 } 1849 CHECK(minSampleDurationMs != 0); 1850 CHECK(avgSampleDurationMs != 0); 1851 CHECK(maxSampleDurationMs != 0); 1852 *min = minSampleDurationMs; 1853 *avg = avgSampleDurationMs; 1854 *max = maxSampleDurationMs; 1855} 1856 1857// Don't count the last duration 1858void MPEG4Writer::Track::findMinMaxChunkDurations(int64_t *min, int64_t *max) { 1859 int64_t duration = mOwner->interleaveDuration(); 1860 int64_t minChunkDuration = duration; 1861 int64_t maxChunkDuration = duration; 1862 if (mChunkDurations.size() > 1) { 1863 for (List<int64_t>::iterator it = mChunkDurations.begin(); 1864 it != --mChunkDurations.end(); ++it) { 1865 if (minChunkDuration > (*it)) { 1866 minChunkDuration = (*it); 1867 } else if (maxChunkDuration < (*it)) { 1868 maxChunkDuration = (*it); 1869 } 1870 } 1871 } 1872 *min = minChunkDuration; 1873 *max = maxChunkDuration; 1874} 1875 1876void MPEG4Writer::Track::logStatisticalData(bool isAudio) { 1877 if (mTrackDurationUs <= 0 || mSampleSizes.empty()) { 1878 LOGI("nothing is recorded"); 1879 return; 1880 } 1881 1882 bool collectStats = collectStatisticalData(); 1883 1884 if (collectStats) { 1885 LOGI("%s track - duration %lld us, total %d frames", 1886 isAudio? "audio": "video", mTrackDurationUs, 1887 mNumSamples); 1888 int32_t min, avg, max; 1889 findMinAvgMaxSampleDurationMs(&min, &avg, &max); 1890 LOGI("min/avg/max sample duration (ms): %d/%d/%d", min, avg, max); 1891 if (!isAudio) { 1892 float avgFps = 1000.0 / avg; 1893 float minFps = 1000.0 / max; 1894 float maxFps = 1000.0 / min; 1895 LOGI("min/avg/max frame rate (fps): %.2f/%.2f/%.2f", 1896 minFps, avgFps, maxFps); 1897 } 1898 1899 int64_t totalBytes = 0; 1900 for (List<size_t>::iterator it = mSampleSizes.begin(); 1901 it != mSampleSizes.end(); ++it) { 1902 totalBytes += (*it); 1903 } 1904 float bitRate = (totalBytes * 8000000.0) / mTrackDurationUs; 1905 LOGI("avg bit rate (bps): %.2f", bitRate); 1906 1907 int64_t duration = mOwner->interleaveDuration(); 1908 if (duration != 0) { // If interleaving is enabled 1909 int64_t minChunk, maxChunk; 1910 findMinMaxChunkDurations(&minChunk, &maxChunk); 1911 LOGI("min/avg/max chunk duration (ms): %lld/%lld/%lld", 1912 minChunk, duration, maxChunk); 1913 } 1914 } 1915} 1916 1917void MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) { 1918 LOGV("setDriftTimeUs: %lld us", driftTimeUs); 1919 Mutex::Autolock autolock(mLock); 1920 mDriftTimeUs = driftTimeUs; 1921} 1922 1923int64_t MPEG4Writer::getDriftTimeUs() { 1924 LOGV("getDriftTimeUs: %lld us", mDriftTimeUs); 1925 Mutex::Autolock autolock(mLock); 1926 return mDriftTimeUs; 1927} 1928 1929void MPEG4Writer::Track::bufferChunk(int64_t timestampUs) { 1930 LOGV("bufferChunk"); 1931 1932 Chunk chunk(this, timestampUs, mChunkSamples); 1933 mOwner->bufferChunk(chunk); 1934 mChunkSamples.clear(); 1935} 1936 1937int64_t MPEG4Writer::Track::getDurationUs() const { 1938 return mTrackDurationUs; 1939} 1940 1941int64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 1942 return mEstimatedTrackSizeBytes; 1943} 1944 1945status_t MPEG4Writer::Track::checkCodecSpecificData() const { 1946 const char *mime; 1947 CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 1948 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) || 1949 !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) || 1950 !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 1951 if (!mCodecSpecificData || 1952 mCodecSpecificDataSize <= 0) { 1953 // Missing codec specific data 1954 return ERROR_MALFORMED; 1955 } 1956 } else { 1957 if (mCodecSpecificData || 1958 mCodecSpecificDataSize > 0) { 1959 // Unexepected codec specific data found 1960 return ERROR_MALFORMED; 1961 } 1962 } 1963 return OK; 1964} 1965 1966void MPEG4Writer::Track::writeTrackHeader( 1967 int32_t trackID, bool use32BitOffset) { 1968 const char *mime; 1969 bool success = mMeta->findCString(kKeyMIMEType, &mime); 1970 CHECK(success); 1971 1972 LOGV("%s track time scale: %d", 1973 mIsAudio? "Audio": "Video", mTimeScale); 1974 1975 time_t now = time(NULL); 1976 int32_t mvhdTimeScale = mOwner->getTimeScale(); 1977 int64_t trakDurationUs = getDurationUs(); 1978 1979 mOwner->beginBox("trak"); 1980 1981 mOwner->beginBox("tkhd"); 1982 // Flags = 7 to indicate that the track is enabled, and 1983 // part of the presentation 1984 mOwner->writeInt32(0x07); // version=0, flags=7 1985 mOwner->writeInt32(now); // creation time 1986 mOwner->writeInt32(now); // modification time 1987 mOwner->writeInt32(trackID); 1988 mOwner->writeInt32(0); // reserved 1989 int32_t tkhdDuration = 1990 (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 1991 mOwner->writeInt32(tkhdDuration); // in mvhd timescale 1992 mOwner->writeInt32(0); // reserved 1993 mOwner->writeInt32(0); // reserved 1994 mOwner->writeInt16(0); // layer 1995 mOwner->writeInt16(0); // alternate group 1996 mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume 1997 mOwner->writeInt16(0); // reserved 1998 1999 mOwner->writeInt32(0x10000); // matrix 2000 mOwner->writeInt32(0); 2001 mOwner->writeInt32(0); 2002 mOwner->writeInt32(0); 2003 mOwner->writeInt32(0x10000); 2004 mOwner->writeInt32(0); 2005 mOwner->writeInt32(0); 2006 mOwner->writeInt32(0); 2007 mOwner->writeInt32(0x40000000); 2008 2009 if (mIsAudio) { 2010 mOwner->writeInt32(0); 2011 mOwner->writeInt32(0); 2012 } else { 2013 int32_t width, height; 2014 bool success = mMeta->findInt32(kKeyWidth, &width); 2015 success = success && mMeta->findInt32(kKeyHeight, &height); 2016 CHECK(success); 2017 2018 mOwner->writeInt32(width << 16); // 32-bit fixed-point value 2019 mOwner->writeInt32(height << 16); // 32-bit fixed-point value 2020 } 2021 mOwner->endBox(); // tkhd 2022 2023 int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 2024 if (mStartTimestampUs != moovStartTimeUs) { 2025 mOwner->beginBox("edts"); 2026 mOwner->beginBox("elst"); 2027 mOwner->writeInt32(0); // version=0, flags=0: 32-bit time 2028 mOwner->writeInt32(2); // never ends with an empty list 2029 2030 // First elst entry: specify the starting time offset 2031 int64_t offsetUs = mStartTimestampUs - moovStartTimeUs; 2032 int32_t seg = (offsetUs * mvhdTimeScale + 5E5) / 1E6; 2033 mOwner->writeInt32(seg); // in mvhd timecale 2034 mOwner->writeInt32(-1); // starting time offset 2035 mOwner->writeInt32(1 << 16); // rate = 1.0 2036 2037 // Second elst entry: specify the track duration 2038 seg = (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 2039 mOwner->writeInt32(seg); // in mvhd timescale 2040 mOwner->writeInt32(0); 2041 mOwner->writeInt32(1 << 16); 2042 mOwner->endBox(); 2043 mOwner->endBox(); 2044 } 2045 2046 mOwner->beginBox("mdia"); 2047 2048 mOwner->beginBox("mdhd"); 2049 mOwner->writeInt32(0); // version=0, flags=0 2050 mOwner->writeInt32(now); // creation time 2051 mOwner->writeInt32(now); // modification time 2052 mOwner->writeInt32(mTimeScale); // media timescale 2053 int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6; 2054 mOwner->writeInt32(mdhdDuration); // use media timescale 2055 // Language follows the three letter standard ISO-639-2/T 2056 // 'e', 'n', 'g' for "English", for instance. 2057 // Each character is packed as the difference between its ASCII value and 0x60. 2058 // For "English", these are 00101, 01110, 00111. 2059 // XXX: Where is the padding bit located: 0x15C7? 2060 mOwner->writeInt16(0); // language code 2061 mOwner->writeInt16(0); // predefined 2062 mOwner->endBox(); 2063 2064 mOwner->beginBox("hdlr"); 2065 mOwner->writeInt32(0); // version=0, flags=0 2066 mOwner->writeInt32(0); // component type: should be mhlr 2067 mOwner->writeFourcc(mIsAudio ? "soun" : "vide"); // component subtype 2068 mOwner->writeInt32(0); // reserved 2069 mOwner->writeInt32(0); // reserved 2070 mOwner->writeInt32(0); // reserved 2071 // Removing "r" for the name string just makes the string 4 byte aligned 2072 mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle"); // name 2073 mOwner->endBox(); 2074 2075 mOwner->beginBox("minf"); 2076 if (mIsAudio) { 2077 mOwner->beginBox("smhd"); 2078 mOwner->writeInt32(0); // version=0, flags=0 2079 mOwner->writeInt16(0); // balance 2080 mOwner->writeInt16(0); // reserved 2081 mOwner->endBox(); 2082 } else { 2083 mOwner->beginBox("vmhd"); 2084 mOwner->writeInt32(0x01); // version=0, flags=1 2085 mOwner->writeInt16(0); // graphics mode 2086 mOwner->writeInt16(0); // opcolor 2087 mOwner->writeInt16(0); 2088 mOwner->writeInt16(0); 2089 mOwner->endBox(); 2090 } 2091 2092 mOwner->beginBox("dinf"); 2093 mOwner->beginBox("dref"); 2094 mOwner->writeInt32(0); // version=0, flags=0 2095 mOwner->writeInt32(1); // entry count (either url or urn) 2096 // The table index here refers to the sample description index 2097 // in the sample table entries. 2098 mOwner->beginBox("url "); 2099 mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 2100 mOwner->endBox(); // url 2101 mOwner->endBox(); // dref 2102 mOwner->endBox(); // dinf 2103 2104 mOwner->beginBox("stbl"); 2105 2106 mOwner->beginBox("stsd"); 2107 mOwner->writeInt32(0); // version=0, flags=0 2108 mOwner->writeInt32(1); // entry count 2109 if (mIsAudio) { 2110 const char *fourcc = NULL; 2111 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 2112 fourcc = "samr"; 2113 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 2114 fourcc = "sawb"; 2115 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2116 fourcc = "mp4a"; 2117 } else { 2118 LOGE("Unknown mime type '%s'.", mime); 2119 CHECK(!"should not be here, unknown mime type."); 2120 } 2121 2122 mOwner->beginBox(fourcc); // audio format 2123 mOwner->writeInt32(0); // reserved 2124 mOwner->writeInt16(0); // reserved 2125 mOwner->writeInt16(0x1); // data ref index 2126 mOwner->writeInt32(0); // reserved 2127 mOwner->writeInt32(0); // reserved 2128 int32_t nChannels; 2129 CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 2130 mOwner->writeInt16(nChannels); // channel count 2131 mOwner->writeInt16(16); // sample size 2132 mOwner->writeInt16(0); // predefined 2133 mOwner->writeInt16(0); // reserved 2134 2135 int32_t samplerate; 2136 bool success = mMeta->findInt32(kKeySampleRate, &samplerate); 2137 CHECK(success); 2138 mOwner->writeInt32(samplerate << 16); 2139 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2140 mOwner->beginBox("esds"); 2141 CHECK(mCodecSpecificData); 2142 CHECK(mCodecSpecificDataSize > 0); 2143 2144 mOwner->writeInt32(0); // version=0, flags=0 2145 mOwner->writeInt8(0x03); // ES_DescrTag 2146 mOwner->writeInt8(23 + mCodecSpecificDataSize); 2147 mOwner->writeInt16(0x0000);// ES_ID 2148 mOwner->writeInt8(0x00); 2149 2150 mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2151 mOwner->writeInt8(15 + mCodecSpecificDataSize); 2152 mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 2153 mOwner->writeInt8(0x15); // streamType AudioStream 2154 2155 mOwner->writeInt16(0x03); // XXX 2156 mOwner->writeInt8(0x00); // buffer size 24-bit 2157 mOwner->writeInt32(96000); // max bit rate 2158 mOwner->writeInt32(96000); // avg bit rate 2159 2160 mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2161 mOwner->writeInt8(mCodecSpecificDataSize); 2162 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2163 2164 static const uint8_t kData2[] = { 2165 0x06, // SLConfigDescriptorTag 2166 0x01, 2167 0x02 2168 }; 2169 mOwner->write(kData2, sizeof(kData2)); 2170 2171 mOwner->endBox(); // esds 2172 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) || 2173 !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 2174 // 3gpp2 Spec AMRSampleEntry fields 2175 mOwner->beginBox("damr"); 2176 mOwner->writeCString(" "); // vendor: 4 bytes 2177 mOwner->writeInt8(0); // decoder version 2178 mOwner->writeInt16(0x83FF); // mode set: all enabled 2179 mOwner->writeInt8(0); // mode change period 2180 mOwner->writeInt8(1); // frames per sample 2181 mOwner->endBox(); 2182 } 2183 mOwner->endBox(); 2184 } else { 2185 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2186 mOwner->beginBox("mp4v"); 2187 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2188 mOwner->beginBox("s263"); 2189 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2190 mOwner->beginBox("avc1"); 2191 } else { 2192 LOGE("Unknown mime type '%s'.", mime); 2193 CHECK(!"should not be here, unknown mime type."); 2194 } 2195 2196 mOwner->writeInt32(0); // reserved 2197 mOwner->writeInt16(0); // reserved 2198 mOwner->writeInt16(1); // data ref index 2199 mOwner->writeInt16(0); // predefined 2200 mOwner->writeInt16(0); // reserved 2201 mOwner->writeInt32(0); // predefined 2202 mOwner->writeInt32(0); // predefined 2203 mOwner->writeInt32(0); // predefined 2204 2205 int32_t width, height; 2206 bool success = mMeta->findInt32(kKeyWidth, &width); 2207 success = success && mMeta->findInt32(kKeyHeight, &height); 2208 CHECK(success); 2209 2210 mOwner->writeInt16(width); 2211 mOwner->writeInt16(height); 2212 mOwner->writeInt32(0x480000); // horiz resolution 2213 mOwner->writeInt32(0x480000); // vert resolution 2214 mOwner->writeInt32(0); // reserved 2215 mOwner->writeInt16(1); // frame count 2216 mOwner->write(" ", 32); 2217 mOwner->writeInt16(0x18); // depth 2218 mOwner->writeInt16(-1); // predefined 2219 2220 CHECK(23 + mCodecSpecificDataSize < 128); 2221 2222 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2223 CHECK(mCodecSpecificData); 2224 CHECK(mCodecSpecificDataSize > 0); 2225 mOwner->beginBox("esds"); 2226 2227 mOwner->writeInt32(0); // version=0, flags=0 2228 2229 mOwner->writeInt8(0x03); // ES_DescrTag 2230 mOwner->writeInt8(23 + mCodecSpecificDataSize); 2231 mOwner->writeInt16(0x0000); // ES_ID 2232 mOwner->writeInt8(0x1f); 2233 2234 mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2235 mOwner->writeInt8(15 + mCodecSpecificDataSize); 2236 mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 2237 mOwner->writeInt8(0x11); // streamType VisualStream 2238 2239 static const uint8_t kData[] = { 2240 0x01, 0x77, 0x00, 2241 0x00, 0x03, 0xe8, 0x00, 2242 0x00, 0x03, 0xe8, 0x00 2243 }; 2244 mOwner->write(kData, sizeof(kData)); 2245 2246 mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2247 2248 mOwner->writeInt8(mCodecSpecificDataSize); 2249 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2250 2251 static const uint8_t kData2[] = { 2252 0x06, // SLConfigDescriptorTag 2253 0x01, 2254 0x02 2255 }; 2256 mOwner->write(kData2, sizeof(kData2)); 2257 2258 mOwner->endBox(); // esds 2259 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2260 mOwner->beginBox("d263"); 2261 2262 mOwner->writeInt32(0); // vendor 2263 mOwner->writeInt8(0); // decoder version 2264 mOwner->writeInt8(10); // level: 10 2265 mOwner->writeInt8(0); // profile: 0 2266 2267 mOwner->endBox(); // d263 2268 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2269 CHECK(mCodecSpecificData); 2270 CHECK(mCodecSpecificDataSize > 0); 2271 mOwner->beginBox("avcC"); 2272 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2273 mOwner->endBox(); // avcC 2274 } 2275 2276 mOwner->beginBox("pasp"); 2277 // This is useful if the pixel is not square 2278 mOwner->writeInt32(1 << 16); // hspacing 2279 mOwner->writeInt32(1 << 16); // vspacing 2280 mOwner->endBox(); // pasp 2281 mOwner->endBox(); // mp4v, s263 or avc1 2282 } 2283 mOwner->endBox(); // stsd 2284 2285 mOwner->beginBox("stts"); 2286 mOwner->writeInt32(0); // version=0, flags=0 2287 mOwner->writeInt32(mNumSttsTableEntries); 2288 int64_t prevTimestampUs = 0; 2289 for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin(); 2290 it != mSttsTableEntries.end(); ++it) { 2291 mOwner->writeInt32(it->sampleCount); 2292 2293 // Make sure that we are calculating the sample duration the exactly 2294 // same way as we made decision on how to create stts entries. 2295 int64_t currTimestampUs = prevTimestampUs + it->sampleDurationUs; 2296 int32_t dur = ((currTimestampUs * mTimeScale + 500000LL) / 1000000LL - 2297 (prevTimestampUs * mTimeScale + 500000LL) / 1000000LL); 2298 prevTimestampUs += (it->sampleCount * it->sampleDurationUs); 2299 2300 mOwner->writeInt32(dur); 2301 } 2302 mOwner->endBox(); // stts 2303 2304 if (!mIsAudio) { 2305 mOwner->beginBox("stss"); 2306 mOwner->writeInt32(0); // version=0, flags=0 2307 mOwner->writeInt32(mNumStssTableEntries); // number of sync frames 2308 for (List<int32_t>::iterator it = mStssTableEntries.begin(); 2309 it != mStssTableEntries.end(); ++it) { 2310 mOwner->writeInt32(*it); 2311 } 2312 mOwner->endBox(); // stss 2313 } 2314 2315 mOwner->beginBox("stsz"); 2316 mOwner->writeInt32(0); // version=0, flags=0 2317 if (mSamplesHaveSameSize) { 2318 List<size_t>::iterator it = mSampleSizes.begin(); 2319 mOwner->writeInt32(*it); // default sample size 2320 } else { 2321 mOwner->writeInt32(0); 2322 } 2323 mOwner->writeInt32(mNumSamples); 2324 if (!mSamplesHaveSameSize) { 2325 for (List<size_t>::iterator it = mSampleSizes.begin(); 2326 it != mSampleSizes.end(); ++it) { 2327 mOwner->writeInt32(*it); 2328 } 2329 } 2330 mOwner->endBox(); // stsz 2331 2332 mOwner->beginBox("stsc"); 2333 mOwner->writeInt32(0); // version=0, flags=0 2334 mOwner->writeInt32(mNumStscTableEntries); 2335 for (List<StscTableEntry>::iterator it = mStscTableEntries.begin(); 2336 it != mStscTableEntries.end(); ++it) { 2337 mOwner->writeInt32(it->firstChunk); 2338 mOwner->writeInt32(it->samplesPerChunk); 2339 mOwner->writeInt32(it->sampleDescriptionId); 2340 } 2341 mOwner->endBox(); // stsc 2342 mOwner->beginBox(use32BitOffset? "stco": "co64"); 2343 mOwner->writeInt32(0); // version=0, flags=0 2344 mOwner->writeInt32(mNumStcoTableEntries); 2345 for (List<off_t>::iterator it = mChunkOffsets.begin(); 2346 it != mChunkOffsets.end(); ++it) { 2347 if (use32BitOffset) { 2348 mOwner->writeInt32(static_cast<int32_t>(*it)); 2349 } else { 2350 mOwner->writeInt64((*it)); 2351 } 2352 } 2353 mOwner->endBox(); // stco or co64 2354 2355 mOwner->endBox(); // stbl 2356 mOwner->endBox(); // minf 2357 mOwner->endBox(); // mdia 2358 mOwner->endBox(); // trak 2359} 2360 2361} // namespace android 2362