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