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