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