MPEG4Writer.cpp revision 4f86a980fee1880dca61b828599fa6d76755a485
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("Frame arrives too late!"); 1528#if 0 1529 // Drop the late frame. 1530 copy->release(); 1531 copy = NULL; 1532 continue; 1533#else 1534 // Don't drop the late frame, since dropping a frame may cause 1535 // problems later during playback 1536 1537 // The idea here is to avoid having two or more samples with the 1538 // same timestamp in the output file. 1539 if (mTimeScale >= 1000000LL) { 1540 timestampUs += 1; 1541 } else { 1542 timestampUs += (1000000LL + (mTimeScale >> 1)) / mTimeScale; 1543 } 1544#endif 1545 } 1546 } 1547 1548 LOGV("time stamp: %lld and previous paused duration %lld", 1549 timestampUs, previousPausedDurationUs); 1550 if (timestampUs > mTrackDurationUs) { 1551 mTrackDurationUs = timestampUs; 1552 } 1553 1554 mSampleSizes.push_back(sampleSize); 1555 ++mNumSamples; 1556 if (mNumSamples > 2) { 1557 // We need to use the time scale based ticks, rather than the 1558 // timestamp itself to determine whether we have to use a new 1559 // stts entry, since we may have rounding errors. 1560 // The calculation is intended to reduce the accumulated 1561 // rounding errors. 1562 currDurationTicks = 1563 ((timestampUs * mTimeScale + 500000LL) / 1000000LL - 1564 (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL); 1565 1566 if (currDurationTicks != lastDurationTicks) { 1567 SttsTableEntry sttsEntry(sampleCount, lastDurationUs); 1568 mSttsTableEntries.push_back(sttsEntry); 1569 sampleCount = 1; 1570 } else { 1571 ++sampleCount; 1572 } 1573 } 1574 if (mSamplesHaveSameSize) { 1575 if (mNumSamples >= 2 && previousSampleSize != sampleSize) { 1576 mSamplesHaveSameSize = false; 1577 } 1578 previousSampleSize = sampleSize; 1579 } 1580 lastDurationUs = timestampUs - lastTimestampUs; 1581 lastDurationTicks = currDurationTicks; 1582 lastTimestampUs = timestampUs; 1583 if (mIsRealTimeRecording && mIsAudio) { 1584 wallClockTimeUs = systemTime() / 1000; 1585 int64_t wallClockDurationUs = wallClockTimeUs - lastWallClockTimeUs; 1586 if (mNumSamples > 2) { 1587 mOwner->addDriftTimeUs(lastDurationUs - wallClockDurationUs); 1588 } 1589 lastWallClockTimeUs = wallClockTimeUs; 1590 } 1591 1592 if (isSync != 0) { 1593 mStssTableEntries.push_back(mNumSamples); 1594 } 1595 1596 if (mTrackingProgressStatus) { 1597 if (mPreviousTrackTimeUs <= 0) { 1598 mPreviousTrackTimeUs = mStartTimestampUs; 1599 } 1600 trackProgressStatus(timestampUs); 1601 } 1602 if (mOwner->numTracks() == 1) { 1603 off_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy) 1604 : mOwner->addSample_l(copy); 1605 if (mChunkOffsets.empty()) { 1606 mChunkOffsets.push_back(offset); 1607 } 1608 copy->release(); 1609 copy = NULL; 1610 continue; 1611 } 1612 1613 mChunkSamples.push_back(copy); 1614 if (interleaveDurationUs == 0) { 1615 StscTableEntry stscEntry(++nChunks, 1, 1); 1616 mStscTableEntries.push_back(stscEntry); 1617 bufferChunk(timestampUs); 1618 } else { 1619 if (chunkTimestampUs == 0) { 1620 chunkTimestampUs = timestampUs; 1621 } else { 1622 if (timestampUs - chunkTimestampUs > interleaveDurationUs) { 1623 ++nChunks; 1624 if (collectStats) { 1625 mChunkDurations.push_back(timestampUs - chunkTimestampUs); 1626 } 1627 if (nChunks == 1 || // First chunk 1628 (--(mStscTableEntries.end()))->samplesPerChunk != 1629 mChunkSamples.size()) { 1630 StscTableEntry stscEntry(nChunks, 1631 mChunkSamples.size(), 1); 1632 mStscTableEntries.push_back(stscEntry); 1633 } 1634 bufferChunk(timestampUs); 1635 chunkTimestampUs = timestampUs; 1636 } 1637 } 1638 } 1639 1640 } 1641 1642 if (mSampleSizes.empty()) { 1643 err = ERROR_MALFORMED; 1644 } else if (OK != checkCodecSpecificData()) { 1645 err = ERROR_MALFORMED; 1646 } 1647 mOwner->trackProgressStatus(this, -1, err); 1648 1649 // Last chunk 1650 if (mOwner->numTracks() == 1) { 1651 StscTableEntry stscEntry(1, mNumSamples, 1); 1652 mStscTableEntries.push_back(stscEntry); 1653 } else if (!mChunkSamples.empty()) { 1654 ++nChunks; 1655 StscTableEntry stscEntry(nChunks, mChunkSamples.size(), 1); 1656 mStscTableEntries.push_back(stscEntry); 1657 bufferChunk(timestampUs); 1658 } 1659 1660 // We don't really know how long the last frame lasts, since 1661 // there is no frame time after it, just repeat the previous 1662 // frame's duration. 1663 if (mNumSamples == 1) { 1664 lastDurationUs = 0; // A single sample's duration 1665 } else { 1666 ++sampleCount; // Count for the last sample 1667 } 1668 SttsTableEntry sttsEntry(sampleCount, lastDurationUs); 1669 mSttsTableEntries.push_back(sttsEntry); 1670 mTrackDurationUs += lastDurationUs; 1671 mReachedEOS = true; 1672 LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. Max write time: %lld us - %s", 1673 count, nZeroLengthFrames, mNumSamples, mMaxWriteTimeUs, mIsAudio? "audio": "video"); 1674 1675 logStatisticalData(mIsAudio); 1676 if (err == ERROR_END_OF_STREAM) { 1677 return OK; 1678 } 1679 return err; 1680} 1681 1682void MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) { 1683 LOGV("trackProgressStatus: %lld us", timeUs); 1684 if (mTrackEveryTimeDurationUs > 0 && 1685 timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 1686 LOGV("Fire time tracking progress status at %lld us", timeUs); 1687 mOwner->trackProgressStatus(this, timeUs - mPreviousTrackTimeUs, err); 1688 mPreviousTrackTimeUs = timeUs; 1689 } 1690} 1691 1692void MPEG4Writer::trackProgressStatus( 1693 const MPEG4Writer::Track* track, int64_t timeUs, status_t err) { 1694 Mutex::Autolock lock(mLock); 1695 int32_t nTracks = mTracks.size(); 1696 CHECK(nTracks >= 1); 1697 CHECK(nTracks < 64); // Arbitrary number 1698 1699 int32_t trackNum = 0; 1700#if 0 1701 // In the worst case, we can put the trackNum 1702 // along with MEDIA_RECORDER_INFO_COMPLETION_STATUS 1703 // to report the progress. 1704 for (List<Track *>::iterator it = mTracks.begin(); 1705 it != mTracks.end(); ++it, ++trackNum) { 1706 if (track == (*it)) { 1707 break; 1708 } 1709 } 1710#endif 1711 CHECK(trackNum < nTracks); 1712 trackNum <<= 16; 1713 1714 // Error notification 1715 // Do not consider ERROR_END_OF_STREAM an error 1716 if (err != OK && err != ERROR_END_OF_STREAM) { 1717 notify(MEDIA_RECORDER_EVENT_ERROR, 1718 trackNum | MEDIA_RECORDER_ERROR_UNKNOWN, 1719 err); 1720 return; 1721 } 1722 1723 if (timeUs == -1) { 1724 // Send completion notification 1725 notify(MEDIA_RECORDER_EVENT_INFO, 1726 trackNum | MEDIA_RECORDER_INFO_COMPLETION_STATUS, 1727 err); 1728 return; 1729 } else { 1730 // Send progress status 1731 notify(MEDIA_RECORDER_EVENT_INFO, 1732 trackNum | MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS, 1733 timeUs / 1000); 1734 } 1735} 1736 1737void MPEG4Writer::Track::findMinAvgMaxSampleDurationMs( 1738 int32_t *min, int32_t *avg, int32_t *max) { 1739 CHECK(!mSampleSizes.empty()); 1740 int32_t avgSampleDurationMs = mTrackDurationUs / 1000 / mNumSamples; 1741 int32_t minSampleDurationMs = 0x7FFFFFFF; 1742 int32_t maxSampleDurationMs = 0; 1743 for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin(); 1744 it != mSttsTableEntries.end(); ++it) { 1745 int32_t sampleDurationMs = 1746 (static_cast<int32_t>(it->sampleDurationUs) + 500) / 1000; 1747 if (sampleDurationMs > maxSampleDurationMs) { 1748 maxSampleDurationMs = sampleDurationMs; 1749 } else if (sampleDurationMs < minSampleDurationMs) { 1750 minSampleDurationMs = sampleDurationMs; 1751 } 1752 LOGI("sample duration: %d ms", sampleDurationMs); 1753 } 1754 CHECK(minSampleDurationMs != 0); 1755 CHECK(avgSampleDurationMs != 0); 1756 CHECK(maxSampleDurationMs != 0); 1757 *min = minSampleDurationMs; 1758 *avg = avgSampleDurationMs; 1759 *max = maxSampleDurationMs; 1760} 1761 1762// Don't count the last duration 1763void MPEG4Writer::Track::findMinMaxChunkDurations(int64_t *min, int64_t *max) { 1764 int64_t duration = mOwner->interleaveDuration(); 1765 int64_t minChunkDuration = duration; 1766 int64_t maxChunkDuration = duration; 1767 if (mChunkDurations.size() > 1) { 1768 for (List<int64_t>::iterator it = mChunkDurations.begin(); 1769 it != --mChunkDurations.end(); ++it) { 1770 if (minChunkDuration > (*it)) { 1771 minChunkDuration = (*it); 1772 } else if (maxChunkDuration < (*it)) { 1773 maxChunkDuration = (*it); 1774 } 1775 } 1776 } 1777 *min = minChunkDuration; 1778 *max = maxChunkDuration; 1779} 1780 1781void MPEG4Writer::Track::logStatisticalData(bool isAudio) { 1782 if (mTrackDurationUs <= 0 || mSampleSizes.empty()) { 1783 LOGI("nothing is recorded"); 1784 return; 1785 } 1786 1787 bool collectStats = collectStatisticalData(); 1788 1789 if (collectStats) { 1790 LOGI("%s track - duration %lld us, total %d frames", 1791 isAudio? "audio": "video", mTrackDurationUs, 1792 mNumSamples); 1793 int32_t min, avg, max; 1794 findMinAvgMaxSampleDurationMs(&min, &avg, &max); 1795 LOGI("min/avg/max sample duration (ms): %d/%d/%d", min, avg, max); 1796 if (!isAudio) { 1797 float avgFps = 1000.0 / avg; 1798 float minFps = 1000.0 / max; 1799 float maxFps = 1000.0 / min; 1800 LOGI("min/avg/max frame rate (fps): %.2f/%.2f/%.2f", 1801 minFps, avgFps, maxFps); 1802 } 1803 1804 int64_t totalBytes = 0; 1805 for (List<size_t>::iterator it = mSampleSizes.begin(); 1806 it != mSampleSizes.end(); ++it) { 1807 totalBytes += (*it); 1808 } 1809 float bitRate = (totalBytes * 8000000.0) / mTrackDurationUs; 1810 LOGI("avg bit rate (bps): %.2f", bitRate); 1811 1812 int64_t duration = mOwner->interleaveDuration(); 1813 if (duration != 0) { // If interleaving is enabled 1814 int64_t minChunk, maxChunk; 1815 findMinMaxChunkDurations(&minChunk, &maxChunk); 1816 LOGI("min/avg/max chunk duration (ms): %lld/%lld/%lld", 1817 minChunk, duration, maxChunk); 1818 } 1819 } 1820} 1821 1822void MPEG4Writer::addDriftTimeUs(int64_t driftTimeUs) { 1823 LOGV("addDriftTimeUs: %lld us", driftTimeUs); 1824 Mutex::Autolock autolock(mLock); 1825 mDriftTimeUs += driftTimeUs; 1826} 1827 1828int64_t MPEG4Writer::getDriftTimeUs() { 1829 LOGV("getDriftTimeUs: %lld us", mDriftTimeUs); 1830 Mutex::Autolock autolock(mLock); 1831 return mDriftTimeUs; 1832} 1833 1834void MPEG4Writer::Track::bufferChunk(int64_t timestampUs) { 1835 LOGV("bufferChunk"); 1836 1837 int64_t startTimeUs = systemTime() / 1000; 1838 Chunk chunk(this, timestampUs, mChunkSamples); 1839 mOwner->bufferChunk(chunk); 1840 mChunkSamples.clear(); 1841 int64_t endTimeUs = systemTime() / 1000; 1842 if (mMaxWriteTimeUs < endTimeUs - startTimeUs) { 1843 mMaxWriteTimeUs = endTimeUs - startTimeUs; 1844 } 1845} 1846 1847int64_t MPEG4Writer::Track::getDurationUs() const { 1848 return mTrackDurationUs; 1849} 1850 1851int64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 1852 return mEstimatedTrackSizeBytes; 1853} 1854 1855status_t MPEG4Writer::Track::checkCodecSpecificData() const { 1856 const char *mime; 1857 CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 1858 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) || 1859 !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) || 1860 !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 1861 if (!mCodecSpecificData || 1862 mCodecSpecificDataSize <= 0) { 1863 // Missing codec specific data 1864 return ERROR_MALFORMED; 1865 } 1866 } else { 1867 if (mCodecSpecificData || 1868 mCodecSpecificDataSize > 0) { 1869 // Unexepected codec specific data found 1870 return ERROR_MALFORMED; 1871 } 1872 } 1873 return OK; 1874} 1875 1876void MPEG4Writer::Track::writeTrackHeader( 1877 int32_t trackID, bool use32BitOffset) { 1878 const char *mime; 1879 bool success = mMeta->findCString(kKeyMIMEType, &mime); 1880 CHECK(success); 1881 1882 LOGV("%s track time scale: %d", 1883 mIsAudio? "Audio": "Video", mTimeScale); 1884 1885 time_t now = time(NULL); 1886 int32_t mvhdTimeScale = mOwner->getTimeScale(); 1887 int64_t trakDurationUs = getDurationUs(); 1888 1889 mOwner->beginBox("trak"); 1890 1891 mOwner->beginBox("tkhd"); 1892 // Flags = 7 to indicate that the track is enabled, and 1893 // part of the presentation 1894 mOwner->writeInt32(0x07); // version=0, flags=7 1895 mOwner->writeInt32(now); // creation time 1896 mOwner->writeInt32(now); // modification time 1897 mOwner->writeInt32(trackID); 1898 mOwner->writeInt32(0); // reserved 1899 int32_t tkhdDuration = 1900 (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 1901 mOwner->writeInt32(tkhdDuration); // in mvhd timescale 1902 mOwner->writeInt32(0); // reserved 1903 mOwner->writeInt32(0); // reserved 1904 mOwner->writeInt16(0); // layer 1905 mOwner->writeInt16(0); // alternate group 1906 mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume 1907 mOwner->writeInt16(0); // reserved 1908 1909 mOwner->writeInt32(0x10000); // matrix 1910 mOwner->writeInt32(0); 1911 mOwner->writeInt32(0); 1912 mOwner->writeInt32(0); 1913 mOwner->writeInt32(0x10000); 1914 mOwner->writeInt32(0); 1915 mOwner->writeInt32(0); 1916 mOwner->writeInt32(0); 1917 mOwner->writeInt32(0x40000000); 1918 1919 if (mIsAudio) { 1920 mOwner->writeInt32(0); 1921 mOwner->writeInt32(0); 1922 } else { 1923 int32_t width, height; 1924 bool success = mMeta->findInt32(kKeyWidth, &width); 1925 success = success && mMeta->findInt32(kKeyHeight, &height); 1926 CHECK(success); 1927 1928 mOwner->writeInt32(width << 16); // 32-bit fixed-point value 1929 mOwner->writeInt32(height << 16); // 32-bit fixed-point value 1930 } 1931 mOwner->endBox(); // tkhd 1932 1933 int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 1934 if (mStartTimestampUs != moovStartTimeUs) { 1935 mOwner->beginBox("edts"); 1936 mOwner->beginBox("elst"); 1937 mOwner->writeInt32(0); // version=0, flags=0: 32-bit time 1938 mOwner->writeInt32(2); // never ends with an empty list 1939 1940 // First elst entry: specify the starting time offset 1941 int64_t offsetUs = mStartTimestampUs - moovStartTimeUs; 1942 int32_t seg = (offsetUs * mvhdTimeScale + 5E5) / 1E6; 1943 mOwner->writeInt32(seg); // in mvhd timecale 1944 mOwner->writeInt32(-1); // starting time offset 1945 mOwner->writeInt32(1 << 16); // rate = 1.0 1946 1947 // Second elst entry: specify the track duration 1948 seg = (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 1949 mOwner->writeInt32(seg); // in mvhd timescale 1950 mOwner->writeInt32(0); 1951 mOwner->writeInt32(1 << 16); 1952 mOwner->endBox(); 1953 mOwner->endBox(); 1954 } 1955 1956 mOwner->beginBox("mdia"); 1957 1958 mOwner->beginBox("mdhd"); 1959 mOwner->writeInt32(0); // version=0, flags=0 1960 mOwner->writeInt32(now); // creation time 1961 mOwner->writeInt32(now); // modification time 1962 mOwner->writeInt32(mTimeScale); // media timescale 1963 int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6; 1964 mOwner->writeInt32(mdhdDuration); // use media timescale 1965 // Language follows the three letter standard ISO-639-2/T 1966 // 'e', 'n', 'g' for "English", for instance. 1967 // Each character is packed as the difference between its ASCII value and 0x60. 1968 // For "English", these are 00101, 01110, 00111. 1969 // XXX: Where is the padding bit located: 0x15C7? 1970 mOwner->writeInt16(0); // language code 1971 mOwner->writeInt16(0); // predefined 1972 mOwner->endBox(); 1973 1974 mOwner->beginBox("hdlr"); 1975 mOwner->writeInt32(0); // version=0, flags=0 1976 mOwner->writeInt32(0); // component type: should be mhlr 1977 mOwner->writeFourcc(mIsAudio ? "soun" : "vide"); // component subtype 1978 mOwner->writeInt32(0); // reserved 1979 mOwner->writeInt32(0); // reserved 1980 mOwner->writeInt32(0); // reserved 1981 // Removing "r" for the name string just makes the string 4 byte aligned 1982 mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle"); // name 1983 mOwner->endBox(); 1984 1985 mOwner->beginBox("minf"); 1986 if (mIsAudio) { 1987 mOwner->beginBox("smhd"); 1988 mOwner->writeInt32(0); // version=0, flags=0 1989 mOwner->writeInt16(0); // balance 1990 mOwner->writeInt16(0); // reserved 1991 mOwner->endBox(); 1992 } else { 1993 mOwner->beginBox("vmhd"); 1994 mOwner->writeInt32(0x01); // version=0, flags=1 1995 mOwner->writeInt16(0); // graphics mode 1996 mOwner->writeInt16(0); // opcolor 1997 mOwner->writeInt16(0); 1998 mOwner->writeInt16(0); 1999 mOwner->endBox(); 2000 } 2001 2002 mOwner->beginBox("dinf"); 2003 mOwner->beginBox("dref"); 2004 mOwner->writeInt32(0); // version=0, flags=0 2005 mOwner->writeInt32(1); // entry count (either url or urn) 2006 // The table index here refers to the sample description index 2007 // in the sample table entries. 2008 mOwner->beginBox("url "); 2009 mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 2010 mOwner->endBox(); // url 2011 mOwner->endBox(); // dref 2012 mOwner->endBox(); // dinf 2013 2014 mOwner->beginBox("stbl"); 2015 2016 mOwner->beginBox("stsd"); 2017 mOwner->writeInt32(0); // version=0, flags=0 2018 mOwner->writeInt32(1); // entry count 2019 if (mIsAudio) { 2020 const char *fourcc = NULL; 2021 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 2022 fourcc = "samr"; 2023 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 2024 fourcc = "sawb"; 2025 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2026 fourcc = "mp4a"; 2027 } else { 2028 LOGE("Unknown mime type '%s'.", mime); 2029 CHECK(!"should not be here, unknown mime type."); 2030 } 2031 2032 mOwner->beginBox(fourcc); // audio format 2033 mOwner->writeInt32(0); // reserved 2034 mOwner->writeInt16(0); // reserved 2035 mOwner->writeInt16(0x1); // data ref index 2036 mOwner->writeInt32(0); // reserved 2037 mOwner->writeInt32(0); // reserved 2038 int32_t nChannels; 2039 CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 2040 mOwner->writeInt16(nChannels); // channel count 2041 mOwner->writeInt16(16); // sample size 2042 mOwner->writeInt16(0); // predefined 2043 mOwner->writeInt16(0); // reserved 2044 2045 int32_t samplerate; 2046 bool success = mMeta->findInt32(kKeySampleRate, &samplerate); 2047 CHECK(success); 2048 mOwner->writeInt32(samplerate << 16); 2049 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2050 mOwner->beginBox("esds"); 2051 CHECK(mCodecSpecificData); 2052 CHECK(mCodecSpecificDataSize > 0); 2053 2054 mOwner->writeInt32(0); // version=0, flags=0 2055 mOwner->writeInt8(0x03); // ES_DescrTag 2056 mOwner->writeInt8(23 + mCodecSpecificDataSize); 2057 mOwner->writeInt16(0x0000);// ES_ID 2058 mOwner->writeInt8(0x00); 2059 2060 mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2061 mOwner->writeInt8(15 + mCodecSpecificDataSize); 2062 mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 2063 mOwner->writeInt8(0x15); // streamType AudioStream 2064 2065 mOwner->writeInt16(0x03); // XXX 2066 mOwner->writeInt8(0x00); // buffer size 24-bit 2067 mOwner->writeInt32(96000); // max bit rate 2068 mOwner->writeInt32(96000); // avg bit rate 2069 2070 mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2071 mOwner->writeInt8(mCodecSpecificDataSize); 2072 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2073 2074 static const uint8_t kData2[] = { 2075 0x06, // SLConfigDescriptorTag 2076 0x01, 2077 0x02 2078 }; 2079 mOwner->write(kData2, sizeof(kData2)); 2080 2081 mOwner->endBox(); // esds 2082 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) || 2083 !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 2084 // 3gpp2 Spec AMRSampleEntry fields 2085 mOwner->beginBox("damr"); 2086 mOwner->writeCString(" "); // vendor: 4 bytes 2087 mOwner->writeInt8(0); // decoder version 2088 mOwner->writeInt16(0x83FF); // mode set: all enabled 2089 mOwner->writeInt8(0); // mode change period 2090 mOwner->writeInt8(1); // frames per sample 2091 mOwner->endBox(); 2092 } 2093 mOwner->endBox(); 2094 } else { 2095 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2096 mOwner->beginBox("mp4v"); 2097 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2098 mOwner->beginBox("s263"); 2099 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2100 mOwner->beginBox("avc1"); 2101 } else { 2102 LOGE("Unknown mime type '%s'.", mime); 2103 CHECK(!"should not be here, unknown mime type."); 2104 } 2105 2106 mOwner->writeInt32(0); // reserved 2107 mOwner->writeInt16(0); // reserved 2108 mOwner->writeInt16(1); // data ref index 2109 mOwner->writeInt16(0); // predefined 2110 mOwner->writeInt16(0); // reserved 2111 mOwner->writeInt32(0); // predefined 2112 mOwner->writeInt32(0); // predefined 2113 mOwner->writeInt32(0); // predefined 2114 2115 int32_t width, height; 2116 bool success = mMeta->findInt32(kKeyWidth, &width); 2117 success = success && mMeta->findInt32(kKeyHeight, &height); 2118 CHECK(success); 2119 2120 mOwner->writeInt16(width); 2121 mOwner->writeInt16(height); 2122 mOwner->writeInt32(0x480000); // horiz resolution 2123 mOwner->writeInt32(0x480000); // vert resolution 2124 mOwner->writeInt32(0); // reserved 2125 mOwner->writeInt16(1); // frame count 2126 mOwner->write(" ", 32); 2127 mOwner->writeInt16(0x18); // depth 2128 mOwner->writeInt16(-1); // predefined 2129 2130 CHECK(23 + mCodecSpecificDataSize < 128); 2131 2132 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2133 CHECK(mCodecSpecificData); 2134 CHECK(mCodecSpecificDataSize > 0); 2135 mOwner->beginBox("esds"); 2136 2137 mOwner->writeInt32(0); // version=0, flags=0 2138 2139 mOwner->writeInt8(0x03); // ES_DescrTag 2140 mOwner->writeInt8(23 + mCodecSpecificDataSize); 2141 mOwner->writeInt16(0x0000); // ES_ID 2142 mOwner->writeInt8(0x1f); 2143 2144 mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2145 mOwner->writeInt8(15 + mCodecSpecificDataSize); 2146 mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 2147 mOwner->writeInt8(0x11); // streamType VisualStream 2148 2149 static const uint8_t kData[] = { 2150 0x01, 0x77, 0x00, 2151 0x00, 0x03, 0xe8, 0x00, 2152 0x00, 0x03, 0xe8, 0x00 2153 }; 2154 mOwner->write(kData, sizeof(kData)); 2155 2156 mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2157 2158 mOwner->writeInt8(mCodecSpecificDataSize); 2159 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2160 2161 static const uint8_t kData2[] = { 2162 0x06, // SLConfigDescriptorTag 2163 0x01, 2164 0x02 2165 }; 2166 mOwner->write(kData2, sizeof(kData2)); 2167 2168 mOwner->endBox(); // esds 2169 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2170 mOwner->beginBox("d263"); 2171 2172 mOwner->writeInt32(0); // vendor 2173 mOwner->writeInt8(0); // decoder version 2174 mOwner->writeInt8(10); // level: 10 2175 mOwner->writeInt8(0); // profile: 0 2176 2177 mOwner->endBox(); // d263 2178 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2179 CHECK(mCodecSpecificData); 2180 CHECK(mCodecSpecificDataSize > 0); 2181 mOwner->beginBox("avcC"); 2182 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2183 mOwner->endBox(); // avcC 2184 } 2185 2186 mOwner->beginBox("pasp"); 2187 // This is useful if the pixel is not square 2188 mOwner->writeInt32(1 << 16); // hspacing 2189 mOwner->writeInt32(1 << 16); // vspacing 2190 mOwner->endBox(); // pasp 2191 mOwner->endBox(); // mp4v, s263 or avc1 2192 } 2193 mOwner->endBox(); // stsd 2194 2195 mOwner->beginBox("stts"); 2196 mOwner->writeInt32(0); // version=0, flags=0 2197 mOwner->writeInt32(mSttsTableEntries.size()); 2198 int64_t prevTimestampUs = 0; 2199 for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin(); 2200 it != mSttsTableEntries.end(); ++it) { 2201 mOwner->writeInt32(it->sampleCount); 2202 2203 // Make sure that we are calculating the sample duration the exactly 2204 // same way as we made decision on how to create stts entries. 2205 int64_t currTimestampUs = prevTimestampUs + it->sampleDurationUs; 2206 int32_t dur = ((currTimestampUs * mTimeScale + 500000LL) / 1000000LL - 2207 (prevTimestampUs * mTimeScale + 500000LL) / 1000000LL); 2208 prevTimestampUs += (it->sampleCount * it->sampleDurationUs); 2209 2210 mOwner->writeInt32(dur); 2211 } 2212 mOwner->endBox(); // stts 2213 2214 if (!mIsAudio) { 2215 mOwner->beginBox("stss"); 2216 mOwner->writeInt32(0); // version=0, flags=0 2217 mOwner->writeInt32(mStssTableEntries.size()); // number of sync frames 2218 for (List<int32_t>::iterator it = mStssTableEntries.begin(); 2219 it != mStssTableEntries.end(); ++it) { 2220 mOwner->writeInt32(*it); 2221 } 2222 mOwner->endBox(); // stss 2223 } 2224 2225 mOwner->beginBox("stsz"); 2226 mOwner->writeInt32(0); // version=0, flags=0 2227 if (mSamplesHaveSameSize) { 2228 List<size_t>::iterator it = mSampleSizes.begin(); 2229 mOwner->writeInt32(*it); // default sample size 2230 } else { 2231 mOwner->writeInt32(0); 2232 } 2233 mOwner->writeInt32(mNumSamples); 2234 if (!mSamplesHaveSameSize) { 2235 for (List<size_t>::iterator it = mSampleSizes.begin(); 2236 it != mSampleSizes.end(); ++it) { 2237 mOwner->writeInt32(*it); 2238 } 2239 } 2240 mOwner->endBox(); // stsz 2241 2242 mOwner->beginBox("stsc"); 2243 mOwner->writeInt32(0); // version=0, flags=0 2244 mOwner->writeInt32(mStscTableEntries.size()); 2245 for (List<StscTableEntry>::iterator it = mStscTableEntries.begin(); 2246 it != mStscTableEntries.end(); ++it) { 2247 mOwner->writeInt32(it->firstChunk); 2248 mOwner->writeInt32(it->samplesPerChunk); 2249 mOwner->writeInt32(it->sampleDescriptionId); 2250 } 2251 mOwner->endBox(); // stsc 2252 mOwner->beginBox(use32BitOffset? "stco": "co64"); 2253 mOwner->writeInt32(0); // version=0, flags=0 2254 mOwner->writeInt32(mChunkOffsets.size()); 2255 for (List<off_t>::iterator it = mChunkOffsets.begin(); 2256 it != mChunkOffsets.end(); ++it) { 2257 if (use32BitOffset) { 2258 mOwner->writeInt32(static_cast<int32_t>(*it)); 2259 } else { 2260 mOwner->writeInt64((*it)); 2261 } 2262 } 2263 mOwner->endBox(); // stco or co64 2264 2265 mOwner->endBox(); // stbl 2266 mOwner->endBox(); // minf 2267 mOwner->endBox(); // mdia 2268 mOwner->endBox(); // trak 2269} 2270 2271} // namespace android 2272