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