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