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