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
20 #include <arpa/inet.h>
21 #include <fcntl.h>
22 #include <inttypes.h>
23 #include <pthread.h>
24 #include <sys/prctl.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <unistd.h>
28
29 #include <utils/Log.h>
30
31 #include <media/stagefright/foundation/ADebug.h>
32 #include <media/stagefright/foundation/AMessage.h>
33 #include <media/stagefright/foundation/ColorUtils.h>
34 #include <media/stagefright/MPEG4Writer.h>
35 #include <media/stagefright/MediaBuffer.h>
36 #include <media/stagefright/MetaData.h>
37 #include <media/stagefright/MediaDefs.h>
38 #include <media/stagefright/MediaErrors.h>
39 #include <media/stagefright/MediaSource.h>
40 #include <media/stagefright/Utils.h>
41 #include <media/mediarecorder.h>
42 #include <cutils/properties.h>
43
44 #include "include/ESDS.h"
45 #include "include/HevcUtils.h"
46
47 #ifndef __predict_false
48 #define __predict_false(exp) __builtin_expect((exp) != 0, 0)
49 #endif
50
51 #define WARN_UNLESS(condition, message, ...) \
52 ( (__predict_false(condition)) ? false : ({ \
53 ALOGW("Condition %s failed " message, #condition, ##__VA_ARGS__); \
54 true; \
55 }))
56
57 namespace android {
58
59 static const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024;
60 static const int64_t kMax32BitFileSize = 0x00ffffffffLL; // 2^32-1 : max FAT32
61 // filesystem file size
62 // used by most SD cards
63 static const uint8_t kNalUnitTypeSeqParamSet = 0x07;
64 static const uint8_t kNalUnitTypePicParamSet = 0x08;
65 static const int64_t kInitialDelayTimeUs = 700000LL;
66
67 static const char kMetaKey_Version[] = "com.android.version";
68 #ifdef SHOW_MODEL_BUILD
69 static const char kMetaKey_Model[] = "com.android.model";
70 static const char kMetaKey_Build[] = "com.android.build";
71 #endif
72 static const char kMetaKey_CaptureFps[] = "com.android.capture.fps";
73
74 static const uint8_t kMandatoryHevcNalUnitTypes[3] = {
75 kHevcNalUnitTypeVps,
76 kHevcNalUnitTypeSps,
77 kHevcNalUnitTypePps,
78 };
79 static const uint8_t kHevcNalUnitTypes[5] = {
80 kHevcNalUnitTypeVps,
81 kHevcNalUnitTypeSps,
82 kHevcNalUnitTypePps,
83 kHevcNalUnitTypePrefixSei,
84 kHevcNalUnitTypeSuffixSei,
85 };
86 /* uncomment to include model and build in meta */
87 //#define SHOW_MODEL_BUILD 1
88
89 class MPEG4Writer::Track {
90 public:
91 Track(MPEG4Writer *owner, const sp<IMediaSource> &source, size_t trackId);
92
93 ~Track();
94
95 status_t start(MetaData *params);
96 status_t stop();
97 status_t pause();
98 bool reachedEOS();
99
100 int64_t getDurationUs() const;
101 int64_t getEstimatedTrackSizeBytes() const;
102 void writeTrackHeader(bool use32BitOffset = true);
103 void bufferChunk(int64_t timestampUs);
isAvc() const104 bool isAvc() const { return mIsAvc; }
isHevc() const105 bool isHevc() const { return mIsHevc; }
isAudio() const106 bool isAudio() const { return mIsAudio; }
isMPEG4() const107 bool isMPEG4() const { return mIsMPEG4; }
108 void addChunkOffset(off64_t offset);
getTrackId() const109 int32_t getTrackId() const { return mTrackId; }
110 status_t dump(int fd, const Vector<String16>& args) const;
111 static const char *getFourCCForMime(const char *mime);
112
113 private:
114 enum {
115 kMaxCttsOffsetTimeUs = 1000000LL, // 1 second
116 kSampleArraySize = 1000,
117 };
118
119 // A helper class to handle faster write box with table entries
120 template<class TYPE>
121 struct ListTableEntries {
ListTableEntriesandroid::MPEG4Writer::Track::ListTableEntries122 ListTableEntries(uint32_t elementCapacity, uint32_t entryCapacity)
123 : mElementCapacity(elementCapacity),
124 mEntryCapacity(entryCapacity),
125 mTotalNumTableEntries(0),
126 mNumValuesInCurrEntry(0),
127 mCurrTableEntriesElement(NULL) {
128 CHECK_GT(mElementCapacity, 0);
129 CHECK_GT(mEntryCapacity, 0);
130 // Ensure no integer overflow on allocation in add().
131 CHECK_LT(mEntryCapacity, UINT32_MAX / mElementCapacity);
132 }
133
134 // Free the allocated memory.
~ListTableEntriesandroid::MPEG4Writer::Track::ListTableEntries135 ~ListTableEntries() {
136 while (!mTableEntryList.empty()) {
137 typename List<TYPE *>::iterator it = mTableEntryList.begin();
138 delete[] (*it);
139 mTableEntryList.erase(it);
140 }
141 }
142
143 // Replace the value at the given position by the given value.
144 // There must be an existing value at the given position.
145 // @arg value must be in network byte order
146 // @arg pos location the value must be in.
setandroid::MPEG4Writer::Track::ListTableEntries147 void set(const TYPE& value, uint32_t pos) {
148 CHECK_LT(pos, mTotalNumTableEntries * mEntryCapacity);
149
150 typename List<TYPE *>::iterator it = mTableEntryList.begin();
151 uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity));
152 while (it != mTableEntryList.end() && iterations > 0) {
153 ++it;
154 --iterations;
155 }
156 CHECK(it != mTableEntryList.end());
157 CHECK_EQ(iterations, 0);
158
159 (*it)[(pos % (mElementCapacity * mEntryCapacity))] = value;
160 }
161
162 // Get the value at the given position by the given value.
163 // @arg value the retrieved value at the position in network byte order.
164 // @arg pos location the value must be in.
165 // @return true if a value is found.
getandroid::MPEG4Writer::Track::ListTableEntries166 bool get(TYPE& value, uint32_t pos) const {
167 if (pos >= mTotalNumTableEntries * mEntryCapacity) {
168 return false;
169 }
170
171 typename List<TYPE *>::iterator it = mTableEntryList.begin();
172 uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity));
173 while (it != mTableEntryList.end() && iterations > 0) {
174 ++it;
175 --iterations;
176 }
177 CHECK(it != mTableEntryList.end());
178 CHECK_EQ(iterations, 0);
179
180 value = (*it)[(pos % (mElementCapacity * mEntryCapacity))];
181 return true;
182 }
183
184 // Store a single value.
185 // @arg value must be in network byte order.
addandroid::MPEG4Writer::Track::ListTableEntries186 void add(const TYPE& value) {
187 CHECK_LT(mNumValuesInCurrEntry, mElementCapacity);
188 uint32_t nEntries = mTotalNumTableEntries % mElementCapacity;
189 uint32_t nValues = mNumValuesInCurrEntry % mEntryCapacity;
190 if (nEntries == 0 && nValues == 0) {
191 mCurrTableEntriesElement = new TYPE[mEntryCapacity * mElementCapacity];
192 CHECK(mCurrTableEntriesElement != NULL);
193 mTableEntryList.push_back(mCurrTableEntriesElement);
194 }
195
196 uint32_t pos = nEntries * mEntryCapacity + nValues;
197 mCurrTableEntriesElement[pos] = value;
198
199 ++mNumValuesInCurrEntry;
200 if ((mNumValuesInCurrEntry % mEntryCapacity) == 0) {
201 ++mTotalNumTableEntries;
202 mNumValuesInCurrEntry = 0;
203 }
204 }
205
206 // Write out the table entries:
207 // 1. the number of entries goes first
208 // 2. followed by the values in the table enties in order
209 // @arg writer the writer to actual write to the storage
writeandroid::MPEG4Writer::Track::ListTableEntries210 void write(MPEG4Writer *writer) const {
211 CHECK_EQ(mNumValuesInCurrEntry % mEntryCapacity, 0);
212 uint32_t nEntries = mTotalNumTableEntries;
213 writer->writeInt32(nEntries);
214 for (typename List<TYPE *>::iterator it = mTableEntryList.begin();
215 it != mTableEntryList.end(); ++it) {
216 CHECK_GT(nEntries, 0);
217 if (nEntries >= mElementCapacity) {
218 writer->write(*it, sizeof(TYPE) * mEntryCapacity, mElementCapacity);
219 nEntries -= mElementCapacity;
220 } else {
221 writer->write(*it, sizeof(TYPE) * mEntryCapacity, nEntries);
222 break;
223 }
224 }
225 }
226
227 // Return the number of entries in the table.
countandroid::MPEG4Writer::Track::ListTableEntries228 uint32_t count() const { return mTotalNumTableEntries; }
229
230 private:
231 uint32_t mElementCapacity; // # entries in an element
232 uint32_t mEntryCapacity; // # of values in each entry
233 uint32_t mTotalNumTableEntries;
234 uint32_t mNumValuesInCurrEntry; // up to mEntryCapacity
235 TYPE *mCurrTableEntriesElement;
236 mutable List<TYPE *> mTableEntryList;
237
238 DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries);
239 };
240
241
242
243 MPEG4Writer *mOwner;
244 sp<MetaData> mMeta;
245 sp<IMediaSource> mSource;
246 volatile bool mDone;
247 volatile bool mPaused;
248 volatile bool mResumed;
249 volatile bool mStarted;
250 bool mIsAvc;
251 bool mIsHevc;
252 bool mIsAudio;
253 bool mIsMPEG4;
254 int32_t mTrackId;
255 int64_t mTrackDurationUs;
256 int64_t mMaxChunkDurationUs;
257
258 int64_t mEstimatedTrackSizeBytes;
259 int64_t mMdatSizeBytes;
260 int32_t mTimeScale;
261
262 pthread_t mThread;
263
264
265 List<MediaBuffer *> mChunkSamples;
266
267 bool mSamplesHaveSameSize;
268 ListTableEntries<uint32_t> *mStszTableEntries;
269
270 ListTableEntries<uint32_t> *mStcoTableEntries;
271 ListTableEntries<off64_t> *mCo64TableEntries;
272 ListTableEntries<uint32_t> *mStscTableEntries;
273 ListTableEntries<uint32_t> *mStssTableEntries;
274 ListTableEntries<uint32_t> *mSttsTableEntries;
275 ListTableEntries<uint32_t> *mCttsTableEntries;
276
277 int64_t mMinCttsOffsetTimeUs;
278 int64_t mMaxCttsOffsetTimeUs;
279
280 // Sequence parameter set or picture parameter set
281 struct AVCParamSet {
AVCParamSetandroid::MPEG4Writer::Track::AVCParamSet282 AVCParamSet(uint16_t length, const uint8_t *data)
283 : mLength(length), mData(data) {}
284
285 uint16_t mLength;
286 const uint8_t *mData;
287 };
288 List<AVCParamSet> mSeqParamSets;
289 List<AVCParamSet> mPicParamSets;
290 uint8_t mProfileIdc;
291 uint8_t mProfileCompatible;
292 uint8_t mLevelIdc;
293
294 void *mCodecSpecificData;
295 size_t mCodecSpecificDataSize;
296 bool mGotAllCodecSpecificData;
297 bool mTrackingProgressStatus;
298
299 bool mReachedEOS;
300 int64_t mStartTimestampUs;
301 int64_t mStartTimeRealUs;
302 int64_t mFirstSampleTimeRealUs;
303 int64_t mPreviousTrackTimeUs;
304 int64_t mTrackEveryTimeDurationUs;
305
306 // Update the audio track's drift information.
307 void updateDriftTime(const sp<MetaData>& meta);
308
309 int32_t getStartTimeOffsetScaledTime() const;
310
311 static void *ThreadWrapper(void *me);
312 status_t threadEntry();
313
314 const uint8_t *parseParamSet(
315 const uint8_t *data, size_t length, int type, size_t *paramSetLen);
316
317 status_t copyCodecSpecificData(const uint8_t *data, size_t size, size_t minLength = 0);
318
319 status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size);
320 status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size);
321 status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size);
322
323 status_t makeHEVCCodecSpecificData(const uint8_t *data, size_t size);
324 status_t copyHEVCCodecSpecificData(const uint8_t *data, size_t size);
325 status_t parseHEVCCodecSpecificData(
326 const uint8_t *data, size_t size, HevcParameterSets ¶mSets);
327
328 // Track authoring progress status
329 void trackProgressStatus(int64_t timeUs, status_t err = OK);
330 void initTrackingProgressStatus(MetaData *params);
331
332 void getCodecSpecificDataFromInputFormatIfPossible();
333
334 // Determine the track time scale
335 // If it is an audio track, try to use the sampling rate as
336 // the time scale; however, if user chooses the overwrite
337 // value, the user-supplied time scale will be used.
338 void setTimeScale();
339
340 // Simple validation on the codec specific data
341 status_t checkCodecSpecificData() const;
342 int32_t mRotation;
343
344 void updateTrackSizeEstimate();
345 void addOneStscTableEntry(size_t chunkId, size_t sampleId);
346 void addOneStssTableEntry(size_t sampleId);
347
348 // Duration is time scale based
349 void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
350 void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
351
352 bool isTrackMalFormed() const;
353 void sendTrackSummary(bool hasMultipleTracks);
354
355 // Write the boxes
356 void writeStcoBox(bool use32BitOffset);
357 void writeStscBox();
358 void writeStszBox();
359 void writeStssBox();
360 void writeSttsBox();
361 void writeCttsBox();
362 void writeD263Box();
363 void writePaspBox();
364 void writeAvccBox();
365 void writeHvccBox();
366 void writeUrlBox();
367 void writeDrefBox();
368 void writeDinfBox();
369 void writeDamrBox();
370 void writeMdhdBox(uint32_t now);
371 void writeSmhdBox();
372 void writeVmhdBox();
373 void writeHdlrBox();
374 void writeTkhdBox(uint32_t now);
375 void writeColrBox();
376 void writeMp4aEsdsBox();
377 void writeMp4vEsdsBox();
378 void writeAudioFourCCBox();
379 void writeVideoFourCCBox();
380 void writeStblBox(bool use32BitOffset);
381
382 Track(const Track &);
383 Track &operator=(const Track &);
384 };
385
MPEG4Writer(int fd)386 MPEG4Writer::MPEG4Writer(int fd)
387 : mFd(dup(fd)),
388 mInitCheck(mFd < 0? NO_INIT: OK),
389 mIsRealTimeRecording(true),
390 mUse4ByteNalLength(true),
391 mUse32BitOffset(true),
392 mIsFileSizeLimitExplicitlyRequested(false),
393 mPaused(false),
394 mStarted(false),
395 mWriterThreadStarted(false),
396 mOffset(0),
397 mMdatOffset(0),
398 mMoovBoxBuffer(NULL),
399 mMoovBoxBufferOffset(0),
400 mWriteMoovBoxToMemory(false),
401 mFreeBoxOffset(0),
402 mStreamableFile(false),
403 mEstimatedMoovBoxSize(0),
404 mMoovExtraSize(0),
405 mInterleaveDurationUs(1000000),
406 mTimeScale(-1),
407 mStartTimestampUs(-1ll),
408 mLatitudex10000(0),
409 mLongitudex10000(0),
410 mAreGeoTagsAvailable(false),
411 mStartTimeOffsetMs(-1),
412 mMetaKeys(new AMessage()) {
413 addDeviceMeta();
414
415 // Verify mFd is seekable
416 off64_t off = lseek64(mFd, 0, SEEK_SET);
417 if (off < 0) {
418 ALOGE("cannot seek mFd: %s (%d)", strerror(errno), errno);
419 release();
420 }
421 }
422
~MPEG4Writer()423 MPEG4Writer::~MPEG4Writer() {
424 reset();
425
426 while (!mTracks.empty()) {
427 List<Track *>::iterator it = mTracks.begin();
428 delete *it;
429 (*it) = NULL;
430 mTracks.erase(it);
431 }
432 mTracks.clear();
433 }
434
dump(int fd,const Vector<String16> & args)435 status_t MPEG4Writer::dump(
436 int fd, const Vector<String16>& args) {
437 const size_t SIZE = 256;
438 char buffer[SIZE];
439 String8 result;
440 snprintf(buffer, SIZE, " MPEG4Writer %p\n", this);
441 result.append(buffer);
442 snprintf(buffer, SIZE, " mStarted: %s\n", mStarted? "true": "false");
443 result.append(buffer);
444 ::write(fd, result.string(), result.size());
445 for (List<Track *>::iterator it = mTracks.begin();
446 it != mTracks.end(); ++it) {
447 (*it)->dump(fd, args);
448 }
449 return OK;
450 }
451
dump(int fd,const Vector<String16> &) const452 status_t MPEG4Writer::Track::dump(
453 int fd, const Vector<String16>& /* args */) const {
454 const size_t SIZE = 256;
455 char buffer[SIZE];
456 String8 result;
457 snprintf(buffer, SIZE, " %s track\n", mIsAudio? "Audio": "Video");
458 result.append(buffer);
459 snprintf(buffer, SIZE, " reached EOS: %s\n",
460 mReachedEOS? "true": "false");
461 result.append(buffer);
462 snprintf(buffer, SIZE, " frames encoded : %d\n", mStszTableEntries->count());
463 result.append(buffer);
464 snprintf(buffer, SIZE, " duration encoded : %" PRId64 " us\n", mTrackDurationUs);
465 result.append(buffer);
466 ::write(fd, result.string(), result.size());
467 return OK;
468 }
469
470 // static
getFourCCForMime(const char * mime)471 const char *MPEG4Writer::Track::getFourCCForMime(const char *mime) {
472 if (mime == NULL) {
473 return NULL;
474 }
475 if (!strncasecmp(mime, "audio/", 6)) {
476 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
477 return "samr";
478 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
479 return "sawb";
480 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
481 return "mp4a";
482 }
483 } else if (!strncasecmp(mime, "video/", 6)) {
484 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
485 return "mp4v";
486 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
487 return "s263";
488 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
489 return "avc1";
490 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
491 return "hvc1";
492 }
493 } else {
494 ALOGE("Track (%s) other than video or audio is not supported", mime);
495 }
496 return NULL;
497 }
498
addSource(const sp<IMediaSource> & source)499 status_t MPEG4Writer::addSource(const sp<IMediaSource> &source) {
500 Mutex::Autolock l(mLock);
501 if (mStarted) {
502 ALOGE("Attempt to add source AFTER recording is started");
503 return UNKNOWN_ERROR;
504 }
505
506 // At most 2 tracks can be supported.
507 if (mTracks.size() >= 2) {
508 ALOGE("Too many tracks (%zu) to add", mTracks.size());
509 return ERROR_UNSUPPORTED;
510 }
511
512 CHECK(source.get() != NULL);
513
514 const char *mime;
515 source->getFormat()->findCString(kKeyMIMEType, &mime);
516 bool isAudio = !strncasecmp(mime, "audio/", 6);
517 if (Track::getFourCCForMime(mime) == NULL) {
518 ALOGE("Unsupported mime '%s'", mime);
519 return ERROR_UNSUPPORTED;
520 }
521
522 // At this point, we know the track to be added is either
523 // video or audio. Thus, we only need to check whether it
524 // is an audio track or not (if it is not, then it must be
525 // a video track).
526
527 // No more than one video or one audio track is supported.
528 for (List<Track*>::iterator it = mTracks.begin();
529 it != mTracks.end(); ++it) {
530 if ((*it)->isAudio() == isAudio) {
531 ALOGE("%s track already exists", isAudio? "Audio": "Video");
532 return ERROR_UNSUPPORTED;
533 }
534 }
535
536 // This is the first track of either audio or video.
537 // Go ahead to add the track.
538 Track *track = new Track(this, source, 1 + mTracks.size());
539 mTracks.push_back(track);
540
541 return OK;
542 }
543
startTracks(MetaData * params)544 status_t MPEG4Writer::startTracks(MetaData *params) {
545 if (mTracks.empty()) {
546 ALOGE("No source added");
547 return INVALID_OPERATION;
548 }
549
550 for (List<Track *>::iterator it = mTracks.begin();
551 it != mTracks.end(); ++it) {
552 status_t err = (*it)->start(params);
553
554 if (err != OK) {
555 for (List<Track *>::iterator it2 = mTracks.begin();
556 it2 != it; ++it2) {
557 (*it2)->stop();
558 }
559
560 return err;
561 }
562 }
563 return OK;
564 }
565
addDeviceMeta()566 void MPEG4Writer::addDeviceMeta() {
567 // add device info and estimate space in 'moov'
568 char val[PROPERTY_VALUE_MAX];
569 size_t n;
570 // meta size is estimated by adding up the following:
571 // - meta header structures, which occur only once (total 66 bytes)
572 // - size for each key, which consists of a fixed header (32 bytes),
573 // plus key length and data length.
574 mMoovExtraSize += 66;
575 if (property_get("ro.build.version.release", val, NULL)
576 && (n = strlen(val)) > 0) {
577 mMetaKeys->setString(kMetaKey_Version, val, n + 1);
578 mMoovExtraSize += sizeof(kMetaKey_Version) + n + 32;
579 }
580 #ifdef SHOW_MODEL_BUILD
581 if (property_get("ro.product.model", val, NULL)
582 && (n = strlen(val)) > 0) {
583 mMetaKeys->setString(kMetaKey_Model, val, n + 1);
584 mMoovExtraSize += sizeof(kMetaKey_Model) + n + 32;
585 }
586 if (property_get("ro.build.display.id", val, NULL)
587 && (n = strlen(val)) > 0) {
588 mMetaKeys->setString(kMetaKey_Build, val, n + 1);
589 mMoovExtraSize += sizeof(kMetaKey_Build) + n + 32;
590 }
591 #endif
592 }
593
estimateMoovBoxSize(int32_t bitRate)594 int64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
595 // This implementation is highly experimental/heurisitic.
596 //
597 // Statistical analysis shows that metadata usually accounts
598 // for a small portion of the total file size, usually < 0.6%.
599
600 // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2,
601 // where 1MB is the common file size limit for MMS application.
602 // The default MAX _MOOV_BOX_SIZE value is based on about 3
603 // minute video recording with a bit rate about 3 Mbps, because
604 // statistics also show that most of the video captured are going
605 // to be less than 3 minutes.
606
607 // If the estimation is wrong, we will pay the price of wasting
608 // some reserved space. This should not happen so often statistically.
609 static const int32_t factor = mUse32BitOffset? 1: 2;
610 static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024; // 3 KB
611 static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
612 int64_t size = MIN_MOOV_BOX_SIZE;
613
614 // Max file size limit is set
615 if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
616 size = mMaxFileSizeLimitBytes * 6 / 1000;
617 }
618
619 // Max file duration limit is set
620 if (mMaxFileDurationLimitUs != 0) {
621 if (bitRate > 0) {
622 int64_t size2 =
623 ((mMaxFileDurationLimitUs * bitRate * 6) / 1000 / 8000000);
624 if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
625 // When both file size and duration limits are set,
626 // we use the smaller limit of the two.
627 if (size > size2) {
628 size = size2;
629 }
630 } else {
631 // Only max file duration limit is set
632 size = size2;
633 }
634 }
635 }
636
637 if (size < MIN_MOOV_BOX_SIZE) {
638 size = MIN_MOOV_BOX_SIZE;
639 }
640
641 // Any long duration recording will be probably end up with
642 // non-streamable mp4 file.
643 if (size > MAX_MOOV_BOX_SIZE) {
644 size = MAX_MOOV_BOX_SIZE;
645 }
646
647 // Account for the extra stuff (Geo, meta keys, etc.)
648 size += mMoovExtraSize;
649
650 ALOGI("limits: %" PRId64 "/%" PRId64 " bytes/us, bit rate: %d bps and the"
651 " estimated moov size %" PRId64 " bytes",
652 mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
653 return factor * size;
654 }
655
start(MetaData * param)656 status_t MPEG4Writer::start(MetaData *param) {
657 if (mInitCheck != OK) {
658 return UNKNOWN_ERROR;
659 }
660
661 /*
662 * Check mMaxFileSizeLimitBytes at the beginning
663 * since mMaxFileSizeLimitBytes may be implicitly
664 * changed later for 32-bit file offset even if
665 * user does not ask to set it explicitly.
666 */
667 if (mMaxFileSizeLimitBytes != 0) {
668 mIsFileSizeLimitExplicitlyRequested = true;
669 }
670
671 int32_t use64BitOffset;
672 if (param &&
673 param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
674 use64BitOffset) {
675 mUse32BitOffset = false;
676 }
677
678 if (mUse32BitOffset) {
679 // Implicit 32 bit file size limit
680 if (mMaxFileSizeLimitBytes == 0) {
681 mMaxFileSizeLimitBytes = kMax32BitFileSize;
682 }
683
684 // If file size is set to be larger than the 32 bit file
685 // size limit, treat it as an error.
686 if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
687 ALOGW("32-bit file size limit (%" PRId64 " bytes) too big. "
688 "It is changed to %" PRId64 " bytes",
689 mMaxFileSizeLimitBytes, kMax32BitFileSize);
690 mMaxFileSizeLimitBytes = kMax32BitFileSize;
691 }
692 }
693
694 int32_t use2ByteNalLength;
695 if (param &&
696 param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) &&
697 use2ByteNalLength) {
698 mUse4ByteNalLength = false;
699 }
700
701 int32_t isRealTimeRecording;
702 if (param && param->findInt32(kKeyRealTimeRecording, &isRealTimeRecording)) {
703 mIsRealTimeRecording = isRealTimeRecording;
704 }
705
706 mStartTimestampUs = -1;
707
708 if (mStarted) {
709 if (mPaused) {
710 mPaused = false;
711 return startTracks(param);
712 }
713 return OK;
714 }
715
716 if (!param ||
717 !param->findInt32(kKeyTimeScale, &mTimeScale)) {
718 mTimeScale = 1000;
719 }
720 CHECK_GT(mTimeScale, 0);
721 ALOGV("movie time scale: %d", mTimeScale);
722
723 /*
724 * When the requested file size limit is small, the priority
725 * is to meet the file size limit requirement, rather than
726 * to make the file streamable. mStreamableFile does not tell
727 * whether the actual recorded file is streamable or not.
728 */
729 mStreamableFile =
730 (mMaxFileSizeLimitBytes != 0 &&
731 mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes);
732
733 /*
734 * mWriteMoovBoxToMemory is true if the amount of data in moov box is
735 * smaller than the reserved free space at the beginning of a file, AND
736 * when the content of moov box is constructed. Note that video/audio
737 * frame data is always written to the file but not in the memory.
738 *
739 * Before stop()/reset() is called, mWriteMoovBoxToMemory is always
740 * false. When reset() is called at the end of a recording session,
741 * Moov box needs to be constructed.
742 *
743 * 1) Right before a moov box is constructed, mWriteMoovBoxToMemory
744 * to set to mStreamableFile so that if
745 * the file is intended to be streamable, it is set to true;
746 * otherwise, it is set to false. When the value is set to false,
747 * all the content of the moov box is written immediately to
748 * the end of the file. When the value is set to true, all the
749 * content of the moov box is written to an in-memory cache,
750 * mMoovBoxBuffer, util the following condition happens. Note
751 * that the size of the in-memory cache is the same as the
752 * reserved free space at the beginning of the file.
753 *
754 * 2) While the data of the moov box is written to an in-memory
755 * cache, the data size is checked against the reserved space.
756 * If the data size surpasses the reserved space, subsequent moov
757 * data could no longer be hold in the in-memory cache. This also
758 * indicates that the reserved space was too small. At this point,
759 * _all_ moov data must be written to the end of the file.
760 * mWriteMoovBoxToMemory must be set to false to direct the write
761 * to the file.
762 *
763 * 3) If the data size in moov box is smaller than the reserved
764 * space after moov box is completely constructed, the in-memory
765 * cache copy of the moov box is written to the reserved free
766 * space. Thus, immediately after the moov is completedly
767 * constructed, mWriteMoovBoxToMemory is always set to false.
768 */
769 mWriteMoovBoxToMemory = false;
770 mMoovBoxBuffer = NULL;
771 mMoovBoxBufferOffset = 0;
772
773 writeFtypBox(param);
774
775 mFreeBoxOffset = mOffset;
776
777 if (mEstimatedMoovBoxSize == 0) {
778 int32_t bitRate = -1;
779 if (param) {
780 param->findInt32(kKeyBitRate, &bitRate);
781 }
782 mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
783 }
784 CHECK_GE(mEstimatedMoovBoxSize, 8);
785 if (mStreamableFile) {
786 // Reserve a 'free' box only for streamable file
787 lseek64(mFd, mFreeBoxOffset, SEEK_SET);
788 writeInt32(mEstimatedMoovBoxSize);
789 write("free", 4);
790 mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
791 } else {
792 mMdatOffset = mOffset;
793 }
794
795 mOffset = mMdatOffset;
796 lseek64(mFd, mMdatOffset, SEEK_SET);
797 if (mUse32BitOffset) {
798 write("????mdat", 8);
799 } else {
800 write("\x00\x00\x00\x01mdat????????", 16);
801 }
802
803 status_t err = startWriterThread();
804 if (err != OK) {
805 return err;
806 }
807
808 err = startTracks(param);
809 if (err != OK) {
810 return err;
811 }
812
813 mStarted = true;
814 return OK;
815 }
816
use32BitFileOffset() const817 bool MPEG4Writer::use32BitFileOffset() const {
818 return mUse32BitOffset;
819 }
820
pause()821 status_t MPEG4Writer::pause() {
822 if (mInitCheck != OK) {
823 return OK;
824 }
825 mPaused = true;
826 status_t err = OK;
827 for (List<Track *>::iterator it = mTracks.begin();
828 it != mTracks.end(); ++it) {
829 status_t status = (*it)->pause();
830 if (status != OK) {
831 err = status;
832 }
833 }
834 return err;
835 }
836
stopWriterThread()837 void MPEG4Writer::stopWriterThread() {
838 ALOGD("Stopping writer thread");
839 if (!mWriterThreadStarted) {
840 return;
841 }
842
843 {
844 Mutex::Autolock autolock(mLock);
845
846 mDone = true;
847 mChunkReadyCondition.signal();
848 }
849
850 void *dummy;
851 pthread_join(mThread, &dummy);
852 mWriterThreadStarted = false;
853 ALOGD("Writer thread stopped");
854 }
855
856 /*
857 * MP4 file standard defines a composition matrix:
858 * | a b u |
859 * | c d v |
860 * | x y w |
861 *
862 * the element in the matrix is stored in the following
863 * order: {a, b, u, c, d, v, x, y, w},
864 * where a, b, c, d, x, and y is in 16.16 format, while
865 * u, v and w is in 2.30 format.
866 */
writeCompositionMatrix(int degrees)867 void MPEG4Writer::writeCompositionMatrix(int degrees) {
868 ALOGV("writeCompositionMatrix");
869 uint32_t a = 0x00010000;
870 uint32_t b = 0;
871 uint32_t c = 0;
872 uint32_t d = 0x00010000;
873 switch (degrees) {
874 case 0:
875 break;
876 case 90:
877 a = 0;
878 b = 0x00010000;
879 c = 0xFFFF0000;
880 d = 0;
881 break;
882 case 180:
883 a = 0xFFFF0000;
884 d = 0xFFFF0000;
885 break;
886 case 270:
887 a = 0;
888 b = 0xFFFF0000;
889 c = 0x00010000;
890 d = 0;
891 break;
892 default:
893 CHECK(!"Should never reach this unknown rotation");
894 break;
895 }
896
897 writeInt32(a); // a
898 writeInt32(b); // b
899 writeInt32(0); // u
900 writeInt32(c); // c
901 writeInt32(d); // d
902 writeInt32(0); // v
903 writeInt32(0); // x
904 writeInt32(0); // y
905 writeInt32(0x40000000); // w
906 }
907
release()908 void MPEG4Writer::release() {
909 close(mFd);
910 mFd = -1;
911 mInitCheck = NO_INIT;
912 mStarted = false;
913 free(mMoovBoxBuffer);
914 mMoovBoxBuffer = NULL;
915 }
916
reset()917 status_t MPEG4Writer::reset() {
918 if (mInitCheck != OK) {
919 return OK;
920 } else {
921 if (!mWriterThreadStarted ||
922 !mStarted) {
923 if (mWriterThreadStarted) {
924 stopWriterThread();
925 }
926 release();
927 return OK;
928 }
929 }
930
931 status_t err = OK;
932 int64_t maxDurationUs = 0;
933 int64_t minDurationUs = 0x7fffffffffffffffLL;
934 for (List<Track *>::iterator it = mTracks.begin();
935 it != mTracks.end(); ++it) {
936 status_t status = (*it)->stop();
937 if (err == OK && status != OK) {
938 err = status;
939 }
940
941 int64_t durationUs = (*it)->getDurationUs();
942 if (durationUs > maxDurationUs) {
943 maxDurationUs = durationUs;
944 }
945 if (durationUs < minDurationUs) {
946 minDurationUs = durationUs;
947 }
948 }
949
950 if (mTracks.size() > 1) {
951 ALOGD("Duration from tracks range is [%" PRId64 ", %" PRId64 "] us",
952 minDurationUs, maxDurationUs);
953 }
954
955 stopWriterThread();
956
957 // Do not write out movie header on error.
958 if (err != OK) {
959 release();
960 return err;
961 }
962
963 // Fix up the size of the 'mdat' chunk.
964 if (mUse32BitOffset) {
965 lseek64(mFd, mMdatOffset, SEEK_SET);
966 uint32_t size = htonl(static_cast<uint32_t>(mOffset - mMdatOffset));
967 ::write(mFd, &size, 4);
968 } else {
969 lseek64(mFd, mMdatOffset + 8, SEEK_SET);
970 uint64_t size = mOffset - mMdatOffset;
971 size = hton64(size);
972 ::write(mFd, &size, 8);
973 }
974 lseek64(mFd, mOffset, SEEK_SET);
975
976 // Construct moov box now
977 mMoovBoxBufferOffset = 0;
978 mWriteMoovBoxToMemory = mStreamableFile;
979 if (mWriteMoovBoxToMemory) {
980 // There is no need to allocate in-memory cache
981 // for moov box if the file is not streamable.
982
983 mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
984 CHECK(mMoovBoxBuffer != NULL);
985 }
986 writeMoovBox(maxDurationUs);
987
988 // mWriteMoovBoxToMemory could be set to false in
989 // MPEG4Writer::write() method
990 if (mWriteMoovBoxToMemory) {
991 mWriteMoovBoxToMemory = false;
992 // Content of the moov box is saved in the cache, and the in-memory
993 // moov box needs to be written to the file in a single shot.
994
995 CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize);
996
997 // Moov box
998 lseek64(mFd, mFreeBoxOffset, SEEK_SET);
999 mOffset = mFreeBoxOffset;
1000 write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset);
1001
1002 // Free box
1003 lseek64(mFd, mOffset, SEEK_SET);
1004 writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
1005 write("free", 4);
1006 } else {
1007 ALOGI("The mp4 file will not be streamable.");
1008 }
1009
1010 // Free in-memory cache for moov box
1011 if (mMoovBoxBuffer != NULL) {
1012 free(mMoovBoxBuffer);
1013 mMoovBoxBuffer = NULL;
1014 mMoovBoxBufferOffset = 0;
1015 }
1016
1017 CHECK(mBoxes.empty());
1018
1019 release();
1020 return err;
1021 }
1022
getMpeg4Time()1023 uint32_t MPEG4Writer::getMpeg4Time() {
1024 time_t now = time(NULL);
1025 // MP4 file uses time counting seconds since midnight, Jan. 1, 1904
1026 // while time function returns Unix epoch values which starts
1027 // at 1970-01-01. Lets add the number of seconds between them
1028 static const uint32_t delta = (66 * 365 + 17) * (24 * 60 * 60);
1029 if (now < 0 || uint32_t(now) > UINT32_MAX - delta) {
1030 return 0;
1031 }
1032 uint32_t mpeg4Time = uint32_t(now) + delta;
1033 return mpeg4Time;
1034 }
1035
writeMvhdBox(int64_t durationUs)1036 void MPEG4Writer::writeMvhdBox(int64_t durationUs) {
1037 uint32_t now = getMpeg4Time();
1038 beginBox("mvhd");
1039 writeInt32(0); // version=0, flags=0
1040 writeInt32(now); // creation time
1041 writeInt32(now); // modification time
1042 writeInt32(mTimeScale); // mvhd timescale
1043 int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6;
1044 writeInt32(duration);
1045 writeInt32(0x10000); // rate: 1.0
1046 writeInt16(0x100); // volume
1047 writeInt16(0); // reserved
1048 writeInt32(0); // reserved
1049 writeInt32(0); // reserved
1050 writeCompositionMatrix(0); // matrix
1051 writeInt32(0); // predefined
1052 writeInt32(0); // predefined
1053 writeInt32(0); // predefined
1054 writeInt32(0); // predefined
1055 writeInt32(0); // predefined
1056 writeInt32(0); // predefined
1057 writeInt32(mTracks.size() + 1); // nextTrackID
1058 endBox(); // mvhd
1059 }
1060
writeMoovBox(int64_t durationUs)1061 void MPEG4Writer::writeMoovBox(int64_t durationUs) {
1062 beginBox("moov");
1063 writeMvhdBox(durationUs);
1064 if (mAreGeoTagsAvailable) {
1065 writeUdtaBox();
1066 }
1067 writeMetaBox();
1068 int32_t id = 1;
1069 for (List<Track *>::iterator it = mTracks.begin();
1070 it != mTracks.end(); ++it, ++id) {
1071 (*it)->writeTrackHeader(mUse32BitOffset);
1072 }
1073 endBox(); // moov
1074 }
1075
writeFtypBox(MetaData * param)1076 void MPEG4Writer::writeFtypBox(MetaData *param) {
1077 beginBox("ftyp");
1078
1079 int32_t fileType;
1080 if (param && param->findInt32(kKeyFileType, &fileType) &&
1081 fileType != OUTPUT_FORMAT_MPEG_4) {
1082 writeFourcc("3gp4");
1083 writeInt32(0);
1084 writeFourcc("isom");
1085 writeFourcc("3gp4");
1086 } else {
1087 writeFourcc("mp42");
1088 writeInt32(0);
1089 writeFourcc("isom");
1090 writeFourcc("mp42");
1091 }
1092
1093 endBox();
1094 }
1095
isTestModeEnabled()1096 static bool isTestModeEnabled() {
1097 #if (PROPERTY_VALUE_MAX < 5)
1098 #error "PROPERTY_VALUE_MAX must be at least 5"
1099 #endif
1100
1101 // Test mode is enabled only if rw.media.record.test system
1102 // property is enabled.
1103 char value[PROPERTY_VALUE_MAX];
1104 if (property_get("rw.media.record.test", value, NULL) &&
1105 (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) {
1106 return true;
1107 }
1108 return false;
1109 }
1110
sendSessionSummary()1111 void MPEG4Writer::sendSessionSummary() {
1112 // Send session summary only if test mode is enabled
1113 if (!isTestModeEnabled()) {
1114 return;
1115 }
1116
1117 for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
1118 it != mChunkInfos.end(); ++it) {
1119 int trackNum = it->mTrack->getTrackId() << 28;
1120 notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
1121 trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS,
1122 it->mMaxInterChunkDurUs);
1123 }
1124 }
1125
setInterleaveDuration(uint32_t durationUs)1126 status_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
1127 mInterleaveDurationUs = durationUs;
1128 return OK;
1129 }
1130
lock()1131 void MPEG4Writer::lock() {
1132 mLock.lock();
1133 }
1134
unlock()1135 void MPEG4Writer::unlock() {
1136 mLock.unlock();
1137 }
1138
addSample_l(MediaBuffer * buffer)1139 off64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
1140 off64_t old_offset = mOffset;
1141
1142 ::write(mFd,
1143 (const uint8_t *)buffer->data() + buffer->range_offset(),
1144 buffer->range_length());
1145
1146 mOffset += buffer->range_length();
1147
1148 return old_offset;
1149 }
1150
StripStartcode(MediaBuffer * buffer)1151 static void StripStartcode(MediaBuffer *buffer) {
1152 if (buffer->range_length() < 4) {
1153 return;
1154 }
1155
1156 const uint8_t *ptr =
1157 (const uint8_t *)buffer->data() + buffer->range_offset();
1158
1159 if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
1160 buffer->set_range(
1161 buffer->range_offset() + 4, buffer->range_length() - 4);
1162 }
1163 }
1164
addLengthPrefixedSample_l(MediaBuffer * buffer)1165 off64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
1166 off64_t old_offset = mOffset;
1167
1168 size_t length = buffer->range_length();
1169
1170 if (mUse4ByteNalLength) {
1171 uint8_t x = length >> 24;
1172 ::write(mFd, &x, 1);
1173 x = (length >> 16) & 0xff;
1174 ::write(mFd, &x, 1);
1175 x = (length >> 8) & 0xff;
1176 ::write(mFd, &x, 1);
1177 x = length & 0xff;
1178 ::write(mFd, &x, 1);
1179
1180 ::write(mFd,
1181 (const uint8_t *)buffer->data() + buffer->range_offset(),
1182 length);
1183
1184 mOffset += length + 4;
1185 } else {
1186 CHECK_LT(length, 65536);
1187
1188 uint8_t x = length >> 8;
1189 ::write(mFd, &x, 1);
1190 x = length & 0xff;
1191 ::write(mFd, &x, 1);
1192 ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length);
1193 mOffset += length + 2;
1194 }
1195
1196 return old_offset;
1197 }
1198
write(const void * ptr,size_t size,size_t nmemb)1199 size_t MPEG4Writer::write(
1200 const void *ptr, size_t size, size_t nmemb) {
1201
1202 const size_t bytes = size * nmemb;
1203 if (mWriteMoovBoxToMemory) {
1204
1205 off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
1206 if (moovBoxSize > mEstimatedMoovBoxSize) {
1207 // The reserved moov box at the beginning of the file
1208 // is not big enough. Moov box should be written to
1209 // the end of the file from now on, but not to the
1210 // in-memory cache.
1211
1212 // We write partial moov box that is in the memory to
1213 // the file first.
1214 for (List<off64_t>::iterator it = mBoxes.begin();
1215 it != mBoxes.end(); ++it) {
1216 (*it) += mOffset;
1217 }
1218 lseek64(mFd, mOffset, SEEK_SET);
1219 ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset);
1220 ::write(mFd, ptr, bytes);
1221 mOffset += (bytes + mMoovBoxBufferOffset);
1222
1223 // All subsequent moov box content will be written
1224 // to the end of the file.
1225 mWriteMoovBoxToMemory = false;
1226 } else {
1227 memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
1228 mMoovBoxBufferOffset += bytes;
1229 }
1230 } else {
1231 ::write(mFd, ptr, size * nmemb);
1232 mOffset += bytes;
1233 }
1234 return bytes;
1235 }
1236
beginBox(uint32_t id)1237 void MPEG4Writer::beginBox(uint32_t id) {
1238 mBoxes.push_back(mWriteMoovBoxToMemory?
1239 mMoovBoxBufferOffset: mOffset);
1240
1241 writeInt32(0);
1242 writeInt32(id);
1243 }
1244
beginBox(const char * fourcc)1245 void MPEG4Writer::beginBox(const char *fourcc) {
1246 CHECK_EQ(strlen(fourcc), 4);
1247
1248 mBoxes.push_back(mWriteMoovBoxToMemory?
1249 mMoovBoxBufferOffset: mOffset);
1250
1251 writeInt32(0);
1252 writeFourcc(fourcc);
1253 }
1254
endBox()1255 void MPEG4Writer::endBox() {
1256 CHECK(!mBoxes.empty());
1257
1258 off64_t offset = *--mBoxes.end();
1259 mBoxes.erase(--mBoxes.end());
1260
1261 if (mWriteMoovBoxToMemory) {
1262 int32_t x = htonl(mMoovBoxBufferOffset - offset);
1263 memcpy(mMoovBoxBuffer + offset, &x, 4);
1264 } else {
1265 lseek64(mFd, offset, SEEK_SET);
1266 writeInt32(mOffset - offset);
1267 mOffset -= 4;
1268 lseek64(mFd, mOffset, SEEK_SET);
1269 }
1270 }
1271
writeInt8(int8_t x)1272 void MPEG4Writer::writeInt8(int8_t x) {
1273 write(&x, 1, 1);
1274 }
1275
writeInt16(int16_t x)1276 void MPEG4Writer::writeInt16(int16_t x) {
1277 x = htons(x);
1278 write(&x, 1, 2);
1279 }
1280
writeInt32(int32_t x)1281 void MPEG4Writer::writeInt32(int32_t x) {
1282 x = htonl(x);
1283 write(&x, 1, 4);
1284 }
1285
writeInt64(int64_t x)1286 void MPEG4Writer::writeInt64(int64_t x) {
1287 x = hton64(x);
1288 write(&x, 1, 8);
1289 }
1290
writeCString(const char * s)1291 void MPEG4Writer::writeCString(const char *s) {
1292 size_t n = strlen(s);
1293 write(s, 1, n + 1);
1294 }
1295
writeFourcc(const char * s)1296 void MPEG4Writer::writeFourcc(const char *s) {
1297 CHECK_EQ(strlen(s), 4);
1298 write(s, 1, 4);
1299 }
1300
1301
1302 // Written in +/-DD.DDDD format
writeLatitude(int degreex10000)1303 void MPEG4Writer::writeLatitude(int degreex10000) {
1304 bool isNegative = (degreex10000 < 0);
1305 char sign = isNegative? '-': '+';
1306
1307 // Handle the whole part
1308 char str[9];
1309 int wholePart = degreex10000 / 10000;
1310 if (wholePart == 0) {
1311 snprintf(str, 5, "%c%.2d.", sign, wholePart);
1312 } else {
1313 snprintf(str, 5, "%+.2d.", wholePart);
1314 }
1315
1316 // Handle the fractional part
1317 int fractionalPart = degreex10000 - (wholePart * 10000);
1318 if (fractionalPart < 0) {
1319 fractionalPart = -fractionalPart;
1320 }
1321 snprintf(&str[4], 5, "%.4d", fractionalPart);
1322
1323 // Do not write the null terminator
1324 write(str, 1, 8);
1325 }
1326
1327 // Written in +/- DDD.DDDD format
writeLongitude(int degreex10000)1328 void MPEG4Writer::writeLongitude(int degreex10000) {
1329 bool isNegative = (degreex10000 < 0);
1330 char sign = isNegative? '-': '+';
1331
1332 // Handle the whole part
1333 char str[10];
1334 int wholePart = degreex10000 / 10000;
1335 if (wholePart == 0) {
1336 snprintf(str, 6, "%c%.3d.", sign, wholePart);
1337 } else {
1338 snprintf(str, 6, "%+.3d.", wholePart);
1339 }
1340
1341 // Handle the fractional part
1342 int fractionalPart = degreex10000 - (wholePart * 10000);
1343 if (fractionalPart < 0) {
1344 fractionalPart = -fractionalPart;
1345 }
1346 snprintf(&str[5], 5, "%.4d", fractionalPart);
1347
1348 // Do not write the null terminator
1349 write(str, 1, 9);
1350 }
1351
1352 /*
1353 * Geodata is stored according to ISO-6709 standard.
1354 * latitudex10000 is latitude in degrees times 10000, and
1355 * longitudex10000 is longitude in degrees times 10000.
1356 * The range for the latitude is in [-90, +90], and
1357 * The range for the longitude is in [-180, +180]
1358 */
setGeoData(int latitudex10000,int longitudex10000)1359 status_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) {
1360 // Is latitude or longitude out of range?
1361 if (latitudex10000 < -900000 || latitudex10000 > 900000 ||
1362 longitudex10000 < -1800000 || longitudex10000 > 1800000) {
1363 return BAD_VALUE;
1364 }
1365
1366 mLatitudex10000 = latitudex10000;
1367 mLongitudex10000 = longitudex10000;
1368 mAreGeoTagsAvailable = true;
1369 mMoovExtraSize += 30;
1370 return OK;
1371 }
1372
setCaptureRate(float captureFps)1373 status_t MPEG4Writer::setCaptureRate(float captureFps) {
1374 if (captureFps <= 0.0f) {
1375 return BAD_VALUE;
1376 }
1377
1378 mMetaKeys->setFloat(kMetaKey_CaptureFps, captureFps);
1379 mMoovExtraSize += sizeof(kMetaKey_CaptureFps) + 4 + 32;
1380
1381 return OK;
1382 }
1383
write(const void * data,size_t size)1384 void MPEG4Writer::write(const void *data, size_t size) {
1385 write(data, 1, size);
1386 }
1387
isFileStreamable() const1388 bool MPEG4Writer::isFileStreamable() const {
1389 return mStreamableFile;
1390 }
1391
exceedsFileSizeLimit()1392 bool MPEG4Writer::exceedsFileSizeLimit() {
1393 // No limit
1394 if (mMaxFileSizeLimitBytes == 0) {
1395 return false;
1396 }
1397
1398 int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
1399 for (List<Track *>::iterator it = mTracks.begin();
1400 it != mTracks.end(); ++it) {
1401 nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
1402 }
1403
1404 if (!mStreamableFile) {
1405 // Add 1024 bytes as error tolerance
1406 return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes;
1407 }
1408 // Be conservative in the estimate: do not exceed 95% of
1409 // the target file limit. For small target file size limit, though,
1410 // this will not help.
1411 return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100);
1412 }
1413
exceedsFileDurationLimit()1414 bool MPEG4Writer::exceedsFileDurationLimit() {
1415 // No limit
1416 if (mMaxFileDurationLimitUs == 0) {
1417 return false;
1418 }
1419
1420 for (List<Track *>::iterator it = mTracks.begin();
1421 it != mTracks.end(); ++it) {
1422 if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
1423 return true;
1424 }
1425 }
1426 return false;
1427 }
1428
reachedEOS()1429 bool MPEG4Writer::reachedEOS() {
1430 bool allDone = true;
1431 for (List<Track *>::iterator it = mTracks.begin();
1432 it != mTracks.end(); ++it) {
1433 if (!(*it)->reachedEOS()) {
1434 allDone = false;
1435 break;
1436 }
1437 }
1438
1439 return allDone;
1440 }
1441
setStartTimestampUs(int64_t timeUs)1442 void MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
1443 ALOGI("setStartTimestampUs: %" PRId64, timeUs);
1444 CHECK_GE(timeUs, 0ll);
1445 Mutex::Autolock autoLock(mLock);
1446 if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
1447 mStartTimestampUs = timeUs;
1448 ALOGI("Earliest track starting time: %" PRId64, mStartTimestampUs);
1449 }
1450 }
1451
getStartTimestampUs()1452 int64_t MPEG4Writer::getStartTimestampUs() {
1453 Mutex::Autolock autoLock(mLock);
1454 return mStartTimestampUs;
1455 }
1456
numTracks()1457 size_t MPEG4Writer::numTracks() {
1458 Mutex::Autolock autolock(mLock);
1459 return mTracks.size();
1460 }
1461
1462 ////////////////////////////////////////////////////////////////////////////////
1463
Track(MPEG4Writer * owner,const sp<IMediaSource> & source,size_t trackId)1464 MPEG4Writer::Track::Track(
1465 MPEG4Writer *owner, const sp<IMediaSource> &source, size_t trackId)
1466 : mOwner(owner),
1467 mMeta(source->getFormat()),
1468 mSource(source),
1469 mDone(false),
1470 mPaused(false),
1471 mResumed(false),
1472 mStarted(false),
1473 mTrackId(trackId),
1474 mTrackDurationUs(0),
1475 mEstimatedTrackSizeBytes(0),
1476 mSamplesHaveSameSize(true),
1477 mStszTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1478 mStcoTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1479 mCo64TableEntries(new ListTableEntries<off64_t>(1000, 1)),
1480 mStscTableEntries(new ListTableEntries<uint32_t>(1000, 3)),
1481 mStssTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1482 mSttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)),
1483 mCttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)),
1484 mCodecSpecificData(NULL),
1485 mCodecSpecificDataSize(0),
1486 mGotAllCodecSpecificData(false),
1487 mReachedEOS(false),
1488 mRotation(0) {
1489 getCodecSpecificDataFromInputFormatIfPossible();
1490
1491 const char *mime;
1492 mMeta->findCString(kKeyMIMEType, &mime);
1493 mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
1494 mIsHevc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC);
1495 mIsAudio = !strncasecmp(mime, "audio/", 6);
1496 mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
1497 !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
1498
1499 setTimeScale();
1500 }
1501
updateTrackSizeEstimate()1502 void MPEG4Writer::Track::updateTrackSizeEstimate() {
1503
1504 uint32_t stcoBoxCount = (mOwner->use32BitFileOffset()
1505 ? mStcoTableEntries->count()
1506 : mCo64TableEntries->count());
1507 int64_t stcoBoxSizeBytes = stcoBoxCount * 4;
1508 int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4);
1509
1510 mEstimatedTrackSizeBytes = mMdatSizeBytes; // media data size
1511 if (!mOwner->isFileStreamable()) {
1512 // Reserved free space is not large enough to hold
1513 // all meta data and thus wasted.
1514 mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 + // stsc box size
1515 mStssTableEntries->count() * 4 + // stss box size
1516 mSttsTableEntries->count() * 8 + // stts box size
1517 mCttsTableEntries->count() * 8 + // ctts box size
1518 stcoBoxSizeBytes + // stco box size
1519 stszBoxSizeBytes; // stsz box size
1520 }
1521 }
1522
addOneStscTableEntry(size_t chunkId,size_t sampleId)1523 void MPEG4Writer::Track::addOneStscTableEntry(
1524 size_t chunkId, size_t sampleId) {
1525
1526 mStscTableEntries->add(htonl(chunkId));
1527 mStscTableEntries->add(htonl(sampleId));
1528 mStscTableEntries->add(htonl(1));
1529 }
1530
addOneStssTableEntry(size_t sampleId)1531 void MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) {
1532 mStssTableEntries->add(htonl(sampleId));
1533 }
1534
addOneSttsTableEntry(size_t sampleCount,int32_t duration)1535 void MPEG4Writer::Track::addOneSttsTableEntry(
1536 size_t sampleCount, int32_t duration) {
1537
1538 if (duration == 0) {
1539 ALOGW("0-duration samples found: %zu", sampleCount);
1540 }
1541 mSttsTableEntries->add(htonl(sampleCount));
1542 mSttsTableEntries->add(htonl(duration));
1543 }
1544
addOneCttsTableEntry(size_t sampleCount,int32_t duration)1545 void MPEG4Writer::Track::addOneCttsTableEntry(
1546 size_t sampleCount, int32_t duration) {
1547
1548 if (mIsAudio) {
1549 return;
1550 }
1551 mCttsTableEntries->add(htonl(sampleCount));
1552 mCttsTableEntries->add(htonl(duration));
1553 }
1554
addChunkOffset(off64_t offset)1555 void MPEG4Writer::Track::addChunkOffset(off64_t offset) {
1556 if (mOwner->use32BitFileOffset()) {
1557 uint32_t value = offset;
1558 mStcoTableEntries->add(htonl(value));
1559 } else {
1560 mCo64TableEntries->add(hton64(offset));
1561 }
1562 }
1563
setTimeScale()1564 void MPEG4Writer::Track::setTimeScale() {
1565 ALOGV("setTimeScale");
1566 // Default time scale
1567 mTimeScale = 90000;
1568
1569 if (mIsAudio) {
1570 // Use the sampling rate as the default time scale for audio track.
1571 int32_t sampleRate;
1572 bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
1573 CHECK(success);
1574 mTimeScale = sampleRate;
1575 }
1576
1577 // If someone would like to overwrite the timescale, use user-supplied value.
1578 int32_t timeScale;
1579 if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
1580 mTimeScale = timeScale;
1581 }
1582
1583 CHECK_GT(mTimeScale, 0);
1584 }
1585
getCodecSpecificDataFromInputFormatIfPossible()1586 void MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
1587 const char *mime;
1588 CHECK(mMeta->findCString(kKeyMIMEType, &mime));
1589
1590 uint32_t type;
1591 const void *data = NULL;
1592 size_t size = 0;
1593 if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
1594 mMeta->findData(kKeyAVCC, &type, &data, &size);
1595 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
1596 mMeta->findData(kKeyHVCC, &type, &data, &size);
1597 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
1598 || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
1599 if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
1600 ESDS esds(data, size);
1601 if (esds.getCodecSpecificInfo(&data, &size) != OK) {
1602 data = NULL;
1603 size = 0;
1604 }
1605 }
1606 }
1607 if (data != NULL && copyCodecSpecificData((uint8_t *)data, size) == OK) {
1608 mGotAllCodecSpecificData = true;
1609 }
1610 }
1611
~Track()1612 MPEG4Writer::Track::~Track() {
1613 stop();
1614
1615 delete mStszTableEntries;
1616 delete mStcoTableEntries;
1617 delete mCo64TableEntries;
1618 delete mStscTableEntries;
1619 delete mSttsTableEntries;
1620 delete mStssTableEntries;
1621 delete mCttsTableEntries;
1622
1623 mStszTableEntries = NULL;
1624 mStcoTableEntries = NULL;
1625 mCo64TableEntries = NULL;
1626 mStscTableEntries = NULL;
1627 mSttsTableEntries = NULL;
1628 mStssTableEntries = NULL;
1629 mCttsTableEntries = NULL;
1630
1631 if (mCodecSpecificData != NULL) {
1632 free(mCodecSpecificData);
1633 mCodecSpecificData = NULL;
1634 }
1635 }
1636
initTrackingProgressStatus(MetaData * params)1637 void MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
1638 ALOGV("initTrackingProgressStatus");
1639 mPreviousTrackTimeUs = -1;
1640 mTrackingProgressStatus = false;
1641 mTrackEveryTimeDurationUs = 0;
1642 {
1643 int64_t timeUs;
1644 if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
1645 ALOGV("Receive request to track progress status for every %" PRId64 " us", timeUs);
1646 mTrackEveryTimeDurationUs = timeUs;
1647 mTrackingProgressStatus = true;
1648 }
1649 }
1650 }
1651
1652 // static
ThreadWrapper(void * me)1653 void *MPEG4Writer::ThreadWrapper(void *me) {
1654 ALOGV("ThreadWrapper: %p", me);
1655 MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
1656 writer->threadFunc();
1657 return NULL;
1658 }
1659
bufferChunk(const Chunk & chunk)1660 void MPEG4Writer::bufferChunk(const Chunk& chunk) {
1661 ALOGV("bufferChunk: %p", chunk.mTrack);
1662 Mutex::Autolock autolock(mLock);
1663 CHECK_EQ(mDone, false);
1664
1665 for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
1666 it != mChunkInfos.end(); ++it) {
1667
1668 if (chunk.mTrack == it->mTrack) { // Found owner
1669 it->mChunks.push_back(chunk);
1670 mChunkReadyCondition.signal();
1671 return;
1672 }
1673 }
1674
1675 CHECK(!"Received a chunk for a unknown track");
1676 }
1677
writeChunkToFile(Chunk * chunk)1678 void MPEG4Writer::writeChunkToFile(Chunk* chunk) {
1679 ALOGV("writeChunkToFile: %" PRId64 " from %s track",
1680 chunk->mTimeStampUs, chunk->mTrack->isAudio()? "audio": "video");
1681
1682 int32_t isFirstSample = true;
1683 while (!chunk->mSamples.empty()) {
1684 List<MediaBuffer *>::iterator it = chunk->mSamples.begin();
1685
1686 off64_t offset = (chunk->mTrack->isAvc() || chunk->mTrack->isHevc())
1687 ? addLengthPrefixedSample_l(*it)
1688 : addSample_l(*it);
1689
1690 if (isFirstSample) {
1691 chunk->mTrack->addChunkOffset(offset);
1692 isFirstSample = false;
1693 }
1694
1695 (*it)->release();
1696 (*it) = NULL;
1697 chunk->mSamples.erase(it);
1698 }
1699 chunk->mSamples.clear();
1700 }
1701
writeAllChunks()1702 void MPEG4Writer::writeAllChunks() {
1703 ALOGV("writeAllChunks");
1704 size_t outstandingChunks = 0;
1705 Chunk chunk;
1706 while (findChunkToWrite(&chunk)) {
1707 writeChunkToFile(&chunk);
1708 ++outstandingChunks;
1709 }
1710
1711 sendSessionSummary();
1712
1713 mChunkInfos.clear();
1714 ALOGD("%zu chunks are written in the last batch", outstandingChunks);
1715 }
1716
findChunkToWrite(Chunk * chunk)1717 bool MPEG4Writer::findChunkToWrite(Chunk *chunk) {
1718 ALOGV("findChunkToWrite");
1719
1720 int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
1721 Track *track = NULL;
1722 for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
1723 it != mChunkInfos.end(); ++it) {
1724 if (!it->mChunks.empty()) {
1725 List<Chunk>::iterator chunkIt = it->mChunks.begin();
1726 if (chunkIt->mTimeStampUs < minTimestampUs) {
1727 minTimestampUs = chunkIt->mTimeStampUs;
1728 track = it->mTrack;
1729 }
1730 }
1731 }
1732
1733 if (track == NULL) {
1734 ALOGV("Nothing to be written after all");
1735 return false;
1736 }
1737
1738 if (mIsFirstChunk) {
1739 mIsFirstChunk = false;
1740 }
1741
1742 for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
1743 it != mChunkInfos.end(); ++it) {
1744 if (it->mTrack == track) {
1745 *chunk = *(it->mChunks.begin());
1746 it->mChunks.erase(it->mChunks.begin());
1747 CHECK_EQ(chunk->mTrack, track);
1748
1749 int64_t interChunkTimeUs =
1750 chunk->mTimeStampUs - it->mPrevChunkTimestampUs;
1751 if (interChunkTimeUs > it->mPrevChunkTimestampUs) {
1752 it->mMaxInterChunkDurUs = interChunkTimeUs;
1753 }
1754
1755 return true;
1756 }
1757 }
1758
1759 return false;
1760 }
1761
threadFunc()1762 void MPEG4Writer::threadFunc() {
1763 ALOGV("threadFunc");
1764
1765 prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0);
1766
1767 Mutex::Autolock autoLock(mLock);
1768 while (!mDone) {
1769 Chunk chunk;
1770 bool chunkFound = false;
1771
1772 while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) {
1773 mChunkReadyCondition.wait(mLock);
1774 }
1775
1776 // In real time recording mode, write without holding the lock in order
1777 // to reduce the blocking time for media track threads.
1778 // Otherwise, hold the lock until the existing chunks get written to the
1779 // file.
1780 if (chunkFound) {
1781 if (mIsRealTimeRecording) {
1782 mLock.unlock();
1783 }
1784 writeChunkToFile(&chunk);
1785 if (mIsRealTimeRecording) {
1786 mLock.lock();
1787 }
1788 }
1789 }
1790
1791 writeAllChunks();
1792 }
1793
startWriterThread()1794 status_t MPEG4Writer::startWriterThread() {
1795 ALOGV("startWriterThread");
1796
1797 mDone = false;
1798 mIsFirstChunk = true;
1799 mDriftTimeUs = 0;
1800 for (List<Track *>::iterator it = mTracks.begin();
1801 it != mTracks.end(); ++it) {
1802 ChunkInfo info;
1803 info.mTrack = *it;
1804 info.mPrevChunkTimestampUs = 0;
1805 info.mMaxInterChunkDurUs = 0;
1806 mChunkInfos.push_back(info);
1807 }
1808
1809 pthread_attr_t attr;
1810 pthread_attr_init(&attr);
1811 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
1812 pthread_create(&mThread, &attr, ThreadWrapper, this);
1813 pthread_attr_destroy(&attr);
1814 mWriterThreadStarted = true;
1815 return OK;
1816 }
1817
1818
start(MetaData * params)1819 status_t MPEG4Writer::Track::start(MetaData *params) {
1820 if (!mDone && mPaused) {
1821 mPaused = false;
1822 mResumed = true;
1823 return OK;
1824 }
1825
1826 int64_t startTimeUs;
1827 if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
1828 startTimeUs = 0;
1829 }
1830 mStartTimeRealUs = startTimeUs;
1831
1832 int32_t rotationDegrees;
1833 if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) {
1834 mRotation = rotationDegrees;
1835 }
1836
1837 initTrackingProgressStatus(params);
1838
1839 sp<MetaData> meta = new MetaData;
1840 if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) {
1841 /*
1842 * This extra delay of accepting incoming audio/video signals
1843 * helps to align a/v start time at the beginning of a recording
1844 * session, and it also helps eliminate the "recording" sound for
1845 * camcorder applications.
1846 *
1847 * If client does not set the start time offset, we fall back to
1848 * use the default initial delay value.
1849 */
1850 int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
1851 if (startTimeOffsetUs < 0) { // Start time offset was not set
1852 startTimeOffsetUs = kInitialDelayTimeUs;
1853 }
1854 startTimeUs += startTimeOffsetUs;
1855 ALOGI("Start time offset: %" PRId64 " us", startTimeOffsetUs);
1856 }
1857
1858 meta->setInt64(kKeyTime, startTimeUs);
1859
1860 status_t err = mSource->start(meta.get());
1861 if (err != OK) {
1862 mDone = mReachedEOS = true;
1863 return err;
1864 }
1865
1866 pthread_attr_t attr;
1867 pthread_attr_init(&attr);
1868 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
1869
1870 mDone = false;
1871 mStarted = true;
1872 mTrackDurationUs = 0;
1873 mReachedEOS = false;
1874 mEstimatedTrackSizeBytes = 0;
1875 mMdatSizeBytes = 0;
1876 mMaxChunkDurationUs = 0;
1877
1878 pthread_create(&mThread, &attr, ThreadWrapper, this);
1879 pthread_attr_destroy(&attr);
1880
1881 return OK;
1882 }
1883
pause()1884 status_t MPEG4Writer::Track::pause() {
1885 mPaused = true;
1886 return OK;
1887 }
1888
stop()1889 status_t MPEG4Writer::Track::stop() {
1890 ALOGD("%s track stopping", mIsAudio? "Audio": "Video");
1891 if (!mStarted) {
1892 ALOGE("Stop() called but track is not started");
1893 return ERROR_END_OF_STREAM;
1894 }
1895
1896 if (mDone) {
1897 return OK;
1898 }
1899 mDone = true;
1900
1901 ALOGD("%s track source stopping", mIsAudio? "Audio": "Video");
1902 mSource->stop();
1903 ALOGD("%s track source stopped", mIsAudio? "Audio": "Video");
1904
1905 void *dummy;
1906 pthread_join(mThread, &dummy);
1907 status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy));
1908
1909 ALOGD("%s track stopped", mIsAudio? "Audio": "Video");
1910 return err;
1911 }
1912
reachedEOS()1913 bool MPEG4Writer::Track::reachedEOS() {
1914 return mReachedEOS;
1915 }
1916
1917 // static
ThreadWrapper(void * me)1918 void *MPEG4Writer::Track::ThreadWrapper(void *me) {
1919 Track *track = static_cast<Track *>(me);
1920
1921 status_t err = track->threadEntry();
1922 return (void *)(uintptr_t)err;
1923 }
1924
getNalUnitType(uint8_t byte,uint8_t * type)1925 static void getNalUnitType(uint8_t byte, uint8_t* type) {
1926 ALOGV("getNalUnitType: %d", byte);
1927
1928 // nal_unit_type: 5-bit unsigned integer
1929 *type = (byte & 0x1F);
1930 }
1931
parseParamSet(const uint8_t * data,size_t length,int type,size_t * paramSetLen)1932 const uint8_t *MPEG4Writer::Track::parseParamSet(
1933 const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
1934
1935 ALOGV("parseParamSet");
1936 CHECK(type == kNalUnitTypeSeqParamSet ||
1937 type == kNalUnitTypePicParamSet);
1938
1939 const uint8_t *nextStartCode = findNextNalStartCode(data, length);
1940 *paramSetLen = nextStartCode - data;
1941 if (*paramSetLen == 0) {
1942 ALOGE("Param set is malformed, since its length is 0");
1943 return NULL;
1944 }
1945
1946 AVCParamSet paramSet(*paramSetLen, data);
1947 if (type == kNalUnitTypeSeqParamSet) {
1948 if (*paramSetLen < 4) {
1949 ALOGE("Seq parameter set malformed");
1950 return NULL;
1951 }
1952 if (mSeqParamSets.empty()) {
1953 mProfileIdc = data[1];
1954 mProfileCompatible = data[2];
1955 mLevelIdc = data[3];
1956 } else {
1957 if (mProfileIdc != data[1] ||
1958 mProfileCompatible != data[2] ||
1959 mLevelIdc != data[3]) {
1960 // COULD DO: set profile/level to the lowest required to support all SPSs
1961 ALOGE("Inconsistent profile/level found in seq parameter sets");
1962 return NULL;
1963 }
1964 }
1965 mSeqParamSets.push_back(paramSet);
1966 } else {
1967 mPicParamSets.push_back(paramSet);
1968 }
1969 return nextStartCode;
1970 }
1971
copyAVCCodecSpecificData(const uint8_t * data,size_t size)1972 status_t MPEG4Writer::Track::copyAVCCodecSpecificData(
1973 const uint8_t *data, size_t size) {
1974 ALOGV("copyAVCCodecSpecificData");
1975
1976 // 2 bytes for each of the parameter set length field
1977 // plus the 7 bytes for the header
1978 return copyCodecSpecificData(data, size, 4 + 7);
1979 }
1980
copyHEVCCodecSpecificData(const uint8_t * data,size_t size)1981 status_t MPEG4Writer::Track::copyHEVCCodecSpecificData(
1982 const uint8_t *data, size_t size) {
1983 ALOGV("copyHEVCCodecSpecificData");
1984
1985 // Min length of HEVC CSD is 23. (ISO/IEC 14496-15:2014 Chapter 8.3.3.1.2)
1986 return copyCodecSpecificData(data, size, 23);
1987 }
1988
copyCodecSpecificData(const uint8_t * data,size_t size,size_t minLength)1989 status_t MPEG4Writer::Track::copyCodecSpecificData(
1990 const uint8_t *data, size_t size, size_t minLength) {
1991 if (size < minLength) {
1992 ALOGE("Codec specific data length too short: %zu", size);
1993 return ERROR_MALFORMED;
1994 }
1995
1996 mCodecSpecificData = malloc(size);
1997 if (mCodecSpecificData == NULL) {
1998 ALOGE("Failed allocating codec specific data");
1999 return NO_MEMORY;
2000 }
2001 mCodecSpecificDataSize = size;
2002 memcpy(mCodecSpecificData, data, size);
2003 return OK;
2004 }
2005
parseAVCCodecSpecificData(const uint8_t * data,size_t size)2006 status_t MPEG4Writer::Track::parseAVCCodecSpecificData(
2007 const uint8_t *data, size_t size) {
2008
2009 ALOGV("parseAVCCodecSpecificData");
2010 // Data starts with a start code.
2011 // SPS and PPS are separated with start codes.
2012 // Also, SPS must come before PPS
2013 uint8_t type = kNalUnitTypeSeqParamSet;
2014 bool gotSps = false;
2015 bool gotPps = false;
2016 const uint8_t *tmp = data;
2017 const uint8_t *nextStartCode = data;
2018 size_t bytesLeft = size;
2019 size_t paramSetLen = 0;
2020 mCodecSpecificDataSize = 0;
2021 while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
2022 getNalUnitType(*(tmp + 4), &type);
2023 if (type == kNalUnitTypeSeqParamSet) {
2024 if (gotPps) {
2025 ALOGE("SPS must come before PPS");
2026 return ERROR_MALFORMED;
2027 }
2028 if (!gotSps) {
2029 gotSps = true;
2030 }
2031 nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen);
2032 } else if (type == kNalUnitTypePicParamSet) {
2033 if (!gotSps) {
2034 ALOGE("SPS must come before PPS");
2035 return ERROR_MALFORMED;
2036 }
2037 if (!gotPps) {
2038 gotPps = true;
2039 }
2040 nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen);
2041 } else {
2042 ALOGE("Only SPS and PPS Nal units are expected");
2043 return ERROR_MALFORMED;
2044 }
2045
2046 if (nextStartCode == NULL) {
2047 return ERROR_MALFORMED;
2048 }
2049
2050 // Move on to find the next parameter set
2051 bytesLeft -= nextStartCode - tmp;
2052 tmp = nextStartCode;
2053 mCodecSpecificDataSize += (2 + paramSetLen);
2054 }
2055
2056 {
2057 // Check on the number of seq parameter sets
2058 size_t nSeqParamSets = mSeqParamSets.size();
2059 if (nSeqParamSets == 0) {
2060 ALOGE("Cound not find sequence parameter set");
2061 return ERROR_MALFORMED;
2062 }
2063
2064 if (nSeqParamSets > 0x1F) {
2065 ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets);
2066 return ERROR_MALFORMED;
2067 }
2068 }
2069
2070 {
2071 // Check on the number of pic parameter sets
2072 size_t nPicParamSets = mPicParamSets.size();
2073 if (nPicParamSets == 0) {
2074 ALOGE("Cound not find picture parameter set");
2075 return ERROR_MALFORMED;
2076 }
2077 if (nPicParamSets > 0xFF) {
2078 ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets);
2079 return ERROR_MALFORMED;
2080 }
2081 }
2082 // FIXME:
2083 // Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above
2084 // and remove #if 0
2085 #if 0
2086 {
2087 // Check on the profiles
2088 // These profiles requires additional parameter set extensions
2089 if (mProfileIdc == 100 || mProfileIdc == 110 ||
2090 mProfileIdc == 122 || mProfileIdc == 144) {
2091 ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
2092 return BAD_VALUE;
2093 }
2094 }
2095 #endif
2096 return OK;
2097 }
2098
makeAVCCodecSpecificData(const uint8_t * data,size_t size)2099 status_t MPEG4Writer::Track::makeAVCCodecSpecificData(
2100 const uint8_t *data, size_t size) {
2101
2102 if (mCodecSpecificData != NULL) {
2103 ALOGE("Already have codec specific data");
2104 return ERROR_MALFORMED;
2105 }
2106
2107 if (size < 4) {
2108 ALOGE("Codec specific data length too short: %zu", size);
2109 return ERROR_MALFORMED;
2110 }
2111
2112 // Data is in the form of AVCCodecSpecificData
2113 if (memcmp("\x00\x00\x00\x01", data, 4)) {
2114 return copyAVCCodecSpecificData(data, size);
2115 }
2116
2117 if (parseAVCCodecSpecificData(data, size) != OK) {
2118 return ERROR_MALFORMED;
2119 }
2120
2121 // ISO 14496-15: AVC file format
2122 mCodecSpecificDataSize += 7; // 7 more bytes in the header
2123 mCodecSpecificData = malloc(mCodecSpecificDataSize);
2124 if (mCodecSpecificData == NULL) {
2125 mCodecSpecificDataSize = 0;
2126 ALOGE("Failed allocating codec specific data");
2127 return NO_MEMORY;
2128 }
2129 uint8_t *header = (uint8_t *)mCodecSpecificData;
2130 header[0] = 1; // version
2131 header[1] = mProfileIdc; // profile indication
2132 header[2] = mProfileCompatible; // profile compatibility
2133 header[3] = mLevelIdc;
2134
2135 // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
2136 if (mOwner->useNalLengthFour()) {
2137 header[4] = 0xfc | 3; // length size == 4 bytes
2138 } else {
2139 header[4] = 0xfc | 1; // length size == 2 bytes
2140 }
2141
2142 // 3-bit '111' followed by 5-bit numSequenceParameterSets
2143 int nSequenceParamSets = mSeqParamSets.size();
2144 header[5] = 0xe0 | nSequenceParamSets;
2145 header += 6;
2146 for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
2147 it != mSeqParamSets.end(); ++it) {
2148 // 16-bit sequence parameter set length
2149 uint16_t seqParamSetLength = it->mLength;
2150 header[0] = seqParamSetLength >> 8;
2151 header[1] = seqParamSetLength & 0xff;
2152
2153 // SPS NAL unit (sequence parameter length bytes)
2154 memcpy(&header[2], it->mData, seqParamSetLength);
2155 header += (2 + seqParamSetLength);
2156 }
2157
2158 // 8-bit nPictureParameterSets
2159 int nPictureParamSets = mPicParamSets.size();
2160 header[0] = nPictureParamSets;
2161 header += 1;
2162 for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
2163 it != mPicParamSets.end(); ++it) {
2164 // 16-bit picture parameter set length
2165 uint16_t picParamSetLength = it->mLength;
2166 header[0] = picParamSetLength >> 8;
2167 header[1] = picParamSetLength & 0xff;
2168
2169 // PPS Nal unit (picture parameter set length bytes)
2170 memcpy(&header[2], it->mData, picParamSetLength);
2171 header += (2 + picParamSetLength);
2172 }
2173
2174 return OK;
2175 }
2176
2177
parseHEVCCodecSpecificData(const uint8_t * data,size_t size,HevcParameterSets & paramSets)2178 status_t MPEG4Writer::Track::parseHEVCCodecSpecificData(
2179 const uint8_t *data, size_t size, HevcParameterSets ¶mSets) {
2180
2181 ALOGV("parseHEVCCodecSpecificData");
2182 const uint8_t *tmp = data;
2183 const uint8_t *nextStartCode = data;
2184 size_t bytesLeft = size;
2185 while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
2186 nextStartCode = findNextNalStartCode(tmp + 4, bytesLeft - 4);
2187 status_t err = paramSets.addNalUnit(tmp + 4, (nextStartCode - tmp) - 4);
2188 if (err != OK) {
2189 return ERROR_MALFORMED;
2190 }
2191
2192 // Move on to find the next parameter set
2193 bytesLeft -= nextStartCode - tmp;
2194 tmp = nextStartCode;
2195 }
2196
2197 size_t csdSize = 23;
2198 const size_t numNalUnits = paramSets.getNumNalUnits();
2199 for (size_t i = 0; i < ARRAY_SIZE(kMandatoryHevcNalUnitTypes); ++i) {
2200 int type = kMandatoryHevcNalUnitTypes[i];
2201 size_t numParamSets = paramSets.getNumNalUnitsOfType(type);
2202 if (numParamSets == 0) {
2203 ALOGE("Cound not find NAL unit of type %d", type);
2204 return ERROR_MALFORMED;
2205 }
2206 }
2207 for (size_t i = 0; i < ARRAY_SIZE(kHevcNalUnitTypes); ++i) {
2208 int type = kHevcNalUnitTypes[i];
2209 size_t numParamSets = paramSets.getNumNalUnitsOfType(type);
2210 if (numParamSets > 0xffff) {
2211 ALOGE("Too many seq parameter sets (%zu) found", numParamSets);
2212 return ERROR_MALFORMED;
2213 }
2214 csdSize += 3;
2215 for (size_t j = 0; j < numNalUnits; ++j) {
2216 if (paramSets.getType(j) != type) {
2217 continue;
2218 }
2219 csdSize += 2 + paramSets.getSize(j);
2220 }
2221 }
2222 mCodecSpecificDataSize = csdSize;
2223 return OK;
2224 }
2225
makeHEVCCodecSpecificData(const uint8_t * data,size_t size)2226 status_t MPEG4Writer::Track::makeHEVCCodecSpecificData(
2227 const uint8_t *data, size_t size) {
2228
2229 if (mCodecSpecificData != NULL) {
2230 ALOGE("Already have codec specific data");
2231 return ERROR_MALFORMED;
2232 }
2233
2234 if (size < 4) {
2235 ALOGE("Codec specific data length too short: %zu", size);
2236 return ERROR_MALFORMED;
2237 }
2238
2239 // Data is in the form of HEVCCodecSpecificData
2240 if (memcmp("\x00\x00\x00\x01", data, 4)) {
2241 return copyHEVCCodecSpecificData(data, size);
2242 }
2243
2244 HevcParameterSets paramSets;
2245 if (parseHEVCCodecSpecificData(data, size, paramSets) != OK) {
2246 ALOGE("failed parsing codec specific data");
2247 return ERROR_MALFORMED;
2248 }
2249
2250 mCodecSpecificData = malloc(mCodecSpecificDataSize);
2251 if (mCodecSpecificData == NULL) {
2252 mCodecSpecificDataSize = 0;
2253 ALOGE("Failed allocating codec specific data");
2254 return NO_MEMORY;
2255 }
2256 status_t err = paramSets.makeHvcc((uint8_t *)mCodecSpecificData,
2257 &mCodecSpecificDataSize, mOwner->useNalLengthFour() ? 4 : 2);
2258 if (err != OK) {
2259 ALOGE("failed constructing HVCC atom");
2260 return err;
2261 }
2262
2263 return OK;
2264 }
2265
2266 /*
2267 * Updates the drift time from the audio track so that
2268 * the video track can get the updated drift time information
2269 * from the file writer. The fluctuation of the drift time of the audio
2270 * encoding path is smoothed out with a simple filter by giving a larger
2271 * weight to more recently drift time. The filter coefficients, 0.5 and 0.5,
2272 * are heuristically determined.
2273 */
updateDriftTime(const sp<MetaData> & meta)2274 void MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) {
2275 int64_t driftTimeUs = 0;
2276 if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) {
2277 int64_t prevDriftTimeUs = mOwner->getDriftTimeUs();
2278 int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1;
2279 mOwner->setDriftTimeUs(timeUs);
2280 }
2281 }
2282
threadEntry()2283 status_t MPEG4Writer::Track::threadEntry() {
2284 int32_t count = 0;
2285 const int64_t interleaveDurationUs = mOwner->interleaveDuration();
2286 const bool hasMultipleTracks = (mOwner->numTracks() > 1);
2287 int64_t chunkTimestampUs = 0;
2288 int32_t nChunks = 0;
2289 int32_t nActualFrames = 0; // frames containing non-CSD data (non-0 length)
2290 int32_t nZeroLengthFrames = 0;
2291 int64_t lastTimestampUs = 0; // Previous sample time stamp
2292 int64_t lastDurationUs = 0; // Between the previous two samples
2293 int64_t currDurationTicks = 0; // Timescale based ticks
2294 int64_t lastDurationTicks = 0; // Timescale based ticks
2295 int32_t sampleCount = 1; // Sample count in the current stts table entry
2296 uint32_t previousSampleSize = 0; // Size of the previous sample
2297 int64_t previousPausedDurationUs = 0;
2298 int64_t timestampUs = 0;
2299 int64_t cttsOffsetTimeUs = 0;
2300 int64_t currCttsOffsetTimeTicks = 0; // Timescale based ticks
2301 int64_t lastCttsOffsetTimeTicks = -1; // Timescale based ticks
2302 int32_t cttsSampleCount = 0; // Sample count in the current ctts table entry
2303 uint32_t lastSamplesPerChunk = 0;
2304
2305 if (mIsAudio) {
2306 prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
2307 } else {
2308 prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
2309 }
2310
2311 if (mOwner->isRealTimeRecording()) {
2312 androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
2313 }
2314
2315 sp<MetaData> meta_data;
2316
2317 status_t err = OK;
2318 MediaBuffer *buffer;
2319 const char *trackName = mIsAudio ? "Audio" : "Video";
2320 while (!mDone && (err = mSource->read(&buffer)) == OK) {
2321 if (buffer->range_length() == 0) {
2322 buffer->release();
2323 buffer = NULL;
2324 ++nZeroLengthFrames;
2325 continue;
2326 }
2327
2328 // If the codec specific data has not been received yet, delay pause.
2329 // After the codec specific data is received, discard what we received
2330 // when the track is to be paused.
2331 if (mPaused && !mResumed) {
2332 buffer->release();
2333 buffer = NULL;
2334 continue;
2335 }
2336
2337 ++count;
2338
2339 int32_t isCodecConfig;
2340 if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
2341 && isCodecConfig) {
2342 // if config format (at track addition) already had CSD, keep that
2343 // UNLESS we have not received any frames yet.
2344 // TODO: for now the entire CSD has to come in one frame for encoders, even though
2345 // they need to be spread out for decoders.
2346 if (mGotAllCodecSpecificData && nActualFrames > 0) {
2347 ALOGI("ignoring additional CSD for video track after first frame");
2348 } else {
2349 mMeta = mSource->getFormat(); // get output format after format change
2350
2351 if (mIsAvc) {
2352 status_t err = makeAVCCodecSpecificData(
2353 (const uint8_t *)buffer->data()
2354 + buffer->range_offset(),
2355 buffer->range_length());
2356 CHECK_EQ((status_t)OK, err);
2357 } else if (mIsHevc) {
2358 status_t err = makeHEVCCodecSpecificData(
2359 (const uint8_t *)buffer->data()
2360 + buffer->range_offset(),
2361 buffer->range_length());
2362 CHECK_EQ((status_t)OK, err);
2363 } else if (mIsMPEG4) {
2364 copyCodecSpecificData((const uint8_t *)buffer->data() + buffer->range_offset(),
2365 buffer->range_length());
2366 }
2367 }
2368
2369 buffer->release();
2370 buffer = NULL;
2371
2372 mGotAllCodecSpecificData = true;
2373 continue;
2374 }
2375
2376 ++nActualFrames;
2377
2378 // Make a deep copy of the MediaBuffer and Metadata and release
2379 // the original as soon as we can
2380 MediaBuffer *copy = new MediaBuffer(buffer->range_length());
2381 memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
2382 buffer->range_length());
2383 copy->set_range(0, buffer->range_length());
2384 meta_data = new MetaData(*buffer->meta_data().get());
2385 buffer->release();
2386 buffer = NULL;
2387
2388 if (mIsAvc || mIsHevc) StripStartcode(copy);
2389
2390 size_t sampleSize = copy->range_length();
2391 if (mIsAvc || mIsHevc) {
2392 if (mOwner->useNalLengthFour()) {
2393 sampleSize += 4;
2394 } else {
2395 sampleSize += 2;
2396 }
2397 }
2398
2399 // Max file size or duration handling
2400 mMdatSizeBytes += sampleSize;
2401 updateTrackSizeEstimate();
2402
2403 if (mOwner->exceedsFileSizeLimit()) {
2404 ALOGW("Recorded file size exceeds limit %" PRId64 "bytes",
2405 mOwner->mMaxFileSizeLimitBytes);
2406 mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
2407 break;
2408 }
2409 if (mOwner->exceedsFileDurationLimit()) {
2410 ALOGW("Recorded file duration exceeds limit %" PRId64 "microseconds",
2411 mOwner->mMaxFileDurationLimitUs);
2412 mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
2413 break;
2414 }
2415
2416
2417 int32_t isSync = false;
2418 meta_data->findInt32(kKeyIsSyncFrame, &isSync);
2419 CHECK(meta_data->findInt64(kKeyTime, ×tampUs));
2420
2421 ////////////////////////////////////////////////////////////////////////////////
2422 if (mStszTableEntries->count() == 0) {
2423 mFirstSampleTimeRealUs = systemTime() / 1000;
2424 mStartTimestampUs = timestampUs;
2425 mOwner->setStartTimestampUs(mStartTimestampUs);
2426 previousPausedDurationUs = mStartTimestampUs;
2427 }
2428
2429 if (mResumed) {
2430 int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
2431 if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) {
2432 copy->release();
2433 return ERROR_MALFORMED;
2434 }
2435
2436 int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
2437 if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) {
2438 copy->release();
2439 return ERROR_MALFORMED;
2440 }
2441
2442 previousPausedDurationUs += pausedDurationUs - lastDurationUs;
2443 mResumed = false;
2444 }
2445
2446 timestampUs -= previousPausedDurationUs;
2447 if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
2448 copy->release();
2449 return ERROR_MALFORMED;
2450 }
2451
2452 if (!mIsAudio) {
2453 /*
2454 * Composition time: timestampUs
2455 * Decoding time: decodingTimeUs
2456 * Composition time offset = composition time - decoding time
2457 */
2458 int64_t decodingTimeUs;
2459 CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
2460 decodingTimeUs -= previousPausedDurationUs;
2461 cttsOffsetTimeUs =
2462 timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
2463 if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) {
2464 copy->release();
2465 return ERROR_MALFORMED;
2466 }
2467
2468 timestampUs = decodingTimeUs;
2469 ALOGV("decoding time: %" PRId64 " and ctts offset time: %" PRId64,
2470 timestampUs, cttsOffsetTimeUs);
2471
2472 // Update ctts box table if necessary
2473 currCttsOffsetTimeTicks =
2474 (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL;
2475 if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) {
2476 copy->release();
2477 return ERROR_MALFORMED;
2478 }
2479
2480 if (mStszTableEntries->count() == 0) {
2481 // Force the first ctts table entry to have one single entry
2482 // so that we can do adjustment for the initial track start
2483 // time offset easily in writeCttsBox().
2484 lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
2485 addOneCttsTableEntry(1, currCttsOffsetTimeTicks);
2486 cttsSampleCount = 0; // No sample in ctts box is pending
2487 } else {
2488 if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) {
2489 addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
2490 lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
2491 cttsSampleCount = 1; // One sample in ctts box is pending
2492 } else {
2493 ++cttsSampleCount;
2494 }
2495 }
2496
2497 // Update ctts time offset range
2498 if (mStszTableEntries->count() == 0) {
2499 mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2500 mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2501 } else {
2502 if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) {
2503 mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2504 } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) {
2505 mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2506 }
2507 }
2508
2509 }
2510
2511 if (mOwner->isRealTimeRecording()) {
2512 if (mIsAudio) {
2513 updateDriftTime(meta_data);
2514 }
2515 }
2516
2517 if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
2518 copy->release();
2519 return ERROR_MALFORMED;
2520 }
2521
2522 ALOGV("%s media time stamp: %" PRId64 " and previous paused duration %" PRId64,
2523 trackName, timestampUs, previousPausedDurationUs);
2524 if (timestampUs > mTrackDurationUs) {
2525 mTrackDurationUs = timestampUs;
2526 }
2527
2528 // We need to use the time scale based ticks, rather than the
2529 // timestamp itself to determine whether we have to use a new
2530 // stts entry, since we may have rounding errors.
2531 // The calculation is intended to reduce the accumulated
2532 // rounding errors.
2533 currDurationTicks =
2534 ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
2535 (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
2536 if (currDurationTicks < 0ll) {
2537 ALOGE("do not support out of order frames (timestamp: %lld < last: %lld for %s track",
2538 (long long)timestampUs, (long long)lastTimestampUs, trackName);
2539 copy->release();
2540 mSource->stop();
2541 return UNKNOWN_ERROR;
2542 }
2543
2544 // if the duration is different for this sample, see if it is close enough to the previous
2545 // duration that we can fudge it and use the same value, to avoid filling the stts table
2546 // with lots of near-identical entries.
2547 // "close enough" here means that the current duration needs to be adjusted by less
2548 // than 0.1 milliseconds
2549 if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) {
2550 int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL
2551 + (mTimeScale / 2)) / mTimeScale;
2552 if (deltaUs > -100 && deltaUs < 100) {
2553 // use previous ticks, and adjust timestamp as if it was actually that number
2554 // of ticks
2555 currDurationTicks = lastDurationTicks;
2556 timestampUs += deltaUs;
2557 }
2558 }
2559
2560 mStszTableEntries->add(htonl(sampleSize));
2561 if (mStszTableEntries->count() > 2) {
2562
2563 // Force the first sample to have its own stts entry so that
2564 // we can adjust its value later to maintain the A/V sync.
2565 if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) {
2566 addOneSttsTableEntry(sampleCount, lastDurationTicks);
2567 sampleCount = 1;
2568 } else {
2569 ++sampleCount;
2570 }
2571
2572 }
2573 if (mSamplesHaveSameSize) {
2574 if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) {
2575 mSamplesHaveSameSize = false;
2576 }
2577 previousSampleSize = sampleSize;
2578 }
2579 ALOGV("%s timestampUs/lastTimestampUs: %" PRId64 "/%" PRId64,
2580 trackName, timestampUs, lastTimestampUs);
2581 lastDurationUs = timestampUs - lastTimestampUs;
2582 lastDurationTicks = currDurationTicks;
2583 lastTimestampUs = timestampUs;
2584
2585 if (isSync != 0) {
2586 addOneStssTableEntry(mStszTableEntries->count());
2587 }
2588
2589 if (mTrackingProgressStatus) {
2590 if (mPreviousTrackTimeUs <= 0) {
2591 mPreviousTrackTimeUs = mStartTimestampUs;
2592 }
2593 trackProgressStatus(timestampUs);
2594 }
2595 if (!hasMultipleTracks) {
2596 off64_t offset = (mIsAvc || mIsHevc) ? mOwner->addLengthPrefixedSample_l(copy)
2597 : mOwner->addSample_l(copy);
2598
2599 uint32_t count = (mOwner->use32BitFileOffset()
2600 ? mStcoTableEntries->count()
2601 : mCo64TableEntries->count());
2602
2603 if (count == 0) {
2604 addChunkOffset(offset);
2605 }
2606 copy->release();
2607 copy = NULL;
2608 continue;
2609 }
2610
2611 mChunkSamples.push_back(copy);
2612 if (interleaveDurationUs == 0) {
2613 addOneStscTableEntry(++nChunks, 1);
2614 bufferChunk(timestampUs);
2615 } else {
2616 if (chunkTimestampUs == 0) {
2617 chunkTimestampUs = timestampUs;
2618 } else {
2619 int64_t chunkDurationUs = timestampUs - chunkTimestampUs;
2620 if (chunkDurationUs > interleaveDurationUs) {
2621 if (chunkDurationUs > mMaxChunkDurationUs) {
2622 mMaxChunkDurationUs = chunkDurationUs;
2623 }
2624 ++nChunks;
2625 if (nChunks == 1 || // First chunk
2626 lastSamplesPerChunk != mChunkSamples.size()) {
2627 lastSamplesPerChunk = mChunkSamples.size();
2628 addOneStscTableEntry(nChunks, lastSamplesPerChunk);
2629 }
2630 bufferChunk(timestampUs);
2631 chunkTimestampUs = timestampUs;
2632 }
2633 }
2634 }
2635
2636 }
2637
2638 if (isTrackMalFormed()) {
2639 err = ERROR_MALFORMED;
2640 }
2641
2642 mOwner->trackProgressStatus(mTrackId, -1, err);
2643
2644 // Last chunk
2645 if (!hasMultipleTracks) {
2646 addOneStscTableEntry(1, mStszTableEntries->count());
2647 } else if (!mChunkSamples.empty()) {
2648 addOneStscTableEntry(++nChunks, mChunkSamples.size());
2649 bufferChunk(timestampUs);
2650 }
2651
2652 // We don't really know how long the last frame lasts, since
2653 // there is no frame time after it, just repeat the previous
2654 // frame's duration.
2655 if (mStszTableEntries->count() == 1) {
2656 lastDurationUs = 0; // A single sample's duration
2657 lastDurationTicks = 0;
2658 } else {
2659 ++sampleCount; // Count for the last sample
2660 }
2661
2662 if (mStszTableEntries->count() <= 2) {
2663 addOneSttsTableEntry(1, lastDurationTicks);
2664 if (sampleCount - 1 > 0) {
2665 addOneSttsTableEntry(sampleCount - 1, lastDurationTicks);
2666 }
2667 } else {
2668 addOneSttsTableEntry(sampleCount, lastDurationTicks);
2669 }
2670
2671 // The last ctts box may not have been written yet, and this
2672 // is to make sure that we write out the last ctts box.
2673 if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) {
2674 if (cttsSampleCount > 0) {
2675 addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
2676 }
2677 }
2678
2679 mTrackDurationUs += lastDurationUs;
2680 mReachedEOS = true;
2681
2682 sendTrackSummary(hasMultipleTracks);
2683
2684 ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
2685 count, nZeroLengthFrames, mStszTableEntries->count(), trackName);
2686 if (mIsAudio) {
2687 ALOGI("Audio track drift time: %" PRId64 " us", mOwner->getDriftTimeUs());
2688 }
2689
2690 if (err == ERROR_END_OF_STREAM) {
2691 return OK;
2692 }
2693 return err;
2694 }
2695
isTrackMalFormed() const2696 bool MPEG4Writer::Track::isTrackMalFormed() const {
2697 if (mStszTableEntries->count() == 0) { // no samples written
2698 ALOGE("The number of recorded samples is 0");
2699 return true;
2700 }
2701
2702 if (!mIsAudio && mStssTableEntries->count() == 0) { // no sync frames for video
2703 ALOGE("There are no sync frames for video track");
2704 return true;
2705 }
2706
2707 if (OK != checkCodecSpecificData()) { // no codec specific data
2708 return true;
2709 }
2710
2711 return false;
2712 }
2713
sendTrackSummary(bool hasMultipleTracks)2714 void MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) {
2715
2716 // Send track summary only if test mode is enabled.
2717 if (!isTestModeEnabled()) {
2718 return;
2719 }
2720
2721 int trackNum = (mTrackId << 28);
2722
2723 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2724 trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE,
2725 mIsAudio? 0: 1);
2726
2727 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2728 trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS,
2729 mTrackDurationUs / 1000);
2730
2731 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2732 trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES,
2733 mStszTableEntries->count());
2734
2735 {
2736 // The system delay time excluding the requested initial delay that
2737 // is used to eliminate the recording sound.
2738 int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
2739 if (startTimeOffsetUs < 0) { // Start time offset was not set
2740 startTimeOffsetUs = kInitialDelayTimeUs;
2741 }
2742 int64_t initialDelayUs =
2743 mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs;
2744
2745 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2746 trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS,
2747 (initialDelayUs) / 1000);
2748 }
2749
2750 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2751 trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES,
2752 mMdatSizeBytes / 1024);
2753
2754 if (hasMultipleTracks) {
2755 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2756 trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS,
2757 mMaxChunkDurationUs / 1000);
2758
2759 int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
2760 if (mStartTimestampUs != moovStartTimeUs) {
2761 int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
2762 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2763 trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS,
2764 startTimeOffsetUs / 1000);
2765 }
2766 }
2767 }
2768
trackProgressStatus(int64_t timeUs,status_t err)2769 void MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
2770 ALOGV("trackProgressStatus: %" PRId64 " us", timeUs);
2771
2772 if (mTrackEveryTimeDurationUs > 0 &&
2773 timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
2774 ALOGV("Fire time tracking progress status at %" PRId64 " us", timeUs);
2775 mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err);
2776 mPreviousTrackTimeUs = timeUs;
2777 }
2778 }
2779
trackProgressStatus(size_t trackId,int64_t timeUs,status_t err)2780 void MPEG4Writer::trackProgressStatus(
2781 size_t trackId, int64_t timeUs, status_t err) {
2782 Mutex::Autolock lock(mLock);
2783 int32_t trackNum = (trackId << 28);
2784
2785 // Error notification
2786 // Do not consider ERROR_END_OF_STREAM an error
2787 if (err != OK && err != ERROR_END_OF_STREAM) {
2788 notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
2789 trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL,
2790 err);
2791 return;
2792 }
2793
2794 if (timeUs == -1) {
2795 // Send completion notification
2796 notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2797 trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS,
2798 err);
2799 } else {
2800 // Send progress status
2801 notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2802 trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME,
2803 timeUs / 1000);
2804 }
2805 }
2806
setDriftTimeUs(int64_t driftTimeUs)2807 void MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) {
2808 ALOGV("setDriftTimeUs: %" PRId64 " us", driftTimeUs);
2809 Mutex::Autolock autolock(mLock);
2810 mDriftTimeUs = driftTimeUs;
2811 }
2812
getDriftTimeUs()2813 int64_t MPEG4Writer::getDriftTimeUs() {
2814 ALOGV("getDriftTimeUs: %" PRId64 " us", mDriftTimeUs);
2815 Mutex::Autolock autolock(mLock);
2816 return mDriftTimeUs;
2817 }
2818
isRealTimeRecording() const2819 bool MPEG4Writer::isRealTimeRecording() const {
2820 return mIsRealTimeRecording;
2821 }
2822
useNalLengthFour()2823 bool MPEG4Writer::useNalLengthFour() {
2824 return mUse4ByteNalLength;
2825 }
2826
bufferChunk(int64_t timestampUs)2827 void MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
2828 ALOGV("bufferChunk");
2829
2830 Chunk chunk(this, timestampUs, mChunkSamples);
2831 mOwner->bufferChunk(chunk);
2832 mChunkSamples.clear();
2833 }
2834
getDurationUs() const2835 int64_t MPEG4Writer::Track::getDurationUs() const {
2836 return mTrackDurationUs;
2837 }
2838
getEstimatedTrackSizeBytes() const2839 int64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
2840 return mEstimatedTrackSizeBytes;
2841 }
2842
checkCodecSpecificData() const2843 status_t MPEG4Writer::Track::checkCodecSpecificData() const {
2844 const char *mime;
2845 CHECK(mMeta->findCString(kKeyMIMEType, &mime));
2846 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
2847 !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
2848 !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime) ||
2849 !strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
2850 if (!mCodecSpecificData ||
2851 mCodecSpecificDataSize <= 0) {
2852 ALOGE("Missing codec specific data");
2853 return ERROR_MALFORMED;
2854 }
2855 } else {
2856 if (mCodecSpecificData ||
2857 mCodecSpecificDataSize > 0) {
2858 ALOGE("Unexepected codec specific data found");
2859 return ERROR_MALFORMED;
2860 }
2861 }
2862 return OK;
2863 }
2864
writeTrackHeader(bool use32BitOffset)2865 void MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) {
2866
2867 ALOGV("%s track time scale: %d",
2868 mIsAudio? "Audio": "Video", mTimeScale);
2869
2870 uint32_t now = getMpeg4Time();
2871 mOwner->beginBox("trak");
2872 writeTkhdBox(now);
2873 mOwner->beginBox("mdia");
2874 writeMdhdBox(now);
2875 writeHdlrBox();
2876 mOwner->beginBox("minf");
2877 if (mIsAudio) {
2878 writeSmhdBox();
2879 } else {
2880 writeVmhdBox();
2881 }
2882 writeDinfBox();
2883 writeStblBox(use32BitOffset);
2884 mOwner->endBox(); // minf
2885 mOwner->endBox(); // mdia
2886 mOwner->endBox(); // trak
2887 }
2888
writeStblBox(bool use32BitOffset)2889 void MPEG4Writer::Track::writeStblBox(bool use32BitOffset) {
2890 mOwner->beginBox("stbl");
2891 mOwner->beginBox("stsd");
2892 mOwner->writeInt32(0); // version=0, flags=0
2893 mOwner->writeInt32(1); // entry count
2894 if (mIsAudio) {
2895 writeAudioFourCCBox();
2896 } else {
2897 writeVideoFourCCBox();
2898 }
2899 mOwner->endBox(); // stsd
2900 writeSttsBox();
2901 writeCttsBox();
2902 if (!mIsAudio) {
2903 writeStssBox();
2904 }
2905 writeStszBox();
2906 writeStscBox();
2907 writeStcoBox(use32BitOffset);
2908 mOwner->endBox(); // stbl
2909 }
2910
writeVideoFourCCBox()2911 void MPEG4Writer::Track::writeVideoFourCCBox() {
2912 const char *mime;
2913 bool success = mMeta->findCString(kKeyMIMEType, &mime);
2914 CHECK(success);
2915 const char *fourcc = getFourCCForMime(mime);
2916 if (fourcc == NULL) {
2917 ALOGE("Unknown mime type '%s'.", mime);
2918 CHECK(!"should not be here, unknown mime type.");
2919 }
2920
2921 mOwner->beginBox(fourcc); // video format
2922 mOwner->writeInt32(0); // reserved
2923 mOwner->writeInt16(0); // reserved
2924 mOwner->writeInt16(1); // data ref index
2925 mOwner->writeInt16(0); // predefined
2926 mOwner->writeInt16(0); // reserved
2927 mOwner->writeInt32(0); // predefined
2928 mOwner->writeInt32(0); // predefined
2929 mOwner->writeInt32(0); // predefined
2930
2931 int32_t width, height;
2932 success = mMeta->findInt32(kKeyWidth, &width);
2933 success = success && mMeta->findInt32(kKeyHeight, &height);
2934 CHECK(success);
2935
2936 mOwner->writeInt16(width);
2937 mOwner->writeInt16(height);
2938 mOwner->writeInt32(0x480000); // horiz resolution
2939 mOwner->writeInt32(0x480000); // vert resolution
2940 mOwner->writeInt32(0); // reserved
2941 mOwner->writeInt16(1); // frame count
2942 mOwner->writeInt8(0); // compressor string length
2943 mOwner->write(" ", 31);
2944 mOwner->writeInt16(0x18); // depth
2945 mOwner->writeInt16(-1); // predefined
2946
2947 CHECK_LT(23 + mCodecSpecificDataSize, 128);
2948
2949 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
2950 writeMp4vEsdsBox();
2951 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
2952 writeD263Box();
2953 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2954 writeAvccBox();
2955 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
2956 writeHvccBox();
2957 }
2958
2959 writePaspBox();
2960 writeColrBox();
2961 mOwner->endBox(); // mp4v, s263 or avc1
2962 }
2963
writeColrBox()2964 void MPEG4Writer::Track::writeColrBox() {
2965 ColorAspects aspects;
2966 memset(&aspects, 0, sizeof(aspects));
2967 // TRICKY: using | instead of || because we want to execute all findInt32-s
2968 if (mMeta->findInt32(kKeyColorPrimaries, (int32_t*)&aspects.mPrimaries)
2969 | mMeta->findInt32(kKeyTransferFunction, (int32_t*)&aspects.mTransfer)
2970 | mMeta->findInt32(kKeyColorMatrix, (int32_t*)&aspects.mMatrixCoeffs)
2971 | mMeta->findInt32(kKeyColorRange, (int32_t*)&aspects.mRange)) {
2972 int32_t primaries, transfer, coeffs;
2973 bool fullRange;
2974 ColorUtils::convertCodecColorAspectsToIsoAspects(
2975 aspects, &primaries, &transfer, &coeffs, &fullRange);
2976 mOwner->beginBox("colr");
2977 mOwner->writeFourcc("nclx");
2978 mOwner->writeInt16(primaries);
2979 mOwner->writeInt16(transfer);
2980 mOwner->writeInt16(coeffs);
2981 mOwner->writeInt8(fullRange ? 128 : 0);
2982 mOwner->endBox(); // colr
2983 }
2984 }
2985
writeAudioFourCCBox()2986 void MPEG4Writer::Track::writeAudioFourCCBox() {
2987 const char *mime;
2988 bool success = mMeta->findCString(kKeyMIMEType, &mime);
2989 CHECK(success);
2990 const char *fourcc = getFourCCForMime(mime);
2991 if (fourcc == NULL) {
2992 ALOGE("Unknown mime type '%s'.", mime);
2993 CHECK(!"should not be here, unknown mime type.");
2994 }
2995
2996 mOwner->beginBox(fourcc); // audio format
2997 mOwner->writeInt32(0); // reserved
2998 mOwner->writeInt16(0); // reserved
2999 mOwner->writeInt16(0x1); // data ref index
3000 mOwner->writeInt32(0); // reserved
3001 mOwner->writeInt32(0); // reserved
3002 int32_t nChannels;
3003 CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
3004 mOwner->writeInt16(nChannels); // channel count
3005 mOwner->writeInt16(16); // sample size
3006 mOwner->writeInt16(0); // predefined
3007 mOwner->writeInt16(0); // reserved
3008
3009 int32_t samplerate;
3010 success = mMeta->findInt32(kKeySampleRate, &samplerate);
3011 CHECK(success);
3012 mOwner->writeInt32(samplerate << 16);
3013 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
3014 writeMp4aEsdsBox();
3015 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
3016 !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
3017 writeDamrBox();
3018 }
3019 mOwner->endBox();
3020 }
3021
writeMp4aEsdsBox()3022 void MPEG4Writer::Track::writeMp4aEsdsBox() {
3023 mOwner->beginBox("esds");
3024 CHECK(mCodecSpecificData);
3025 CHECK_GT(mCodecSpecificDataSize, 0);
3026
3027 // Make sure all sizes encode to a single byte.
3028 CHECK_LT(mCodecSpecificDataSize + 23, 128);
3029
3030 mOwner->writeInt32(0); // version=0, flags=0
3031 mOwner->writeInt8(0x03); // ES_DescrTag
3032 mOwner->writeInt8(23 + mCodecSpecificDataSize);
3033 mOwner->writeInt16(0x0000);// ES_ID
3034 mOwner->writeInt8(0x00);
3035
3036 mOwner->writeInt8(0x04); // DecoderConfigDescrTag
3037 mOwner->writeInt8(15 + mCodecSpecificDataSize);
3038 mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2
3039 mOwner->writeInt8(0x15); // streamType AudioStream
3040
3041 mOwner->writeInt16(0x03); // XXX
3042 mOwner->writeInt8(0x00); // buffer size 24-bit (0x300)
3043
3044 int32_t avgBitrate = 0;
3045 (void)mMeta->findInt32(kKeyBitRate, &avgBitrate);
3046 int32_t maxBitrate = 0;
3047 (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate);
3048 mOwner->writeInt32(maxBitrate);
3049 mOwner->writeInt32(avgBitrate);
3050
3051 mOwner->writeInt8(0x05); // DecoderSpecificInfoTag
3052 mOwner->writeInt8(mCodecSpecificDataSize);
3053 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3054
3055 static const uint8_t kData2[] = {
3056 0x06, // SLConfigDescriptorTag
3057 0x01,
3058 0x02
3059 };
3060 mOwner->write(kData2, sizeof(kData2));
3061
3062 mOwner->endBox(); // esds
3063 }
3064
writeMp4vEsdsBox()3065 void MPEG4Writer::Track::writeMp4vEsdsBox() {
3066 CHECK(mCodecSpecificData);
3067 CHECK_GT(mCodecSpecificDataSize, 0);
3068 mOwner->beginBox("esds");
3069
3070 mOwner->writeInt32(0); // version=0, flags=0
3071
3072 mOwner->writeInt8(0x03); // ES_DescrTag
3073 mOwner->writeInt8(23 + mCodecSpecificDataSize);
3074 mOwner->writeInt16(0x0000); // ES_ID
3075 mOwner->writeInt8(0x1f);
3076
3077 mOwner->writeInt8(0x04); // DecoderConfigDescrTag
3078 mOwner->writeInt8(15 + mCodecSpecificDataSize);
3079 mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2
3080 mOwner->writeInt8(0x11); // streamType VisualStream
3081
3082 static const uint8_t kData[] = {
3083 0x01, 0x77, 0x00, // buffer size 96000 bytes
3084 };
3085 mOwner->write(kData, sizeof(kData));
3086
3087 int32_t avgBitrate = 0;
3088 (void)mMeta->findInt32(kKeyBitRate, &avgBitrate);
3089 int32_t maxBitrate = 0;
3090 (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate);
3091 mOwner->writeInt32(maxBitrate);
3092 mOwner->writeInt32(avgBitrate);
3093
3094 mOwner->writeInt8(0x05); // DecoderSpecificInfoTag
3095
3096 mOwner->writeInt8(mCodecSpecificDataSize);
3097 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3098
3099 static const uint8_t kData2[] = {
3100 0x06, // SLConfigDescriptorTag
3101 0x01,
3102 0x02
3103 };
3104 mOwner->write(kData2, sizeof(kData2));
3105
3106 mOwner->endBox(); // esds
3107 }
3108
writeTkhdBox(uint32_t now)3109 void MPEG4Writer::Track::writeTkhdBox(uint32_t now) {
3110 mOwner->beginBox("tkhd");
3111 // Flags = 7 to indicate that the track is enabled, and
3112 // part of the presentation
3113 mOwner->writeInt32(0x07); // version=0, flags=7
3114 mOwner->writeInt32(now); // creation time
3115 mOwner->writeInt32(now); // modification time
3116 mOwner->writeInt32(mTrackId); // track id starts with 1
3117 mOwner->writeInt32(0); // reserved
3118 int64_t trakDurationUs = getDurationUs();
3119 int32_t mvhdTimeScale = mOwner->getTimeScale();
3120 int32_t tkhdDuration =
3121 (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
3122 mOwner->writeInt32(tkhdDuration); // in mvhd timescale
3123 mOwner->writeInt32(0); // reserved
3124 mOwner->writeInt32(0); // reserved
3125 mOwner->writeInt16(0); // layer
3126 mOwner->writeInt16(0); // alternate group
3127 mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume
3128 mOwner->writeInt16(0); // reserved
3129
3130 mOwner->writeCompositionMatrix(mRotation); // matrix
3131
3132 if (mIsAudio) {
3133 mOwner->writeInt32(0);
3134 mOwner->writeInt32(0);
3135 } else {
3136 int32_t width, height;
3137 bool success = mMeta->findInt32(kKeyWidth, &width);
3138 success = success && mMeta->findInt32(kKeyHeight, &height);
3139 CHECK(success);
3140
3141 mOwner->writeInt32(width << 16); // 32-bit fixed-point value
3142 mOwner->writeInt32(height << 16); // 32-bit fixed-point value
3143 }
3144 mOwner->endBox(); // tkhd
3145 }
3146
writeVmhdBox()3147 void MPEG4Writer::Track::writeVmhdBox() {
3148 mOwner->beginBox("vmhd");
3149 mOwner->writeInt32(0x01); // version=0, flags=1
3150 mOwner->writeInt16(0); // graphics mode
3151 mOwner->writeInt16(0); // opcolor
3152 mOwner->writeInt16(0);
3153 mOwner->writeInt16(0);
3154 mOwner->endBox();
3155 }
3156
writeSmhdBox()3157 void MPEG4Writer::Track::writeSmhdBox() {
3158 mOwner->beginBox("smhd");
3159 mOwner->writeInt32(0); // version=0, flags=0
3160 mOwner->writeInt16(0); // balance
3161 mOwner->writeInt16(0); // reserved
3162 mOwner->endBox();
3163 }
3164
writeHdlrBox()3165 void MPEG4Writer::Track::writeHdlrBox() {
3166 mOwner->beginBox("hdlr");
3167 mOwner->writeInt32(0); // version=0, flags=0
3168 mOwner->writeInt32(0); // component type: should be mhlr
3169 mOwner->writeFourcc(mIsAudio ? "soun" : "vide"); // component subtype
3170 mOwner->writeInt32(0); // reserved
3171 mOwner->writeInt32(0); // reserved
3172 mOwner->writeInt32(0); // reserved
3173 // Removing "r" for the name string just makes the string 4 byte aligned
3174 mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle"); // name
3175 mOwner->endBox();
3176 }
3177
writeMdhdBox(uint32_t now)3178 void MPEG4Writer::Track::writeMdhdBox(uint32_t now) {
3179 int64_t trakDurationUs = getDurationUs();
3180 mOwner->beginBox("mdhd");
3181 mOwner->writeInt32(0); // version=0, flags=0
3182 mOwner->writeInt32(now); // creation time
3183 mOwner->writeInt32(now); // modification time
3184 mOwner->writeInt32(mTimeScale); // media timescale
3185 int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
3186 mOwner->writeInt32(mdhdDuration); // use media timescale
3187 // Language follows the three letter standard ISO-639-2/T
3188 // 'e', 'n', 'g' for "English", for instance.
3189 // Each character is packed as the difference between its ASCII value and 0x60.
3190 // For "English", these are 00101, 01110, 00111.
3191 // XXX: Where is the padding bit located: 0x15C7?
3192 mOwner->writeInt16(0); // language code
3193 mOwner->writeInt16(0); // predefined
3194 mOwner->endBox();
3195 }
3196
writeDamrBox()3197 void MPEG4Writer::Track::writeDamrBox() {
3198 // 3gpp2 Spec AMRSampleEntry fields
3199 mOwner->beginBox("damr");
3200 mOwner->writeCString(" "); // vendor: 4 bytes
3201 mOwner->writeInt8(0); // decoder version
3202 mOwner->writeInt16(0x83FF); // mode set: all enabled
3203 mOwner->writeInt8(0); // mode change period
3204 mOwner->writeInt8(1); // frames per sample
3205 mOwner->endBox();
3206 }
3207
writeUrlBox()3208 void MPEG4Writer::Track::writeUrlBox() {
3209 // The table index here refers to the sample description index
3210 // in the sample table entries.
3211 mOwner->beginBox("url ");
3212 mOwner->writeInt32(1); // version=0, flags=1 (self-contained)
3213 mOwner->endBox(); // url
3214 }
3215
writeDrefBox()3216 void MPEG4Writer::Track::writeDrefBox() {
3217 mOwner->beginBox("dref");
3218 mOwner->writeInt32(0); // version=0, flags=0
3219 mOwner->writeInt32(1); // entry count (either url or urn)
3220 writeUrlBox();
3221 mOwner->endBox(); // dref
3222 }
3223
writeDinfBox()3224 void MPEG4Writer::Track::writeDinfBox() {
3225 mOwner->beginBox("dinf");
3226 writeDrefBox();
3227 mOwner->endBox(); // dinf
3228 }
3229
writeAvccBox()3230 void MPEG4Writer::Track::writeAvccBox() {
3231 CHECK(mCodecSpecificData);
3232 CHECK_GE(mCodecSpecificDataSize, 5);
3233
3234 // Patch avcc's lengthSize field to match the number
3235 // of bytes we use to indicate the size of a nal unit.
3236 uint8_t *ptr = (uint8_t *)mCodecSpecificData;
3237 ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
3238 mOwner->beginBox("avcC");
3239 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3240 mOwner->endBox(); // avcC
3241 }
3242
3243
writeHvccBox()3244 void MPEG4Writer::Track::writeHvccBox() {
3245 CHECK(mCodecSpecificData);
3246 CHECK_GE(mCodecSpecificDataSize, 5);
3247
3248 // Patch avcc's lengthSize field to match the number
3249 // of bytes we use to indicate the size of a nal unit.
3250 uint8_t *ptr = (uint8_t *)mCodecSpecificData;
3251 ptr[21] = (ptr[21] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
3252 mOwner->beginBox("hvcC");
3253 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3254 mOwner->endBox(); // hvcC
3255 }
3256
writeD263Box()3257 void MPEG4Writer::Track::writeD263Box() {
3258 mOwner->beginBox("d263");
3259 mOwner->writeInt32(0); // vendor
3260 mOwner->writeInt8(0); // decoder version
3261 mOwner->writeInt8(10); // level: 10
3262 mOwner->writeInt8(0); // profile: 0
3263 mOwner->endBox(); // d263
3264 }
3265
3266 // This is useful if the pixel is not square
writePaspBox()3267 void MPEG4Writer::Track::writePaspBox() {
3268 mOwner->beginBox("pasp");
3269 mOwner->writeInt32(1 << 16); // hspacing
3270 mOwner->writeInt32(1 << 16); // vspacing
3271 mOwner->endBox(); // pasp
3272 }
3273
getStartTimeOffsetScaledTime() const3274 int32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const {
3275 int64_t trackStartTimeOffsetUs = 0;
3276 int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
3277 if (mStartTimestampUs != moovStartTimeUs) {
3278 CHECK_GT(mStartTimestampUs, moovStartTimeUs);
3279 trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
3280 }
3281 return (trackStartTimeOffsetUs * mTimeScale + 500000LL) / 1000000LL;
3282 }
3283
writeSttsBox()3284 void MPEG4Writer::Track::writeSttsBox() {
3285 mOwner->beginBox("stts");
3286 mOwner->writeInt32(0); // version=0, flags=0
3287 uint32_t duration;
3288 CHECK(mSttsTableEntries->get(duration, 1));
3289 duration = htonl(duration); // Back to host byte order
3290 mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1);
3291 mSttsTableEntries->write(mOwner);
3292 mOwner->endBox(); // stts
3293 }
3294
writeCttsBox()3295 void MPEG4Writer::Track::writeCttsBox() {
3296 if (mIsAudio) { // ctts is not for audio
3297 return;
3298 }
3299
3300 // There is no B frame at all
3301 if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) {
3302 return;
3303 }
3304
3305 // Do not write ctts box when there is no need to have it.
3306 if (mCttsTableEntries->count() == 0) {
3307 return;
3308 }
3309
3310 ALOGV("ctts box has %d entries with range [%" PRId64 ", %" PRId64 "]",
3311 mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs);
3312
3313 mOwner->beginBox("ctts");
3314 mOwner->writeInt32(0); // version=0, flags=0
3315 uint32_t duration;
3316 CHECK(mCttsTableEntries->get(duration, 1));
3317 duration = htonl(duration); // Back host byte order
3318 mCttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime() - mMinCttsOffsetTimeUs), 1);
3319 mCttsTableEntries->write(mOwner);
3320 mOwner->endBox(); // ctts
3321 }
3322
writeStssBox()3323 void MPEG4Writer::Track::writeStssBox() {
3324 mOwner->beginBox("stss");
3325 mOwner->writeInt32(0); // version=0, flags=0
3326 mStssTableEntries->write(mOwner);
3327 mOwner->endBox(); // stss
3328 }
3329
writeStszBox()3330 void MPEG4Writer::Track::writeStszBox() {
3331 mOwner->beginBox("stsz");
3332 mOwner->writeInt32(0); // version=0, flags=0
3333 mOwner->writeInt32(0);
3334 mStszTableEntries->write(mOwner);
3335 mOwner->endBox(); // stsz
3336 }
3337
writeStscBox()3338 void MPEG4Writer::Track::writeStscBox() {
3339 mOwner->beginBox("stsc");
3340 mOwner->writeInt32(0); // version=0, flags=0
3341 mStscTableEntries->write(mOwner);
3342 mOwner->endBox(); // stsc
3343 }
3344
writeStcoBox(bool use32BitOffset)3345 void MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) {
3346 mOwner->beginBox(use32BitOffset? "stco": "co64");
3347 mOwner->writeInt32(0); // version=0, flags=0
3348 if (use32BitOffset) {
3349 mStcoTableEntries->write(mOwner);
3350 } else {
3351 mCo64TableEntries->write(mOwner);
3352 }
3353 mOwner->endBox(); // stco or co64
3354 }
3355
writeUdtaBox()3356 void MPEG4Writer::writeUdtaBox() {
3357 beginBox("udta");
3358 writeGeoDataBox();
3359 endBox();
3360 }
3361
writeHdlr()3362 void MPEG4Writer::writeHdlr() {
3363 beginBox("hdlr");
3364 writeInt32(0); // Version, Flags
3365 writeInt32(0); // Predefined
3366 writeFourcc("mdta");
3367 writeInt32(0); // Reserved[0]
3368 writeInt32(0); // Reserved[1]
3369 writeInt32(0); // Reserved[2]
3370 writeInt8(0); // Name (empty)
3371 endBox();
3372 }
3373
writeKeys()3374 void MPEG4Writer::writeKeys() {
3375 size_t count = mMetaKeys->countEntries();
3376
3377 beginBox("keys");
3378 writeInt32(0); // Version, Flags
3379 writeInt32(count); // Entry_count
3380 for (size_t i = 0; i < count; i++) {
3381 AMessage::Type type;
3382 const char *key = mMetaKeys->getEntryNameAt(i, &type);
3383 size_t n = strlen(key);
3384 writeInt32(n + 8);
3385 writeFourcc("mdta");
3386 write(key, n); // write without the \0
3387 }
3388 endBox();
3389 }
3390
writeIlst()3391 void MPEG4Writer::writeIlst() {
3392 size_t count = mMetaKeys->countEntries();
3393
3394 beginBox("ilst");
3395 for (size_t i = 0; i < count; i++) {
3396 beginBox(i + 1); // key id (1-based)
3397 beginBox("data");
3398 AMessage::Type type;
3399 const char *key = mMetaKeys->getEntryNameAt(i, &type);
3400 switch (type) {
3401 case AMessage::kTypeString:
3402 {
3403 AString val;
3404 CHECK(mMetaKeys->findString(key, &val));
3405 writeInt32(1); // type = UTF8
3406 writeInt32(0); // default country/language
3407 write(val.c_str(), strlen(val.c_str())); // write without \0
3408 break;
3409 }
3410
3411 case AMessage::kTypeFloat:
3412 {
3413 float val;
3414 CHECK(mMetaKeys->findFloat(key, &val));
3415 writeInt32(23); // type = float32
3416 writeInt32(0); // default country/language
3417 writeInt32(*reinterpret_cast<int32_t *>(&val));
3418 break;
3419 }
3420
3421 case AMessage::kTypeInt32:
3422 {
3423 int32_t val;
3424 CHECK(mMetaKeys->findInt32(key, &val));
3425 writeInt32(67); // type = signed int32
3426 writeInt32(0); // default country/language
3427 writeInt32(val);
3428 break;
3429 }
3430
3431 default:
3432 {
3433 ALOGW("Unsupported key type, writing 0 instead");
3434 writeInt32(77); // type = unsigned int32
3435 writeInt32(0); // default country/language
3436 writeInt32(0);
3437 break;
3438 }
3439 }
3440 endBox(); // data
3441 endBox(); // key id
3442 }
3443 endBox(); // ilst
3444 }
3445
writeMetaBox()3446 void MPEG4Writer::writeMetaBox() {
3447 size_t count = mMetaKeys->countEntries();
3448 if (count == 0) {
3449 return;
3450 }
3451
3452 beginBox("meta");
3453 writeHdlr();
3454 writeKeys();
3455 writeIlst();
3456 endBox();
3457 }
3458
3459 /*
3460 * Geodata is stored according to ISO-6709 standard.
3461 */
writeGeoDataBox()3462 void MPEG4Writer::writeGeoDataBox() {
3463 beginBox("\xA9xyz");
3464 /*
3465 * For historical reasons, any user data start
3466 * with "\0xA9", must be followed by its assoicated
3467 * language code.
3468 * 0x0012: text string length
3469 * 0x15c7: lang (locale) code: en
3470 */
3471 writeInt32(0x001215c7);
3472 writeLatitude(mLatitudex10000);
3473 writeLongitude(mLongitudex10000);
3474 writeInt8(0x2F);
3475 endBox();
3476 }
3477
3478 } // namespace android
3479