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