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