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