MPEG4Writer.cpp revision a9292fe1c19e8a9b43398ba3d69284c215d7589f
120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber/*
220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Copyright (C) 2009 The Android Open Source Project
320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * you may not use this file except in compliance with the License.
620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * You may obtain a copy of the License at
720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
1020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Unless required by applicable law or agreed to in writing, software
1120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * See the License for the specific language governing permissions and
1420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * limitations under the License.
1520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber */
1620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17050b28a593350047845a45a14cc5026221ac1620James Dong//#define LOG_NDEBUG 0
18050b28a593350047845a45a14cc5026221ac1620James Dong#define LOG_TAG "MPEG4Writer"
19050b28a593350047845a45a14cc5026221ac1620James Dong
20826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar#include <algorithm>
21826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar
2220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <arpa/inet.h>
23a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <fcntl.h>
24a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <inttypes.h>
2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <pthread.h>
26a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong#include <sys/prctl.h>
27a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <sys/stat.h>
28a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <sys/types.h>
29a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <unistd.h>
30a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn
31a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <utils/Log.h>
3220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar#include <functional>
34c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar
3543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong#include <media/stagefright/foundation/ADebug.h>
36e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang#include <media/stagefright/foundation/AMessage.h>
37826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar#include <media/stagefright/foundation/AUtils.h>
3858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar#include <media/stagefright/foundation/ColorUtils.h>
3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h>
4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h>
4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
4218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
4303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#include <media/stagefright/MediaErrors.h>
4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h>
4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h>
46d599cd4573b5a2d5914c5040e0565ef866749b77James Dong#include <media/mediarecorder.h>
4707ec01904613a0bac32caaa8444b4690998faed7James Dong#include <cutils/properties.h>
4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber#include "include/ESDS.h"
509aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim#include "include/HevcUtils.h"
5180f78b773f92048944a850efb7b60629643370cdPraveen Chavan#include "include/avc_utils.h"
52dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn
53dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#ifndef __predict_false
54dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#define __predict_false(exp) __builtin_expect((exp) != 0, 0)
55dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#endif
56dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn
5711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih#define WARN_UNLESS(condition, message, ...) \
58dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn( (__predict_false(condition)) ? false : ({ \
5911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih    ALOGW("Condition %s failed "  message, #condition, ##__VA_ARGS__); \
6011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih    true; \
6111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih}))
6211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
6320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6577e8ae9967a078770416619e99ddb5b010def312James Dongstatic const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024;
661f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachadstatic const int64_t kMax32BitFileSize = 0x00ffffffffLL; // 2^32-1 : max FAT32
671f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad                                                         // filesystem file size
681f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad                                                         // used by most SD cards
693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypeSeqParamSet = 0x07;
703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypePicParamSet = 0x08;
7170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongstatic const int64_t kInitialDelayTimeUs     = 700000LL;
72e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuangstatic const int64_t kMaxMetadataSize = 0x4000000LL;   // 64MB max per-frame metadata size
735b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong
747c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Version[]    = "com.android.version";
75da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuangstatic const char kMetaKey_Manufacturer[]      = "com.android.manufacturer";
763b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnarstatic const char kMetaKey_Model[]      = "com.android.model";
77da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang
78da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang#ifdef SHOW_BUILD
797c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Build[]      = "com.android.build";
803b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnar#endif
817c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_CaptureFps[] = "com.android.capture.fps";
824dbff11975e737482537e1636051690188f3fbc4Praveen Chavanstatic const char kMetaKey_TemporalLayerCount[] = "com.android.video.temporal_layers_count";
837c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
8462a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuangstatic const int kTimestampDebugCount = 10;
8562a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang
869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatic const uint8_t kMandatoryHevcNalUnitTypes[3] = {
879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeVps,
889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeSps,
899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypePps,
909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim};
919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatic const uint8_t kHevcNalUnitTypes[5] = {
929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeVps,
939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeSps,
949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypePps,
959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypePrefixSei,
969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeSuffixSei,
979aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim};
98da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang/* uncomment to include build in meta */
997c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang//#define SHOW_MODEL_BUILD 1
1007c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track {
10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
103b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen    Track(MPEG4Writer *owner, const sp<IMediaSource> &source, size_t trackId);
1048f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
10520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ~Track();
10620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t start(MetaData *params);
108fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    status_t stop(bool stopSource = true);
10937187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t pause();
11025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool reachedEOS();
11120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1123b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    int64_t getDurationUs() const;
113d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t getEstimatedTrackSizeBytes() const;
114b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeTrackHeader(bool use32BitOffset = true);
1151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void bufferChunk(int64_t timestampUs);
1161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAvc() const { return mIsAvc; }
1179aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    bool isHevc() const { return mIsHevc; }
1181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAudio() const { return mIsAudio; }
1191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isMPEG4() const { return mIsMPEG4; }
120c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    void addChunkOffset(off64_t offset);
12170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int32_t getTrackId() const { return mTrackId; }
122dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    status_t dump(int fd, const Vector<String16>& args) const;
1238b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    static const char *getFourCCForMime(const char *mime);
12425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    const char *getTrackType() const;
125fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    void resetInternal();
12620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
128000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    enum {
129000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        kMaxCttsOffsetTimeUs = 1000000LL,  // 1 second
1308c460498c028888c533ab442be12b6d4b669b965James Dong        kSampleArraySize = 1000,
131000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    };
132000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
133c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    // A helper class to handle faster write box with table entries
134c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    template<class TYPE, unsigned ENTRY_SIZE>
135c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    // ENTRY_SIZE: # of values in each entry
136c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    struct ListTableEntries {
137c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        static_assert(ENTRY_SIZE > 0, "ENTRY_SIZE must be positive");
138c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        ListTableEntries(uint32_t elementCapacity)
139c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            : mElementCapacity(elementCapacity),
140c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mTotalNumTableEntries(0),
141c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mNumValuesInCurrEntry(0),
142c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCurrTableEntriesElement(NULL) {
143b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross            CHECK_GT(mElementCapacity, 0u);
1442177f21c1ae5bf5cb8c1113a1adbe1fd7db34206Wei Jia            // Ensure no integer overflow on allocation in add().
145c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            CHECK_LT(ENTRY_SIZE, UINT32_MAX / mElementCapacity);
146c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
147c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
148c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Free the allocated memory.
149c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        ~ListTableEntries() {
150c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (!mTableEntryList.empty()) {
151c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                typename List<TYPE *>::iterator it = mTableEntryList.begin();
152c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                delete[] (*it);
153c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.erase(it);
154c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
155c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
156c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
157c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Replace the value at the given position by the given value.
158c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // There must be an existing value at the given position.
159c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order
160c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
161c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void set(const TYPE& value, uint32_t pos) {
162c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            CHECK_LT(pos, mTotalNumTableEntries * ENTRY_SIZE);
163c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
164c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            typename List<TYPE *>::iterator it = mTableEntryList.begin();
165c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            uint32_t iterations = (pos / (mElementCapacity * ENTRY_SIZE));
166c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (it != mTableEntryList.end() && iterations > 0) {
167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++it;
168c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                --iterations;
169c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
170c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK(it != mTableEntryList.end());
171b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross            CHECK_EQ(iterations, 0u);
172c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
173c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            (*it)[(pos % (mElementCapacity * ENTRY_SIZE))] = value;
174c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
176c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Get the value at the given position by the given value.
177c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value the retrieved value at the position in network byte order.
178c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
179c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @return true if a value is found.
180c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        bool get(TYPE& value, uint32_t pos) const {
181c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            if (pos >= mTotalNumTableEntries * ENTRY_SIZE) {
182c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                return false;
183c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
184c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            typename List<TYPE *>::iterator it = mTableEntryList.begin();
186c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            uint32_t iterations = (pos / (mElementCapacity * ENTRY_SIZE));
187c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (it != mTableEntryList.end() && iterations > 0) {
188c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++it;
189c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                --iterations;
190c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
191c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK(it != mTableEntryList.end());
192b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross            CHECK_EQ(iterations, 0u);
193c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
194c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            value = (*it)[(pos % (mElementCapacity * ENTRY_SIZE))];
195c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            return true;
196c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
197c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
198c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        // adjusts all values by |adjust(value)|
199c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        void adjustEntries(
200c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                std::function<void(size_t /* ix */, TYPE(& /* entry */)[ENTRY_SIZE])> update) {
201c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            size_t nEntries = mTotalNumTableEntries + mNumValuesInCurrEntry / ENTRY_SIZE;
202c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            size_t ix = 0;
203c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            for (TYPE *entryArray : mTableEntryList) {
204c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                size_t num = std::min(nEntries, (size_t)mElementCapacity);
205c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                for (size_t i = 0; i < num; ++i) {
206c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                    update(ix++, (TYPE(&)[ENTRY_SIZE])(*entryArray));
207c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                    entryArray += ENTRY_SIZE;
208c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                }
209c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                nEntries -= num;
210c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            }
211c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        }
212c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar
213c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Store a single value.
214c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order.
215c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void add(const TYPE& value) {
216c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_LT(mNumValuesInCurrEntry, mElementCapacity);
217c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries % mElementCapacity;
218c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            uint32_t nValues  = mNumValuesInCurrEntry % ENTRY_SIZE;
219c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (nEntries == 0 && nValues == 0) {
220c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                mCurrTableEntriesElement = new TYPE[ENTRY_SIZE * mElementCapacity];
221c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                CHECK(mCurrTableEntriesElement != NULL);
222c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.push_back(mCurrTableEntriesElement);
223c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
224c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
225c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            uint32_t pos = nEntries * ENTRY_SIZE + nValues;
226c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCurrTableEntriesElement[pos] = value;
227c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
228c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            ++mNumValuesInCurrEntry;
229c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            if ((mNumValuesInCurrEntry % ENTRY_SIZE) == 0) {
230c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++mTotalNumTableEntries;
231c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mNumValuesInCurrEntry = 0;
232c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
233c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
234c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
235c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Write out the table entries:
236c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 1. the number of entries goes first
237c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 2. followed by the values in the table enties in order
238c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg writer the writer to actual write to the storage
239c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void write(MPEG4Writer *writer) const {
240b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross            CHECK_EQ(mNumValuesInCurrEntry % ENTRY_SIZE, 0u);
241c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries;
242c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            writer->writeInt32(nEntries);
243c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            for (typename List<TYPE *>::iterator it = mTableEntryList.begin();
244c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                it != mTableEntryList.end(); ++it) {
245b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross                CHECK_GT(nEntries, 0u);
246c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                if (nEntries >= mElementCapacity) {
247c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                    writer->write(*it, sizeof(TYPE) * ENTRY_SIZE, mElementCapacity);
248c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    nEntries -= mElementCapacity;
249c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                } else {
250c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                    writer->write(*it, sizeof(TYPE) * ENTRY_SIZE, nEntries);
251c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    break;
252c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                }
253c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
254c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
255c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
256c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Return the number of entries in the table.
257c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t count() const { return mTotalNumTableEntries; }
258c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
259c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    private:
260c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mElementCapacity;  // # entries in an element
261c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mTotalNumTableEntries;
262c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        uint32_t         mNumValuesInCurrEntry;  // up to ENTRY_SIZE
263c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        TYPE             *mCurrTableEntriesElement;
264c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mutable List<TYPE *>     mTableEntryList;
265c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
266c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries);
267c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    };
268c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
269c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
270c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
27120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Writer *mOwner;
27220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mMeta;
273b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen    sp<IMediaSource> mSource;
27420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    volatile bool mDone;
275a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mPaused;
276a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mResumed;
277eaae38445a340c4857c1c5569475879a728e63b7James Dong    volatile bool mStarted;
2781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAvc;
2799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    bool mIsHevc;
2801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAudio;
28125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    bool mIsVideo;
2821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsMPEG4;
283fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    bool mGotStartKeyFrame;
2849db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang    bool mIsMalformed;
285bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t mTrackId;
286c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    int64_t mTrackDurationUs;
28743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int64_t mMaxChunkDurationUs;
288826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar    int64_t mLastDecodingTimeUs;
289e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
290d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t mEstimatedTrackSizeBytes;
2911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t mMdatSizeBytes;
2928f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mTimeScale;
29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_t mThread;
29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
296be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
29713aec890216948b0c364f8f92792129d0335f506James Dong    List<MediaBuffer *> mChunkSamples;
2981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
299c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    bool                mSamplesHaveSameSize;
300c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 1> *mStszTableEntries;
301be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
302c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 1> *mStcoTableEntries;
303c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<off64_t, 1> *mCo64TableEntries;
304c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 3> *mStscTableEntries;
305c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 1> *mStssTableEntries;
306c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 2> *mSttsTableEntries;
307c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 2> *mCttsTableEntries;
308965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
309000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMinCttsOffsetTimeUs;
310000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMaxCttsOffsetTimeUs;
311965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
31262a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang    // Save the last 10 frames' timestamp for debug.
31362a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang    std::list<std::pair<int64_t, int64_t>> mTimestampDebugHelper;
31462a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang
3153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Sequence parameter set or picture parameter set
3163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    struct AVCParamSet {
3173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        AVCParamSet(uint16_t length, const uint8_t *data)
3183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            : mLength(length), mData(data) {}
3193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
3203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t mLength;
3213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *mData;
3223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    };
3233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mSeqParamSets;
3243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mPicParamSets;
3253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileIdc;
3263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileCompatible;
3273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mLevelIdc;
3283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
32920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *mCodecSpecificData;
33020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t mCodecSpecificDataSize;
331548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    bool mGotAllCodecSpecificData;
33293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    bool mTrackingProgressStatus;
33320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool mReachedEOS;
3353c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    int64_t mStartTimestampUs;
33670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mStartTimeRealUs;
33770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mFirstSampleTimeRealUs;
33893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mPreviousTrackTimeUs;
33993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mTrackEveryTimeDurationUs;
34025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
341872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Update the audio track's drift information.
342872a481558350634a3fd5cb67939de288af00ecbJames Dong    void updateDriftTime(const sp<MetaData>& meta);
343872a481558350634a3fd5cb67939de288af00ecbJames Dong
34462a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang    void dumpTimeStamps();
34562a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang
3466a5c19cae5b1958af824f349a5c3778255ecd9c7Robert Shih    int64_t getStartTimeOffsetScaledTimeUs() const;
347000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int32_t getStartTimeOffsetScaledTime() const;
348000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
34920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static void *ThreadWrapper(void *me);
35037187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t threadEntry();
35120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *parseParamSet(
3533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen);
3543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
3559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t copyCodecSpecificData(const uint8_t *data, size_t size, size_t minLength = 0);
3569aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
357b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size);
358b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size);
359b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size);
360215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong
3619aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t makeHEVCCodecSpecificData(const uint8_t *data, size_t size);
3629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t copyHEVCCodecSpecificData(const uint8_t *data, size_t size);
3639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t parseHEVCCodecSpecificData(
3649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            const uint8_t *data, size_t size, HevcParameterSets &paramSets);
3659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
366215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    // Track authoring progress status
367faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    void trackProgressStatus(int64_t timeUs, status_t err = OK);
36893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    void initTrackingProgressStatus(MetaData *params);
36903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
37019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    void getCodecSpecificDataFromInputFormatIfPossible();
37119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
372c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Determine the track time scale
373c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If it is an audio track, try to use the sampling rate as
374c059860c73678a202bfa33062723e8f82fb779d9James Dong    // the time scale; however, if user chooses the overwrite
375c059860c73678a202bfa33062723e8f82fb779d9James Dong    // value, the user-supplied time scale will be used.
376c059860c73678a202bfa33062723e8f82fb779d9James Dong    void setTimeScale();
377c059860c73678a202bfa33062723e8f82fb779d9James Dong
378690f546b0ee548dbfe997df36418e5302ec2d786James Dong    // Simple validation on the codec specific data
379690f546b0ee548dbfe997df36418e5302ec2d786James Dong    status_t checkCodecSpecificData() const;
38013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t mRotation;
381690f546b0ee548dbfe997df36418e5302ec2d786James Dong
3821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void updateTrackSizeEstimate();
3831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStscTableEntry(size_t chunkId, size_t sampleId);
3841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStssTableEntry(size_t sampleId);
38579761ab096f57c3027fad9556c2bc436672d614eJames Dong
38679761ab096f57c3027fad9556c2bc436672d614eJames Dong    // Duration is time scale based
38779761ab096f57c3027fad9556c2bc436672d614eJames Dong    void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
388965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
38945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
39045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    bool isTrackMalFormed() const;
39143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    void sendTrackSummary(bool hasMultipleTracks);
3921f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
393b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Write the boxes
394b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStcoBox(bool use32BitOffset);
395b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStscBox();
396b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStszBox();
397b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStssBox();
398b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSttsBox();
399965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void writeCttsBox();
400b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeD263Box();
401b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writePaspBox();
402b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAvccBox();
4039aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    void writeHvccBox();
404b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeUrlBox();
405b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDrefBox();
406b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDinfBox();
407b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDamrBox();
408efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeMdhdBox(uint32_t now);
409b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSmhdBox();
410b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVmhdBox();
41125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    void writeNmhdBox();
412b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeHdlrBox();
413efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeTkhdBox(uint32_t now);
41458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    void writeColrBox();
415b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4aEsdsBox();
416b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4vEsdsBox();
417b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAudioFourCCBox();
418b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVideoFourCCBox();
41925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    void writeMetadataFourCCBox();
420b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStblBox(bool use32BitOffset);
421b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
42220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track(const Track &);
42320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track &operator=(const Track &);
42420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
42520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
426fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu KuangMPEG4Writer::MPEG4Writer(int fd) {
427fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    initInternal(fd);
42830ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
42930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
43020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
4318bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong    reset();
43220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4331f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    while (!mTracks.empty()) {
4341f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        List<Track *>::iterator it = mTracks.begin();
43520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
4361f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        (*it) = NULL;
4371f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mTracks.erase(it);
43820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
43920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
440fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
441fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mNextFd != -1) {
442fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        close(mNextFd);
443fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
444fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
445fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
446fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::initInternal(int fd) {
447fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGV("initInternal");
4488fdb3fde346b446ad3b04dafa65a6844da672e23Hangyu Kuang    mFd = dup(fd);
449fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mNextFd = -1;
450fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mInitCheck = mFd < 0? NO_INIT: OK;
451fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mIsRealTimeRecording = true;
452fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mUse4ByteNalLength = true;
453fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mUse32BitOffset = true;
454fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mIsFileSizeLimitExplicitlyRequested = false;
455fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mPaused = false;
456fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mStarted = false;
457fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mWriterThreadStarted = false;
458fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mSendNotify = false;
459fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mOffset = 0;
460fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mMdatOffset = 0;
461fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mMoovBoxBuffer = NULL;
462fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mMoovBoxBufferOffset = 0;
463fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mWriteMoovBoxToMemory = false;
464fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mFreeBoxOffset = 0;
465fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mStreamableFile = false;
466fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mEstimatedMoovBoxSize = 0;
467fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mMoovExtraSize = 0;
468fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mInterleaveDurationUs = 1000000;
469fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mTimeScale = -1;
470fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mStartTimestampUs = -1ll;
471fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mLatitudex10000 = 0;
472fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mLongitudex10000 = 0;
473fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mAreGeoTagsAvailable = false;
474fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mStartTimeOffsetMs = -1;
475fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mSwitchPending = false;
476fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mMetaKeys = new AMessage();
477fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    addDeviceMeta();
478fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    // Verify mFd is seekable
479fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    off64_t off = lseek64(mFd, 0, SEEK_SET);
480fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (off < 0) {
481fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        ALOGE("cannot seek mFd: %s (%d) %lld", strerror(errno), errno, (long long)mFd);
482fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        release();
483fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
484fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    for (List<Track *>::iterator it = mTracks.begin();
485fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         it != mTracks.end(); ++it) {
486fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        (*it)->resetInternal();
487fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
48820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
48920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
490dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump(
491dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) {
492dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
493dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
494dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
495dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "   MPEG4Writer %p\n", this);
496dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
497dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     mStarted: %s\n", mStarted? "true": "false");
498dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
499dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
500dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    for (List<Track *>::iterator it = mTracks.begin();
501dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong         it != mTracks.end(); ++it) {
502dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        (*it)->dump(fd, args);
503dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    }
504dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
505dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
506dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
507dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump(
50884333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        int fd, const Vector<String16>& /* args */) const {
509dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
510dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
511dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
51225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    snprintf(buffer, SIZE, "     %s track\n", getTrackType());
513dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
514dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "       reached EOS: %s\n",
515dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong            mReachedEOS? "true": "false");
516dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
517c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    snprintf(buffer, SIZE, "       frames encoded : %d\n", mStszTableEntries->count());
51813210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
519377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    snprintf(buffer, SIZE, "       duration encoded : %" PRId64 " us\n", mTrackDurationUs);
52013210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
521dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
522dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
523dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
524dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
5258b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan// static
5268b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavanconst char *MPEG4Writer::Track::getFourCCForMime(const char *mime) {
5278b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (mime == NULL) {
5288b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        return NULL;
5298b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    }
5308b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (!strncasecmp(mime, "audio/", 6)) {
5318b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
5328b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "samr";
5338b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
5348b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "sawb";
5358b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
5368b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "mp4a";
5378b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        }
5388b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    } else if (!strncasecmp(mime, "video/", 6)) {
5398b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
5408b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "mp4v";
5418b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
5428b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "s263";
5438b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
5448b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "avc1";
5459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
5469aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return "hvc1";
5478b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        }
54825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else if (!strncasecmp(mime, "application/", 12)) {
54925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        return "mett";
5508b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    } else {
55125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        ALOGE("Track (%s) other than video/audio/metadata is not supported", mime);
5528b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    }
5538b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    return NULL;
5548b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan}
5558b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan
556b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissenstatus_t MPEG4Writer::addSource(const sp<IMediaSource> &source) {
557bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    Mutex::Autolock l(mLock);
558bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    if (mStarted) {
55929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Attempt to add source AFTER recording is started");
560bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        return UNKNOWN_ERROR;
561bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    }
562acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
563acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    CHECK(source.get() != NULL);
564acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
565acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    const char *mime;
566acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    source->getFormat()->findCString(kKeyMIMEType, &mime);
567acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
56825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (Track::getFourCCForMime(mime) == NULL) {
56925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        ALOGE("Unsupported mime '%s'", mime);
57025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        return ERROR_UNSUPPORTED;
57125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    }
57225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang
57325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    // This is a metadata track or the first track of either audio or video
574acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // Go ahead to add the track.
575219f195159f93d627af2b243732e3f9020511a46James Dong    Track *track = new Track(this, source, 1 + mTracks.size());
57620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
5772dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
5782dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
57920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
58020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
58193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) {
582acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    if (mTracks.empty()) {
583acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        ALOGE("No source added");
584acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return INVALID_OPERATION;
585acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
586acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
587a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
588a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
58993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        status_t err = (*it)->start(params);
590a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
591a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (err != OK) {
592a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            for (List<Track *>::iterator it2 = mTracks.begin();
593a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                 it2 != it; ++it2) {
594a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                (*it2)->stop();
595a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            }
596a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
597a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            return err;
598a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
599a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
600a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
601a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
602a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
6037c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangvoid MPEG4Writer::addDeviceMeta() {
6047c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // add device info and estimate space in 'moov'
6057c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    char val[PROPERTY_VALUE_MAX];
6067c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    size_t n;
6077c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // meta size is estimated by adding up the following:
6087c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // - meta header structures, which occur only once (total 66 bytes)
6097c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // - size for each key, which consists of a fixed header (32 bytes),
6107c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    //   plus key length and data length.
6117c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += 66;
6127c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.build.version.release", val, NULL)
6137c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
6147c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Version, val, n + 1);
6157c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Version) + n + 32;
6167c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
617da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang
618da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang    if (property_get_bool("media.recorder.show_manufacturer_and_model", false)) {
619da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang        if (property_get("ro.product.manufacturer", val, NULL)
620da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang                && (n = strlen(val)) > 0) {
621da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang            mMetaKeys->setString(kMetaKey_Manufacturer, val, n + 1);
622da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang            mMoovExtraSize += sizeof(kMetaKey_Manufacturer) + n + 32;
623da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang        }
624da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang        if (property_get("ro.product.model", val, NULL)
625da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang                && (n = strlen(val)) > 0) {
626da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang            mMetaKeys->setString(kMetaKey_Model, val, n + 1);
627da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang            mMoovExtraSize += sizeof(kMetaKey_Model) + n + 32;
628da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang        }
6297c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
630da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang#ifdef SHOW_MODEL_BUILD
6317c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.build.display.id", val, NULL)
6327c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
6337c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Build, val, n + 1);
6347c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Build) + n + 32;
6357c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
6367c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#endif
6377c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang}
6387c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
6392dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
6402dec2b5be2056c6d9428897dc672185872d30d17James Dong    // This implementation is highly experimental/heurisitic.
6412dec2b5be2056c6d9428897dc672185872d30d17James Dong    //
6422dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Statistical analysis shows that metadata usually accounts
6432dec2b5be2056c6d9428897dc672185872d30d17James Dong    // for a small portion of the total file size, usually < 0.6%.
6442dec2b5be2056c6d9428897dc672185872d30d17James Dong
64578a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2,
6462dec2b5be2056c6d9428897dc672185872d30d17James Dong    // where 1MB is the common file size limit for MMS application.
64778a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MAX _MOOV_BOX_SIZE value is based on about 3
6482dec2b5be2056c6d9428897dc672185872d30d17James Dong    // minute video recording with a bit rate about 3 Mbps, because
6492dec2b5be2056c6d9428897dc672185872d30d17James Dong    // statistics also show that most of the video captured are going
6502dec2b5be2056c6d9428897dc672185872d30d17James Dong    // to be less than 3 minutes.
6512dec2b5be2056c6d9428897dc672185872d30d17James Dong
6522dec2b5be2056c6d9428897dc672185872d30d17James Dong    // If the estimation is wrong, we will pay the price of wasting
6532dec2b5be2056c6d9428897dc672185872d30d17James Dong    // some reserved space. This should not happen so often statistically.
6542dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int32_t factor = mUse32BitOffset? 1: 2;
65578a1a286f736888ae7af8860b2c424af0d978848James Dong    static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024;  // 3 KB
6562dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
6572dec2b5be2056c6d9428897dc672185872d30d17James Dong    int64_t size = MIN_MOOV_BOX_SIZE;
6582dec2b5be2056c6d9428897dc672185872d30d17James Dong
65978a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file size limit is set
660a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
66178a1a286f736888ae7af8860b2c424af0d978848James Dong        size = mMaxFileSizeLimitBytes * 6 / 1000;
66278a1a286f736888ae7af8860b2c424af0d978848James Dong    }
66378a1a286f736888ae7af8860b2c424af0d978848James Dong
66478a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file duration limit is set
66578a1a286f736888ae7af8860b2c424af0d978848James Dong    if (mMaxFileDurationLimitUs != 0) {
66678a1a286f736888ae7af8860b2c424af0d978848James Dong        if (bitRate > 0) {
66778a1a286f736888ae7af8860b2c424af0d978848James Dong            int64_t size2 =
6680ca31521644b9396829850f7400d23f9b107cc64Johan Redestig                ((mMaxFileDurationLimitUs / 1000) * bitRate * 6) / 8000000;
66978a1a286f736888ae7af8860b2c424af0d978848James Dong            if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
67078a1a286f736888ae7af8860b2c424af0d978848James Dong                // When both file size and duration limits are set,
67178a1a286f736888ae7af8860b2c424af0d978848James Dong                // we use the smaller limit of the two.
67278a1a286f736888ae7af8860b2c424af0d978848James Dong                if (size > size2) {
67378a1a286f736888ae7af8860b2c424af0d978848James Dong                    size = size2;
67478a1a286f736888ae7af8860b2c424af0d978848James Dong                }
67578a1a286f736888ae7af8860b2c424af0d978848James Dong            } else {
67678a1a286f736888ae7af8860b2c424af0d978848James Dong                // Only max file duration limit is set
67778a1a286f736888ae7af8860b2c424af0d978848James Dong                size = size2;
67878a1a286f736888ae7af8860b2c424af0d978848James Dong            }
6792dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
6802dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
68178a1a286f736888ae7af8860b2c424af0d978848James Dong
6822dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size < MIN_MOOV_BOX_SIZE) {
6832dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MIN_MOOV_BOX_SIZE;
6842dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
6852dec2b5be2056c6d9428897dc672185872d30d17James Dong
6862dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Any long duration recording will be probably end up with
6872dec2b5be2056c6d9428897dc672185872d30d17James Dong    // non-streamable mp4 file.
6882dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size > MAX_MOOV_BOX_SIZE) {
6892dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MAX_MOOV_BOX_SIZE;
6902dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
6912dec2b5be2056c6d9428897dc672185872d30d17James Dong
6927c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // Account for the extra stuff (Geo, meta keys, etc.)
6937c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    size += mMoovExtraSize;
6947c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
695a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGI("limits: %" PRId64 "/%" PRId64 " bytes/us, bit rate: %d bps and the"
696a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn         " estimated moov size %" PRId64 " bytes",
6972dec2b5be2056c6d9428897dc672185872d30d17James Dong         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
6982dec2b5be2056c6d9428897dc672185872d30d17James Dong    return factor * size;
6992dec2b5be2056c6d9428897dc672185872d30d17James Dong}
7002dec2b5be2056c6d9428897dc672185872d30d17James Dong
7012dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) {
702674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
70325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
70420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
705fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mStartMeta = param;
70620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
707a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    /*
708a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * Check mMaxFileSizeLimitBytes at the beginning
709a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * since mMaxFileSizeLimitBytes may be implicitly
710a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * changed later for 32-bit file offset even if
711a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * user does not ask to set it explicitly.
712a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     */
713a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0) {
714a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong        mIsFileSizeLimitExplicitlyRequested = true;
715a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    }
716a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong
7172dec2b5be2056c6d9428897dc672185872d30d17James Dong    int32_t use64BitOffset;
7182dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (param &&
7192dec2b5be2056c6d9428897dc672185872d30d17James Dong        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
7202dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64BitOffset) {
7212dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
7222dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
7232dec2b5be2056c6d9428897dc672185872d30d17James Dong
7241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    if (mUse32BitOffset) {
7251f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // Implicit 32 bit file size limit
7261f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes == 0) {
7271f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
7281f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
7291f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
7301f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // If file size is set to be larger than the 32 bit file
7311f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // size limit, treat it as an error.
7321f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
733a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGW("32-bit file size limit (%" PRId64 " bytes) too big. "
734a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                 "It is changed to %" PRId64 " bytes",
735d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                mMaxFileSizeLimitBytes, kMax32BitFileSize);
736d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
7371f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
7381f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    }
7391f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
740b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    int32_t use2ByteNalLength;
741b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (param &&
742b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) &&
743b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        use2ByteNalLength) {
744b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mUse4ByteNalLength = false;
7452dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
7462dec2b5be2056c6d9428897dc672185872d30d17James Dong
747de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    int32_t isRealTimeRecording;
748de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (param && param->findInt32(kKeyRealTimeRecording, &isRealTimeRecording)) {
749de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        mIsRealTimeRecording = isRealTimeRecording;
750de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    }
751de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
752065d1aff96818df54456053f1574aec8a234d0deJames Dong    mStartTimestampUs = -1;
75393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
754a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mStarted) {
755a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused) {
756a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mPaused = false;
75793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return startTracks(param);
758a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
759a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
760a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
761a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
7628f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (!param ||
7638f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
7648f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mTimeScale = 1000;
7658f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
76643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
7673856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("movie time scale: %d", mTimeScale);
7688f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
76977e8ae9967a078770416619e99ddb5b010def312James Dong    /*
77077e8ae9967a078770416619e99ddb5b010def312James Dong     * When the requested file size limit is small, the priority
77177e8ae9967a078770416619e99ddb5b010def312James Dong     * is to meet the file size limit requirement, rather than
7727b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to make the file streamable. mStreamableFile does not tell
7737b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * whether the actual recorded file is streamable or not.
77477e8ae9967a078770416619e99ddb5b010def312James Dong     */
77577e8ae9967a078770416619e99ddb5b010def312James Dong    mStreamableFile =
77677e8ae9967a078770416619e99ddb5b010def312James Dong        (mMaxFileSizeLimitBytes != 0 &&
77777e8ae9967a078770416619e99ddb5b010def312James Dong         mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes);
77877e8ae9967a078770416619e99ddb5b010def312James Dong
7797b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    /*
7807b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mWriteMoovBoxToMemory is true if the amount of data in moov box is
7817b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * smaller than the reserved free space at the beginning of a file, AND
7827b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * when the content of moov box is constructed. Note that video/audio
7837b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * frame data is always written to the file but not in the memory.
7847b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7857b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * Before stop()/reset() is called, mWriteMoovBoxToMemory is always
7867b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * false. When reset() is called at the end of a recording session,
7877b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * Moov box needs to be constructed.
7887b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7897b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 1) Right before a moov box is constructed, mWriteMoovBoxToMemory
7907b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to set to mStreamableFile so that if
7917b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * the file is intended to be streamable, it is set to true;
7927b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * otherwise, it is set to false. When the value is set to false,
7937b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * all the content of the moov box is written immediately to
7947b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * the end of the file. When the value is set to true, all the
7957b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * content of the moov box is written to an in-memory cache,
7967b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mMoovBoxBuffer, util the following condition happens. Note
7977b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * that the size of the in-memory cache is the same as the
7987b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * reserved free space at the beginning of the file.
7997b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
8007b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 2) While the data of the moov box is written to an in-memory
8017b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * cache, the data size is checked against the reserved space.
8027b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * If the data size surpasses the reserved space, subsequent moov
8037b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * data could no longer be hold in the in-memory cache. This also
8047b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * indicates that the reserved space was too small. At this point,
8057b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * _all_ moov data must be written to the end of the file.
8067b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mWriteMoovBoxToMemory must be set to false to direct the write
8077b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to the file.
8087b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
8097b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 3) If the data size in moov box is smaller than the reserved
8107b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * space after moov box is completely constructed, the in-memory
8117b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * cache copy of the moov box is written to the reserved free
8127b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * space. Thus, immediately after the moov is completedly
8137b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * constructed, mWriteMoovBoxToMemory is always set to false.
8147b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     */
8157b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    mWriteMoovBoxToMemory = false;
8167837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = NULL;
8177837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
8187837c17063a4c50bc856ba59418516fdab731de7James Dong
819b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeFtypBox(param);
82020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8217837c17063a4c50bc856ba59418516fdab731de7James Dong    mFreeBoxOffset = mOffset;
82220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8237837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mEstimatedMoovBoxSize == 0) {
8242dec2b5be2056c6d9428897dc672185872d30d17James Dong        int32_t bitRate = -1;
8252dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (param) {
8262dec2b5be2056c6d9428897dc672185872d30d17James Dong            param->findInt32(kKeyBitRate, &bitRate);
8272dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
8282dec2b5be2056c6d9428897dc672185872d30d17James Dong        mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
8297837c17063a4c50bc856ba59418516fdab731de7James Dong    }
83043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(mEstimatedMoovBoxSize, 8);
83177e8ae9967a078770416619e99ddb5b010def312James Dong    if (mStreamableFile) {
83277e8ae9967a078770416619e99ddb5b010def312James Dong        // Reserve a 'free' box only for streamable file
83377e8ae9967a078770416619e99ddb5b010def312James Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
83477e8ae9967a078770416619e99ddb5b010def312James Dong        writeInt32(mEstimatedMoovBoxSize);
83577e8ae9967a078770416619e99ddb5b010def312James Dong        write("free", 4);
83677e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
83777e8ae9967a078770416619e99ddb5b010def312James Dong    } else {
83877e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mOffset;
83977e8ae9967a078770416619e99ddb5b010def312James Dong    }
8407837c17063a4c50bc856ba59418516fdab731de7James Dong
8417837c17063a4c50bc856ba59418516fdab731de7James Dong    mOffset = mMdatOffset;
842c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mMdatOffset, SEEK_SET);
8431acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
8441acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("????mdat", 8);
8451acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
8461acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("\x00\x00\x00\x01mdat????????", 16);
8471acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
8481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    status_t err = startWriterThread();
8501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (err != OK) {
8511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return err;
8521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    err = startTracks(param);
855a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (err != OK) {
856a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return err;
85720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
8581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
859a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = true;
86025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
86120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
86220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8631f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const {
8641f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    return mUse32BitOffset;
8651f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
8661f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
86737187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() {
868674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
86937187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
870a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
871a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
87237187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
873a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
874a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
87537187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->pause();
87637187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (status != OK) {
87737187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
87837187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
879a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
88037187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
881a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
882a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
8831c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() {
884b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Stopping writer thread");
885411ba422e3635d534928ffd81abf54f4f291c739James Dong    if (!mWriterThreadStarted) {
886411ba422e3635d534928ffd81abf54f4f291c739James Dong        return;
887411ba422e3635d534928ffd81abf54f4f291c739James Dong    }
8881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
8901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
8911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mDone = true;
8931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkReadyCondition.signal();
8941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void *dummy;
8971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_join(mThread, &dummy);
898411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = false;
899b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Writer thread stopped");
9001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
9011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
90213f6284305e4b27395a23db7882d670bdb1bcae1James Dong/*
90313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix:
90413f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a  b  u |
90513f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c  d  v |
90613f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x  y  w |
90713f6284305e4b27395a23db7882d670bdb1bcae1James Dong *
90813f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following
90913f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w},
91013f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while
91113f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format.
91213f6284305e4b27395a23db7882d670bdb1bcae1James Dong */
91313f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) {
9143856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeCompositionMatrix");
91513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t a = 0x00010000;
91613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t b = 0;
91713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t c = 0;
91813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t d = 0x00010000;
91913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    switch (degrees) {
92013f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 0:
92113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
92213f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 90:
92313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
92413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0x00010000;
92513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0xFFFF0000;
92613f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
92713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
92813f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 180:
92913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0xFFFF0000;
93013f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0xFFFF0000;
93113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
93213f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 270:
93313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
93413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0xFFFF0000;
93513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0x00010000;
93613f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
93713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
93813f6284305e4b27395a23db7882d670bdb1bcae1James Dong        default:
93913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            CHECK(!"Should never reach this unknown rotation");
94013f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
94113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
94213f6284305e4b27395a23db7882d670bdb1bcae1James Dong
94313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(a);           // a
94413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(b);           // b
94513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // u
94613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(c);           // c
94713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(d);           // d
94813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // v
94913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // x
95013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // y
95113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0x40000000);  // w
95213f6284305e4b27395a23db7882d670bdb1bcae1James Dong}
95313f6284305e4b27395a23db7882d670bdb1bcae1James Dong
954411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() {
955411ba422e3635d534928ffd81abf54f4f291c739James Dong    close(mFd);
956411ba422e3635d534928ffd81abf54f4f291c739James Dong    mFd = -1;
957411ba422e3635d534928ffd81abf54f4f291c739James Dong    mInitCheck = NO_INIT;
958411ba422e3635d534928ffd81abf54f4f291c739James Dong    mStarted = false;
9594c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary    free(mMoovBoxBuffer);
9604c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary    mMoovBoxBuffer = NULL;
961411ba422e3635d534928ffd81abf54f4f291c739James Dong}
96213f6284305e4b27395a23db7882d670bdb1bcae1James Dong
963fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::finishCurrentSession() {
964fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    reset(false /* stopSource */);
965fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
966fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
967fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::switchFd() {
968fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGV("switchFd");
969fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    Mutex::Autolock l(mLock);
970fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mSwitchPending) {
971fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return OK;
972fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
973fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
974fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mNextFd == -1) {
975fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        ALOGW("No FileDescripter for next recording");
976fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return INVALID_OPERATION;
977fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
978fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
979fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mSwitchPending = true;
980fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    sp<AMessage> msg = new AMessage(kWhatSwitch, mReflector);
981fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    status_t err = msg->post();
982fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
983fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    return err;
984fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
985fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
986fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::reset(bool stopSource) {
987674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
98837187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
989411ba422e3635d534928ffd81abf54f4f291c739James Dong    } else {
990411ba422e3635d534928ffd81abf54f4f291c739James Dong        if (!mWriterThreadStarted ||
991411ba422e3635d534928ffd81abf54f4f291c739James Dong            !mStarted) {
992411ba422e3635d534928ffd81abf54f4f291c739James Dong            if (mWriterThreadStarted) {
993411ba422e3635d534928ffd81abf54f4f291c739James Dong                stopWriterThread();
994411ba422e3635d534928ffd81abf54f4f291c739James Dong            }
995411ba422e3635d534928ffd81abf54f4f291c739James Dong            release();
996411ba422e3635d534928ffd81abf54f4f291c739James Dong            return OK;
997411ba422e3635d534928ffd81abf54f4f291c739James Dong        }
99820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
99920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
100037187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
10018f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t maxDurationUs = 0;
100265b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    int64_t minDurationUs = 0x7fffffffffffffffLL;
100320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
100420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
1005fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        status_t status = (*it)->stop(stopSource);
100637187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK) {
100737187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
100837187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
100920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10108f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int64_t durationUs = (*it)->getDurationUs();
10118f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (durationUs > maxDurationUs) {
10128f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            maxDurationUs = durationUs;
101320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
101465b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        if (durationUs < minDurationUs) {
101565b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs = durationUs;
101665b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        }
101765b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    }
101865b3d76025c71d755b0fb3b6ead90255f25417edJames Dong
101965b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    if (mTracks.size() > 1) {
1020a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGD("Duration from tracks range is [%" PRId64 ", %" PRId64 "] us",
102165b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs, maxDurationUs);
102220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
102320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    stopWriterThread();
10257837c17063a4c50bc856ba59418516fdab731de7James Dong
102637187916a486504acaf83bea30147eb5fbf46ae5James Dong    // Do not write out movie header on error.
102737187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err != OK) {
1028411ba422e3635d534928ffd81abf54f4f291c739James Dong        release();
102937187916a486504acaf83bea30147eb5fbf46ae5James Dong        return err;
103037187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
103137187916a486504acaf83bea30147eb5fbf46ae5James Dong
103220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
10331acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
1034c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset, SEEK_SET);
10351f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad        uint32_t size = htonl(static_cast<uint32_t>(mOffset - mMdatOffset));
1036c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 4);
10371acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
1038c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset + 8, SEEK_SET);
10391f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad        uint64_t size = mOffset - mMdatOffset;
10401acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        size = hton64(size);
1041c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 8);
10421acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
1043c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mOffset, SEEK_SET);
104420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10457b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // Construct moov box now
10467837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
10477b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    mWriteMoovBoxToMemory = mStreamableFile;
10487b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mWriteMoovBoxToMemory) {
10497b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // There is no need to allocate in-memory cache
10507b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // for moov box if the file is not streamable.
10517b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
10527b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
10537b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        CHECK(mMoovBoxBuffer != NULL);
10547b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    }
1055b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMoovBox(maxDurationUs);
105620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10577b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // mWriteMoovBoxToMemory could be set to false in
10587b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // MPEG4Writer::write() method
10597b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mWriteMoovBoxToMemory) {
10607b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        mWriteMoovBoxToMemory = false;
10617b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // Content of the moov box is saved in the cache, and the in-memory
10627b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // moov box needs to be written to the file in a single shot.
10637b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
106443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize);
10657837c17063a4c50bc856ba59418516fdab731de7James Dong
10667837c17063a4c50bc856ba59418516fdab731de7James Dong        // Moov box
1067c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
10687837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset = mFreeBoxOffset;
1069674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset);
10707837c17063a4c50bc856ba59418516fdab731de7James Dong
10717837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free box
1072c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
10737837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
10747837c17063a4c50bc856ba59418516fdab731de7James Dong        write("free", 4);
10757b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    } else {
10767b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        ALOGI("The mp4 file will not be streamable.");
10777b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    }
10787837c17063a4c50bc856ba59418516fdab731de7James Dong
10797b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // Free in-memory cache for moov box
10807b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mMoovBoxBuffer != NULL) {
10817837c17063a4c50bc856ba59418516fdab731de7James Dong        free(mMoovBoxBuffer);
10827837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBuffer = NULL;
10837837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBufferOffset = 0;
10847837c17063a4c50bc856ba59418516fdab731de7James Dong    }
10857837c17063a4c50bc856ba59418516fdab731de7James Dong
10860c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
108720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1088411ba422e3635d534928ffd81abf54f4f291c739James Dong    release();
108937187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
109020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
109120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1092efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonuint32_t MPEG4Writer::getMpeg4Time() {
1093b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    time_t now = time(NULL);
1094efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // MP4 file uses time counting seconds since midnight, Jan. 1, 1904
1095efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // while time function returns Unix epoch values which starts
1096efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // at 1970-01-01. Lets add the number of seconds between them
10972b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    static const uint32_t delta = (66 * 365 + 17) * (24 * 60 * 60);
10982b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    if (now < 0 || uint32_t(now) > UINT32_MAX - delta) {
10992b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen        return 0;
11002b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    }
11012b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    uint32_t mpeg4Time = uint32_t(now) + delta;
1102efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    return mpeg4Time;
1103efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson}
1104efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson
1105efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) {
1106efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
1107b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("mvhd");
1108b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // version=0, flags=0
1109b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // creation time
1110b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // modification time
1111b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTimeScale);    // mvhd timescale
1112b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6;
1113b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(duration);
1114b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0x10000);       // rate: 1.0
1115b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0x100);         // volume
1116b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0);             // reserved
1117b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
1118b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
1119b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeCompositionMatrix(0); // matrix
1120b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1121b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1122b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1123b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1124b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1125b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1126b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTracks.size() + 1);  // nextTrackID
1127b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // mvhd
1128b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1129b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1130b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) {
1131b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("moov");
1132b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMvhdBox(durationUs);
113307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (mAreGeoTagsAvailable) {
113407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        writeUdtaBox();
113507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
1136e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeMetaBox();
1137b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t id = 1;
1138b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    for (List<Track *>::iterator it = mTracks.begin();
1139b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        it != mTracks.end(); ++it, ++id) {
1140b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (*it)->writeTrackHeader(mUse32BitOffset);
1141b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
1142b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // moov
1143b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1144b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
11452cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) {
1146b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("ftyp");
1147b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1148b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t fileType;
1149b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (param && param->findInt32(kKeyFileType, &fileType) &&
1150b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fileType != OUTPUT_FORMAT_MPEG_4) {
1151b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("3gp4");
11528284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeInt32(0);
11538284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("isom");
11548284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("3gp4");
1155b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
11568284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("mp42");
11578284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeInt32(0);
1158b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("isom");
11598284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("mp42");
1160b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
1161b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1162b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();
1163b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1164b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
116507ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() {
116607ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5)
116707ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5"
116807ec01904613a0bac32caaa8444b4690998faed7James Dong#endif
116907ec01904613a0bac32caaa8444b4690998faed7James Dong
117007ec01904613a0bac32caaa8444b4690998faed7James Dong    // Test mode is enabled only if rw.media.record.test system
117107ec01904613a0bac32caaa8444b4690998faed7James Dong    // property is enabled.
117296626b7f9a4e5c9e1e04f7f710383631d1470364Marco Nelissen    if (property_get_bool("rw.media.record.test", false)) {
117307ec01904613a0bac32caaa8444b4690998faed7James Dong        return true;
117407ec01904613a0bac32caaa8444b4690998faed7James Dong    }
117507ec01904613a0bac32caaa8444b4690998faed7James Dong    return false;
117607ec01904613a0bac32caaa8444b4690998faed7James Dong}
117707ec01904613a0bac32caaa8444b4690998faed7James Dong
117870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() {
117907ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send session summary only if test mode is enabled
118007ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
118107ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
118207ec01904613a0bac32caaa8444b4690998faed7James Dong    }
118307ec01904613a0bac32caaa8444b4690998faed7James Dong
118470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
118570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong         it != mChunkInfos.end(); ++it) {
118670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int trackNum = it->mTrack->getTrackId() << 28;
118770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
118870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS,
118970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs);
119070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    }
119170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong}
119270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
119313aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
119413aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
119513aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
119613aec890216948b0c364f8f92792129d0335f506James Dong}
119713aec890216948b0c364f8f92792129d0335f506James Dong
119813aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() {
119913aec890216948b0c364f8f92792129d0335f506James Dong    mLock.lock();
120013aec890216948b0c364f8f92792129d0335f506James Dong}
120113aec890216948b0c364f8f92792129d0335f506James Dong
120213aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() {
120313aec890216948b0c364f8f92792129d0335f506James Dong    mLock.unlock();
120413aec890216948b0c364f8f92792129d0335f506James Dong}
120520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1206c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
1207c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
120820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1209c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    ::write(mFd,
1210c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          (const uint8_t *)buffer->data() + buffer->range_offset(),
1211c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          buffer->range_length());
121220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
121320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
121420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
121520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
121620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
121720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
121803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
121903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
122003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
122103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
122203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
122303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
122403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
122503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
122603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
122703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
122803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
122903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
123003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
123103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
123280f78b773f92048944a850efb7b60629643370cdPraveen Chavanoff64_t MPEG4Writer::addMultipleLengthPrefixedSamples_l(MediaBuffer *buffer) {
123380f78b773f92048944a850efb7b60629643370cdPraveen Chavan    off64_t old_offset = mOffset;
123480f78b773f92048944a850efb7b60629643370cdPraveen Chavan
123580f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const size_t kExtensionNALSearchRange = 64; // bytes to look for non-VCL NALUs
123680f78b773f92048944a850efb7b60629643370cdPraveen Chavan
123780f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *dataStart = (const uint8_t *)buffer->data() + buffer->range_offset();
123880f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *currentNalStart = dataStart;
123980f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *nextNalStart;
124080f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *data = dataStart;
124180f78b773f92048944a850efb7b60629643370cdPraveen Chavan    size_t nextNalSize;
124280f78b773f92048944a850efb7b60629643370cdPraveen Chavan    size_t searchSize = buffer->range_length() > kExtensionNALSearchRange ?
124380f78b773f92048944a850efb7b60629643370cdPraveen Chavan                   kExtensionNALSearchRange : buffer->range_length();
124480f78b773f92048944a850efb7b60629643370cdPraveen Chavan
124580f78b773f92048944a850efb7b60629643370cdPraveen Chavan    while (getNextNALUnit(&data, &searchSize, &nextNalStart,
124680f78b773f92048944a850efb7b60629643370cdPraveen Chavan            &nextNalSize, true) == OK) {
124710cc12c4eec9ff974edb72f9140b05762fa50907Lajos Molnar        size_t currentNalSize = nextNalStart - currentNalStart - 4 /* strip start-code */;
124880f78b773f92048944a850efb7b60629643370cdPraveen Chavan        MediaBuffer *nalBuf = new MediaBuffer((void *)currentNalStart, currentNalSize);
124980f78b773f92048944a850efb7b60629643370cdPraveen Chavan        addLengthPrefixedSample_l(nalBuf);
125080f78b773f92048944a850efb7b60629643370cdPraveen Chavan        nalBuf->release();
125180f78b773f92048944a850efb7b60629643370cdPraveen Chavan
125280f78b773f92048944a850efb7b60629643370cdPraveen Chavan        currentNalStart = nextNalStart;
125380f78b773f92048944a850efb7b60629643370cdPraveen Chavan    }
125480f78b773f92048944a850efb7b60629643370cdPraveen Chavan
125580f78b773f92048944a850efb7b60629643370cdPraveen Chavan    size_t currentNalOffset = currentNalStart - dataStart;
125680f78b773f92048944a850efb7b60629643370cdPraveen Chavan    buffer->set_range(buffer->range_offset() + currentNalOffset,
125780f78b773f92048944a850efb7b60629643370cdPraveen Chavan            buffer->range_length() - currentNalOffset);
125880f78b773f92048944a850efb7b60629643370cdPraveen Chavan    addLengthPrefixedSample_l(buffer);
125980f78b773f92048944a850efb7b60629643370cdPraveen Chavan
126080f78b773f92048944a850efb7b60629643370cdPraveen Chavan    return old_offset;
126180f78b773f92048944a850efb7b60629643370cdPraveen Chavan}
126280f78b773f92048944a850efb7b60629643370cdPraveen Chavan
1263c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
1264c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
126530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
126630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
126703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1268b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mUse4ByteNalLength) {
1269b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 24;
1270c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1271b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 16) & 0xff;
1272c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1273b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 8) & 0xff;
1274c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1275b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
1276c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1277c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong
1278c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd,
1279c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              (const uint8_t *)buffer->data() + buffer->range_offset(),
1280c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              length);
1281b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
1282b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 4;
1283b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
1284b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross        CHECK_LT(length, 65536u);
128530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1286b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 8;
1287c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1288b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
1289c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1290c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length);
1291b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 2;
1292b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
129330ab66297501757d745b9ae10da61adcd891f497Andreas Huber
129430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
129530ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
129630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
12977837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write(
1298674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        const void *ptr, size_t size, size_t nmemb) {
12997837c17063a4c50bc856ba59418516fdab731de7James Dong
13007837c17063a4c50bc856ba59418516fdab731de7James Dong    const size_t bytes = size * nmemb;
13017837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
13027b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
1303c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
13041acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        if (moovBoxSize > mEstimatedMoovBoxSize) {
13057b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // The reserved moov box at the beginning of the file
13067b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // is not big enough. Moov box should be written to
13077b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // the end of the file from now on, but not to the
13087b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // in-memory cache.
13097b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
13107b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // We write partial moov box that is in the memory to
13117b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // the file first.
1312c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            for (List<off64_t>::iterator it = mBoxes.begin();
13137837c17063a4c50bc856ba59418516fdab731de7James Dong                 it != mBoxes.end(); ++it) {
13147837c17063a4c50bc856ba59418516fdab731de7James Dong                (*it) += mOffset;
13157837c17063a4c50bc856ba59418516fdab731de7James Dong            }
1316674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            lseek64(mFd, mOffset, SEEK_SET);
1317674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset);
13187b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            ::write(mFd, ptr, bytes);
13197837c17063a4c50bc856ba59418516fdab731de7James Dong            mOffset += (bytes + mMoovBoxBufferOffset);
13207b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
13217b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // All subsequent moov box content will be written
13227b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // to the end of the file.
13237837c17063a4c50bc856ba59418516fdab731de7James Dong            mWriteMoovBoxToMemory = false;
13247837c17063a4c50bc856ba59418516fdab731de7James Dong        } else {
13257837c17063a4c50bc856ba59418516fdab731de7James Dong            memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
13267837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset += bytes;
13277837c17063a4c50bc856ba59418516fdab731de7James Dong        }
13287837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1329674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        ::write(mFd, ptr, size * nmemb);
13307837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset += bytes;
13317837c17063a4c50bc856ba59418516fdab731de7James Dong    }
13327837c17063a4c50bc856ba59418516fdab731de7James Dong    return bytes;
13337837c17063a4c50bc856ba59418516fdab731de7James Dong}
13347837c17063a4c50bc856ba59418516fdab731de7James Dong
1335e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::beginBox(uint32_t id) {
1336e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    mBoxes.push_back(mWriteMoovBoxToMemory?
1337e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            mMoovBoxBufferOffset: mOffset);
1338e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
1339e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0);
1340e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(id);
1341e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
1342e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
134320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
1344b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_EQ(strlen(fourcc), 4u);
134520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13467837c17063a4c50bc856ba59418516fdab731de7James Dong    mBoxes.push_back(mWriteMoovBoxToMemory?
13477837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset: mOffset);
134820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
134920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
135020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
135120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
135220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
135320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
13540c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
135520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1356c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = *--mBoxes.end();
135720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
135820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13597837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
13607837c17063a4c50bc856ba59418516fdab731de7James Dong       int32_t x = htonl(mMoovBoxBufferOffset - offset);
13617837c17063a4c50bc856ba59418516fdab731de7James Dong       memcpy(mMoovBoxBuffer + offset, &x, 4);
13627837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1363c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, offset, SEEK_SET);
13647837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mOffset - offset);
13657837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset -= 4;
1366c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
13677837c17063a4c50bc856ba59418516fdab731de7James Dong    }
136820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
136920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
137020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
1371674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 1);
137220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
137320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
137420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
137520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
1376674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 2);
137720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
137820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
137920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
138020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
1381674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 4);
138220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
138320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
138420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
138520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
1386674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 8);
138720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
138820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
138920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
139020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
1391674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, n + 1);
139220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
139320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
139420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
1395b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_EQ(strlen(s), 4u);
1396674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, 4);
139720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
139820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
139907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
140007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format
140107b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) {
140207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
140307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
140407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
140507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
140607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[9];
140707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
140807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
140907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%c%.2d.", sign, wholePart);
141007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
141107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%+.2d.", wholePart);
141207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
141307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
141407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
141507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
141607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
141707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
141807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
141907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[4], 5, "%.4d", fractionalPart);
142007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
142107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
142207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 8);
142307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
142407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
142507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format
142607b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) {
142707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
142807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
142907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
143007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
143107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[10];
143207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
143307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
143407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%c%.3d.", sign, wholePart);
143507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
143607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%+.3d.", wholePart);
143707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
143807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
143907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
144007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
144107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
144207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
144307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
144407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[5], 5, "%.4d", fractionalPart);
144507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
144607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
144707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 9);
144807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
144907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
145007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
145107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
145207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and
145307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000.
145407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and
145507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180]
145607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
145707b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) {
145807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Is latitude or longitude out of range?
145907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (latitudex10000 < -900000 || latitudex10000 > 900000 ||
146007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        longitudex10000 < -1800000 || longitudex10000 > 1800000) {
146107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        return BAD_VALUE;
146207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
146307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
146407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLatitudex10000 = latitudex10000;
146507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLongitudex10000 = longitudex10000;
146607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mAreGeoTagsAvailable = true;
14677c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += 30;
146807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    return OK;
146907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
147007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
1471e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangstatus_t MPEG4Writer::setCaptureRate(float captureFps) {
1472e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    if (captureFps <= 0.0f) {
1473e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        return BAD_VALUE;
1474e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
1475e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
14767c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMetaKeys->setFloat(kMetaKey_CaptureFps, captureFps);
14777c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += sizeof(kMetaKey_CaptureFps) + 4 + 32;
14787c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
1479e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    return OK;
1480e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
1481e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
14824dbff11975e737482537e1636051690188f3fbc4Praveen Chavanstatus_t MPEG4Writer::setTemporalLayerCount(uint32_t layerCount) {
14834dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    if (layerCount > 9) {
14844dbff11975e737482537e1636051690188f3fbc4Praveen Chavan        return BAD_VALUE;
14854dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    }
14864dbff11975e737482537e1636051690188f3fbc4Praveen Chavan
14874dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    if (layerCount > 0) {
14884dbff11975e737482537e1636051690188f3fbc4Praveen Chavan        mMetaKeys->setInt32(kMetaKey_TemporalLayerCount, layerCount);
14894dbff11975e737482537e1636051690188f3fbc4Praveen Chavan        mMoovExtraSize += sizeof(kMetaKey_TemporalLayerCount) + 4 + 32;
14904dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    }
14914dbff11975e737482537e1636051690188f3fbc4Praveen Chavan
14924dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    return OK;
14934dbff11975e737482537e1636051690188f3fbc4Praveen Chavan}
14944dbff11975e737482537e1636051690188f3fbc4Praveen Chavan
1495fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::notifyApproachingLimit() {
1496fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    Mutex::Autolock autolock(mLock);
1497fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    // Only notify once.
1498fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mSendNotify) {
1499fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return;
1500fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1501fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGW("Recorded file size is approaching limit %" PRId64 "bytes",
1502fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mMaxFileSizeLimitBytes);
1503fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING, 0);
1504fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mSendNotify = true;
1505fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
1506fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
150720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
1508674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(data, 1, size);
150920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
151020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
151178a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const {
151278a1a286f736888ae7af8860b2c424af0d978848James Dong    return mStreamableFile;
151378a1a286f736888ae7af8860b2c424af0d978848James Dong}
151478a1a286f736888ae7af8860b2c424af0d978848James Dong
1515d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() {
1516d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1517d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeLimitBytes == 0) {
1518d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1519d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1520956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
1521d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1522d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1523d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
1524d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
15251f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
152677e8ae9967a078770416619e99ddb5b010def312James Dong    if (!mStreamableFile) {
152777e8ae9967a078770416619e99ddb5b010def312James Dong        // Add 1024 bytes as error tolerance
152877e8ae9967a078770416619e99ddb5b010def312James Dong        return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes;
152977e8ae9967a078770416619e99ddb5b010def312James Dong    }
1530fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1531acd234bba9f048971d66890009eeff9a8db94be3James Dong    // Be conservative in the estimate: do not exceed 95% of
1532acd234bba9f048971d66890009eeff9a8db94be3James Dong    // the target file limit. For small target file size limit, though,
1533acd234bba9f048971d66890009eeff9a8db94be3James Dong    // this will not help.
1534acd234bba9f048971d66890009eeff9a8db94be3James Dong    return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100);
1535d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1536d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1537fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangbool MPEG4Writer::approachingFileSizeLimit() {
1538fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    // No limit
1539fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mMaxFileSizeLimitBytes == 0) {
1540fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return false;
1541fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1542fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1543fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
1544fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    for (List<Track *>::iterator it = mTracks.begin();
1545fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         it != mTracks.end(); ++it) {
1546fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
1547fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1548fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1549fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (!mStreamableFile) {
1550fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        // Add 1024 bytes as error tolerance
1551fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return nTotalBytesEstimate + 1024 >= (90 * mMaxFileSizeLimitBytes) / 100;
1552fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1553fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1554fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    return (nTotalBytesEstimate >= (90 * mMaxFileSizeLimitBytes) / 100);
1555fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
1556fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1557d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() {
1558d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1559d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationLimitUs == 0) {
1560d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1561d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1562d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1563d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1564d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1565d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
1566d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            return true;
1567d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1568d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1569d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return false;
1570d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1571d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
157225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
157325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
157425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
157525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
157625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
157725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
157825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
157925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
158025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
158125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
158225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
158325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
158425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
1585f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
1586a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGI("setStartTimestampUs: %" PRId64, timeUs);
158743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(timeUs, 0ll);
15883c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
1589065d1aff96818df54456053f1574aec8a234d0deJames Dong    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
1590f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimestampUs = timeUs;
1591a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Earliest track starting time: %" PRId64, mStartTimestampUs);
15923c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    }
15933c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
15943c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
1595f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() {
15963c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
15973c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    return mStartTimestampUs;
15983c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
15993c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
160058ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() {
160158ae9c530247668f8af36e30d228c716c226b3d4James Dong    Mutex::Autolock autolock(mLock);
160258ae9c530247668f8af36e30d228c716c226b3d4James Dong    return mTracks.size();
160358ae9c530247668f8af36e30d228c716c226b3d4James Dong}
160458ae9c530247668f8af36e30d228c716c226b3d4James Dong
160520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
160620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
160720111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
1608b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen        MPEG4Writer *owner, const sp<IMediaSource> &source, size_t trackId)
160920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
161025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
161120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
161220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
1613a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
1614a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mResumed(false),
1615eaae38445a340c4857c1c5569475879a728e63b7James Dong      mStarted(false),
1616fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mGotStartKeyFrame(false),
16179db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang      mIsMalformed(false),
1618bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong      mTrackId(trackId),
1619c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong      mTrackDurationUs(0),
1620956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mEstimatedTrackSizeBytes(0),
1621be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong      mSamplesHaveSameSize(true),
1622c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mStszTableEntries(new ListTableEntries<uint32_t, 1>(1000)),
1623c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mStcoTableEntries(new ListTableEntries<uint32_t, 1>(1000)),
1624c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mCo64TableEntries(new ListTableEntries<off64_t, 1>(1000)),
1625c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mStscTableEntries(new ListTableEntries<uint32_t, 3>(1000)),
1626c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mStssTableEntries(new ListTableEntries<uint32_t, 1>(1000)),
1627c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mSttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)),
1628c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mCttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)),
162920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
163025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
1631548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
163213f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mReachedEOS(false),
1633a9292fe1c19e8a9b43398ba3d69284c215d7589fRobert Shih      mStartTimestampUs(-1),
163413f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mRotation(0) {
163519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    getCodecSpecificDataFromInputFormatIfPossible();
16368f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
16371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    const char *mime;
16381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMeta->findCString(kKeyMIMEType, &mime);
16391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
16409aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mIsHevc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC);
16411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAudio = !strncasecmp(mime, "audio/", 6);
164225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mIsVideo = !strncasecmp(mime, "video/", 6);
16431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
16441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
16451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1646b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar    // store temporal layer count
164725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (mIsVideo) {
1648b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar        int32_t count;
1649b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar        if (mMeta->findInt32(kKeyTemporalLayerCount, &count) && count > 1) {
1650b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar            mOwner->setTemporalLayerCount(count);
1651b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar        }
1652b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar    }
1653b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar
1654c059860c73678a202bfa33062723e8f82fb779d9James Dong    setTimeScale();
1655c059860c73678a202bfa33062723e8f82fb779d9James Dong}
1656c059860c73678a202bfa33062723e8f82fb779d9James Dong
1657fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang// Clear all the internal states except the CSD data.
1658fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::Track::resetInternal() {
1659fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mDone = false;
1660fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mPaused = false;
1661fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mResumed = false;
1662fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mStarted = false;
1663fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mGotStartKeyFrame = false;
1664fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mIsMalformed = false;
1665fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mTrackDurationUs = 0;
1666fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mEstimatedTrackSizeBytes = 0;
1667fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mSamplesHaveSameSize = 0;
1668fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mStszTableEntries != NULL) {
1669fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mStszTableEntries;
1670fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mStszTableEntries = new ListTableEntries<uint32_t, 1>(1000);
1671fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1672fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1673fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mStcoTableEntries != NULL) {
1674fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mStcoTableEntries;
1675fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mStcoTableEntries = new ListTableEntries<uint32_t, 1>(1000);
1676fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1677fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mCo64TableEntries != NULL) {
1678fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mCo64TableEntries;
1679fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mCo64TableEntries = new ListTableEntries<off64_t, 1>(1000);
1680fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1681fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1682fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mStscTableEntries != NULL) {
1683fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mStscTableEntries;
1684fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mStscTableEntries = new ListTableEntries<uint32_t, 3>(1000);
1685fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1686fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mStssTableEntries != NULL) {
1687fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mStssTableEntries;
1688fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mStssTableEntries = new ListTableEntries<uint32_t, 1>(1000);
1689fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1690fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mSttsTableEntries != NULL) {
1691fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mSttsTableEntries;
1692fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mSttsTableEntries = new ListTableEntries<uint32_t, 2>(1000);
1693fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1694fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mCttsTableEntries != NULL) {
1695fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mCttsTableEntries;
1696fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mCttsTableEntries = new ListTableEntries<uint32_t, 2>(1000);
1697fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1698fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mReachedEOS = false;
1699fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
1700fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
17011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() {
17021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1703c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t stcoBoxCount = (mOwner->use32BitFileOffset()
1704c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                            ? mStcoTableEntries->count()
1705c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                            : mCo64TableEntries->count());
1706c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    int64_t stcoBoxSizeBytes = stcoBoxCount * 4;
1707c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4);
17081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
170978a1a286f736888ae7af8860b2c424af0d978848James Dong    mEstimatedTrackSizeBytes = mMdatSizeBytes;  // media data size
171078a1a286f736888ae7af8860b2c424af0d978848James Dong    if (!mOwner->isFileStreamable()) {
171178a1a286f736888ae7af8860b2c424af0d978848James Dong        // Reserved free space is not large enough to hold
171278a1a286f736888ae7af8860b2c424af0d978848James Dong        // all meta data and thus wasted.
1713c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 +  // stsc box size
1714c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mStssTableEntries->count() * 4 +   // stss box size
1715c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mSttsTableEntries->count() * 8 +   // stts box size
1716c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mCttsTableEntries->count() * 8 +   // ctts box size
171778a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stcoBoxSizeBytes +           // stco box size
171878a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stszBoxSizeBytes;            // stsz box size
171978a1a286f736888ae7af8860b2c424af0d978848James Dong    }
17201f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
17211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
17221f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry(
17231f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        size_t chunkId, size_t sampleId) {
17241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1725c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(chunkId));
1726c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(sampleId));
1727c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(1));
17281f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
17291f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
17301f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) {
1731c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->add(htonl(sampleId));
17321f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
17331f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
17341f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry(
173579761ab096f57c3027fad9556c2bc436672d614eJames Dong        size_t sampleCount, int32_t duration) {
17361f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
17375a217fba010e801c255503602bda4b86ac5a6ac9James Dong    if (duration == 0) {
1738377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGW("0-duration samples found: %zu", sampleCount);
17395a217fba010e801c255503602bda4b86ac5a6ac9James Dong    }
1740c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(sampleCount));
1741c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(duration));
17421f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
17431f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1744965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry(
1745965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        size_t sampleCount, int32_t duration) {
1746965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
174725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (!mIsVideo) {
1748965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
1749965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
1750c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(sampleCount));
1751c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(duration));
1752965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
1753965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1754fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::setNextFd(int fd) {
1755fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGV("addNextFd");
1756fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    Mutex::Autolock l(mLock);
1757fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mLooper == NULL) {
1758fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mReflector = new AHandlerReflector<MPEG4Writer>(this);
1759fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mLooper = new ALooper;
1760fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mLooper->registerHandler(mReflector);
1761fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mLooper->start();
1762fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1763fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1764fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mNextFd != -1) {
1765fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        // No need to set a new FD yet.
1766fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return INVALID_OPERATION;
1767fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1768fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mNextFd = fd;
1769fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    return OK;
1770fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
1771fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1772c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) {
1773c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mOwner->use32BitFileOffset()) {
1774c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t value = offset;
1775c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->add(htonl(value));
1776c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
1777c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->add(hton64(offset));
1778c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    }
17791f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
17801f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1781c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() {
17823856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setTimeScale");
1783c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Default time scale
1784c059860c73678a202bfa33062723e8f82fb779d9James Dong    mTimeScale = 90000;
1785c059860c73678a202bfa33062723e8f82fb779d9James Dong
1786c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mIsAudio) {
1787c059860c73678a202bfa33062723e8f82fb779d9James Dong        // Use the sampling rate as the default time scale for audio track.
1788c059860c73678a202bfa33062723e8f82fb779d9James Dong        int32_t sampleRate;
1789c059860c73678a202bfa33062723e8f82fb779d9James Dong        bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
1790c059860c73678a202bfa33062723e8f82fb779d9James Dong        CHECK(success);
1791c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = sampleRate;
1792c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1793c059860c73678a202bfa33062723e8f82fb779d9James Dong
1794c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If someone would like to overwrite the timescale, use user-supplied value.
1795c059860c73678a202bfa33062723e8f82fb779d9James Dong    int32_t timeScale;
1796c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
1797c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = timeScale;
1798c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1799c059860c73678a202bfa33062723e8f82fb779d9James Dong
180043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
180119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber}
180219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
1803fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::onMessageReceived(const sp<AMessage> &msg) {
1804fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    switch (msg->what()) {
1805fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        case kWhatSwitch:
1806fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        {
1807fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            finishCurrentSession();
1808fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mLock.lock();
1809fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            int fd = mNextFd;
1810fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mNextFd = -1;
1811fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mLock.unlock();
1812fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            initInternal(fd);
1813fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            start(mStartMeta.get());
1814fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mSwitchPending = false;
1815fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED, 0);
1816fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            break;
1817fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        }
1818fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        default:
1819fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        TRESPASS();
1820fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1821fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
1822fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
182319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
182419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    const char *mime;
1825fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
182619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
182719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
18289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    uint32_t type;
18299aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const void *data = NULL;
18309aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t size = 0;
183119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
18329aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mMeta->findData(kKeyAVCC, &type, &data, &size);
18339aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
18349aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mMeta->findData(kKeyHVCC, &type, &data, &size);
183519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
183619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
183719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
183819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            ESDS esds(data, size);
18399aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            if (esds.getCodecSpecificInfo(&data, &size) != OK) {
18409aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                data = NULL;
18419aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                size = 0;
184219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            }
184319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
184419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
18459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (data != NULL && copyCodecSpecificData((uint8_t *)data, size) == OK) {
18469aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mGotAllCodecSpecificData = true;
18479aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
184820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
184920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
185020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
185120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
185220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1853c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStszTableEntries;
1854c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStcoTableEntries;
1855c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCo64TableEntries;
1856c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStscTableEntries;
1857c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mSttsTableEntries;
1858c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStssTableEntries;
1859c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCttsTableEntries;
1860c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
1861c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries = NULL;
1862c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStcoTableEntries = NULL;
1863c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCo64TableEntries = NULL;
1864c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries = NULL;
1865c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries = NULL;
1866c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries = NULL;
1867c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries = NULL;
1868c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
186920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
187020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
187120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
187220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
187320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
187420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
187593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
18763856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("initTrackingProgressStatus");
187793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mPreviousTrackTimeUs = -1;
187893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackingProgressStatus = false;
187993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
188093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    {
188193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeUs;
188293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
1883a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGV("Receive request to track progress status for every %" PRId64 " us", timeUs);
188493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackEveryTimeDurationUs = timeUs;
188593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackingProgressStatus = true;
188693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
188793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
188893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
188993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
18901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static
18911c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) {
18923856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("ThreadWrapper: %p", me);
18931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
18941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    writer->threadFunc();
18951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return NULL;
18961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
18971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18981c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) {
18993856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk: %p", chunk.mTrack);
19001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Mutex::Autolock autolock(mLock);
19011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK_EQ(mDone, false);
19021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
19031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
19041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
19051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
19061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (chunk.mTrack == it->mTrack) {  // Found owner
19071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            it->mChunks.push_back(chunk);
19081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.signal();
19091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            return;
19101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
19111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
19121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
191343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK(!"Received a chunk for a unknown track");
19141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
19151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1916fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) {
1917a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("writeChunkToFile: %" PRId64 " from %s track",
191825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        chunk->mTimeStampUs, chunk->mTrack->getTrackType());
1919fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1920fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    int32_t isFirstSample = true;
1921fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    while (!chunk->mSamples.empty()) {
1922fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        List<MediaBuffer *>::iterator it = chunk->mSamples.begin();
1923fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
19249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        off64_t offset = (chunk->mTrack->isAvc() || chunk->mTrack->isHevc())
192580f78b773f92048944a850efb7b60629643370cdPraveen Chavan                                ? addMultipleLengthPrefixedSamples_l(*it)
1926fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong                                : addSample_l(*it);
1927fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1928fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (isFirstSample) {
1929fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            chunk->mTrack->addChunkOffset(offset);
1930fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            isFirstSample = false;
19311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
19321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
19331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it)->release();
19341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it) = NULL;
1935fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        chunk->mSamples.erase(it);
19361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1937fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    chunk->mSamples.clear();
19381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
19391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1940fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() {
19413856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeAllChunks");
19421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    size_t outstandingChunks = 0;
194370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    Chunk chunk;
194470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    while (findChunkToWrite(&chunk)) {
1945e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong        writeChunkToFile(&chunk);
194670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        ++outstandingChunks;
19471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
194870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
194970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    sendSessionSummary();
195070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
19511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mChunkInfos.clear();
1952377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    ALOGD("%zu chunks are written in the last batch", outstandingChunks);
19531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
19541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1955fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) {
19563856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("findChunkToWrite");
19571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
19581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
19591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Track *track = NULL;
19601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
19611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
19621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (!it->mChunks.empty()) {
19631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            List<Chunk>::iterator chunkIt = it->mChunks.begin();
19641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (chunkIt->mTimeStampUs < minTimestampUs) {
19651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                minTimestampUs = chunkIt->mTimeStampUs;
19661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                track = it->mTrack;
19671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            }
19681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
19691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
19701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
19711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (track == NULL) {
19723856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Nothing to be written after all");
1973fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        return false;
19741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
19751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
19761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mIsFirstChunk) {
19771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsFirstChunk = false;
19781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1979fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
19801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
19811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
19821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it->mTrack == track) {
1983fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            *chunk = *(it->mChunks.begin());
1984fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            it->mChunks.erase(it->mChunks.begin());
1985fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            CHECK_EQ(chunk->mTrack, track);
198670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
198770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t interChunkTimeUs =
198870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                chunk->mTimeStampUs - it->mPrevChunkTimestampUs;
198970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            if (interChunkTimeUs > it->mPrevChunkTimestampUs) {
199070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs = interChunkTimeUs;
199170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            }
199270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
1993fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            return true;
19941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
19951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1996fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1997fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    return false;
19981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
19991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
20001c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() {
20013856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("threadFunc");
20021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
2003a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0);
2004fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
2005fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    Mutex::Autolock autoLock(mLock);
20061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mDone) {
2007fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        Chunk chunk;
2008fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        bool chunkFound = false;
2009fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
2010fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) {
20111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.wait(mLock);
20121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
20131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
2014de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // In real time recording mode, write without holding the lock in order
2015de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // to reduce the blocking time for media track threads.
2016de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // Otherwise, hold the lock until the existing chunks get written to the
2017de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // file.
2018fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (chunkFound) {
2019de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            if (mIsRealTimeRecording) {
2020de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui                mLock.unlock();
2021de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            }
2022fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            writeChunkToFile(&chunk);
2023de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            if (mIsRealTimeRecording) {
2024de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui                mLock.lock();
2025de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            }
2026fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        }
20271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
2028fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
2029fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    writeAllChunks();
20301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
20311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
20321c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() {
20333856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("startWriterThread");
20341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
20351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mDone = false;
20361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsFirstChunk = true;
2037e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    mDriftTimeUs = 0;
20381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<Track *>::iterator it = mTracks.begin();
20391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mTracks.end(); ++it) {
20401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        ChunkInfo info;
20411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        info.mTrack = *it;
204270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mPrevChunkTimestampUs = 0;
204370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mMaxInterChunkDurUs = 0;
20441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.push_back(info);
20451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
20461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
20471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_t attr;
20481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_init(&attr);
20491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
20501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_create(&mThread, &attr, ThreadWrapper, this);
20511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_destroy(&attr);
2052411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = true;
20531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
20541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
20551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
20561f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
205793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) {
2058a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (!mDone && mPaused) {
2059a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mPaused = false;
2060a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mResumed = true;
2061a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
2062a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
206325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
206493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t startTimeUs;
206519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
206619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        startTimeUs = 0;
206719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
206870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    mStartTimeRealUs = startTimeUs;
206919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
207013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t rotationDegrees;
207125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (mIsVideo && params && params->findInt32(kKeyRotation, &rotationDegrees)) {
207213f6284305e4b27395a23db7882d670bdb1bcae1James Dong        mRotation = rotationDegrees;
207313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
207413f6284305e4b27395a23db7882d670bdb1bcae1James Dong
207593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    initTrackingProgressStatus(params);
207693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
2077f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    sp<MetaData> meta = new MetaData;
2078de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) {
2079a472613aec322e25891abf5c77bf3f7e3c244920James Dong        /*
2080a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * This extra delay of accepting incoming audio/video signals
2081a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * helps to align a/v start time at the beginning of a recording
2082a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * session, and it also helps eliminate the "recording" sound for
2083a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * camcorder applications.
2084a472613aec322e25891abf5c77bf3f7e3c244920James Dong         *
208586b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * If client does not set the start time offset, we fall back to
208686b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * use the default initial delay value.
2087a472613aec322e25891abf5c77bf3f7e3c244920James Dong         */
208886b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
208986b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
209086b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
209186b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
209286b7f47aa7482424cf8fd248f1315311919be3b0James Dong        startTimeUs += startTimeOffsetUs;
2093a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Start time offset: %" PRId64 " us", startTimeOffsetUs);
2094a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
2095a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2096f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    meta->setInt64(kKeyTime, startTimeUs);
2097a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2098f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    status_t err = mSource->start(meta.get());
209925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
210025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
210125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
210225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
210320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
210420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
210520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
210620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
210720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
210820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
2109eaae38445a340c4857c1c5569475879a728e63b7James Dong    mStarted = true;
2110c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs = 0;
211125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
2112956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mEstimatedTrackSizeBytes = 0;
21131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mMdatSizeBytes = 0;
211443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mMaxChunkDurationUs = 0;
2115826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar    mLastDecodingTimeUs = -1;
211620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
211725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
211820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
211925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
212025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
212120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
212220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
212337187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() {
2124a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
212537187916a486504acaf83bea30147eb5fbf46ae5James Dong    return OK;
2126a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
2127a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2128fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::Track::stop(bool stopSource) {
2129fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGD("%s track stopping. %s source", getTrackType(), stopSource ? "Stop" : "Not Stop");
2130eaae38445a340c4857c1c5569475879a728e63b7James Dong    if (!mStarted) {
213129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Stop() called but track is not started");
2132eaae38445a340c4857c1c5569475879a728e63b7James Dong        return ERROR_END_OF_STREAM;
2133eaae38445a340c4857c1c5569475879a728e63b7James Dong    }
2134eaae38445a340c4857c1c5569475879a728e63b7James Dong
213520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
213637187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
213720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
2138f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang
2139fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (stopSource) {
2140fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        ALOGD("%s track source stopping", getTrackType());
2141fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mSource->stop();
2142fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        ALOGD("%s track source stopped", getTrackType());
2143fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
214472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
2145f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang    // Set mDone to be true after sucessfully stop mSource as mSource may be still outputting
2146f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang    // buffers to the writer.
2147f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang    mDone = true;
2148f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang
214920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
215020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
2151377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy));
215237187916a486504acaf83bea30147eb5fbf46ae5James Dong
2153fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGD("%s track stopped. %s source", getTrackType(), stopSource ? "Stop" : "Not Stop");
215437187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
215520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
215620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
215725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
215825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
215925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
216025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
216120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
216220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
216320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
216420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
216537187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = track->threadEntry();
2166377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    return (void *)(uintptr_t)err;
216720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
216820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) {
21703856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("getNalUnitType: %d", byte);
21713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // nal_unit_type: 5-bit unsigned integer
21733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *type = (byte & 0x1F);
21743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
21753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet(
21773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
21783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21793856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseParamSet");
21803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    CHECK(type == kNalUnitTypeSeqParamSet ||
21813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong          type == kNalUnitTypePicParamSet);
21823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
218347d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar    const uint8_t *nextStartCode = findNextNalStartCode(data, length);
21843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *paramSetLen = nextStartCode - data;
21853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (*paramSetLen == 0) {
218629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Param set is malformed, since its length is 0");
21873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return NULL;
21883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
21893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    AVCParamSet paramSet(*paramSetLen, data);
21913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (type == kNalUnitTypeSeqParamSet) {
21923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (*paramSetLen < 4) {
219329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Seq parameter set malformed");
21943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return NULL;
21953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
21963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mSeqParamSets.empty()) {
21973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc = data[1];
21983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileCompatible = data[2];
21993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mLevelIdc = data[3];
22003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
22013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (mProfileIdc != data[1] ||
22023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mProfileCompatible != data[2] ||
22033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mLevelIdc != data[3]) {
220407b2fbfb40770f3be0f674596f2e51d257c6d2bdLajos Molnar                // COULD DO: set profile/level to the lowest required to support all SPSs
220529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Inconsistent profile/level found in seq parameter sets");
22063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return NULL;
22073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
22083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
22093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mSeqParamSets.push_back(paramSet);
22103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    } else {
22113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mPicParamSets.push_back(paramSet);
22123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
22133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return nextStartCode;
22143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
22153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData(
22173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
22183856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("copyAVCCodecSpecificData");
22193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 2 bytes for each of the parameter set length field
22213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // plus the 7 bytes for the header
22229aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return copyCodecSpecificData(data, size, 4 + 7);
22239aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
22249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22259aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyHEVCCodecSpecificData(
22269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size) {
22279aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ALOGV("copyHEVCCodecSpecificData");
22289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22299aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Min length of HEVC CSD is 23. (ISO/IEC 14496-15:2014 Chapter 8.3.3.1.2)
22309aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return copyCodecSpecificData(data, size, 23);
22319aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
22329aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22339aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyCodecSpecificData(
22349aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size, size_t minLength) {
22359aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (size < minLength) {
2236377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGE("Codec specific data length too short: %zu", size);
22373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return ERROR_MALFORMED;
22383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
22393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificData = malloc(size);
22419aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
22429aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
22439aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
22449aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
22459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificDataSize = size;
22463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    memcpy(mCodecSpecificData, data, size);
22473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
22483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
22493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData(
22513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
22523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22533856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseAVCCodecSpecificData");
22543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data starts with a start code.
22553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // SPS and PPS are separated with start codes.
22563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Also, SPS must come before PPS
22573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t type = kNalUnitTypeSeqParamSet;
22583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotSps = false;
22593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotPps = false;
22603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *tmp = data;
22613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = data;
22623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = size;
22633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t paramSetLen = 0;
22643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = 0;
22653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
22663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        getNalUnitType(*(tmp + 4), &type);
22673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (type == kNalUnitTypeSeqParamSet) {
22683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (gotPps) {
226929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
22703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
22713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
22723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
22733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotSps = true;
22743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
22753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
22763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else if (type == kNalUnitTypePicParamSet) {
22773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
227829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
22793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
22803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
22813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotPps) {
22823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotPps = true;
22833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
22843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
22853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
228629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Only SPS and PPS Nal units are expected");
22873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
22883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
22893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nextStartCode == NULL) {
22913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
22923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
22933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Move on to find the next parameter set
22953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft -= nextStartCode - tmp;
22963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        tmp = nextStartCode;
22973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mCodecSpecificDataSize += (2 + paramSetLen);
22983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
22993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
23003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
23013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of seq parameter sets
23023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nSeqParamSets = mSeqParamSets.size();
23033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets == 0) {
230429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find sequence parameter set");
23053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
23063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
23073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
23083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets > 0x1F) {
2309377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets);
23103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
23113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
23123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
23133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
23143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
23153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of pic parameter sets
23163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nPicParamSets = mPicParamSets.size();
23173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets == 0) {
231829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find picture parameter set");
23193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
23203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
23213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets > 0xFF) {
2322377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets);
23233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
23243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
23253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
23261374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME:
23271374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above
23281374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0
23291374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0
23303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
23313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the profiles
23323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // These profiles requires additional parameter set extensions
23333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mProfileIdc == 100 || mProfileIdc == 110 ||
23343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc == 122 || mProfileIdc == 144) {
233529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
23363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return BAD_VALUE;
23373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
23383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
23391374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif
23403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
23413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
2342548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
234303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
234403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
2345548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
234603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
234729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Already have codec specific data");
234803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
234903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
235003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
23513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4) {
2352377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGE("Codec specific data length too short: %zu", size);
235303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
235403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
235503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
23563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data is in the form of AVCCodecSpecificData
23573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (memcmp("\x00\x00\x00\x01", data, 4)) {
23583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return copyAVCCodecSpecificData(data, size);
235903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
236003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
23613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (parseAVCCodecSpecificData(data, size) != OK) {
236203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
236303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
236403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
23653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // ISO 14496-15: AVC file format
23663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize += 7;  // 7 more bytes in the header
236703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
23689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
23699aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mCodecSpecificDataSize = 0;
23709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
23719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
23729aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
237303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
23743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = 1;                     // version
23753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[1] = mProfileIdc;           // profile indication
23763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[2] = mProfileCompatible;    // profile compatibility
23773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[3] = mLevelIdc;
237803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
23793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
2380b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mOwner->useNalLengthFour()) {
2381b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 3;  // length size == 4 bytes
2382b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
2383b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 1;  // length size == 2 bytes
2384b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
238503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
23863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 3-bit '111' followed by 5-bit numSequenceParameterSets
23873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nSequenceParamSets = mSeqParamSets.size();
23883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[5] = 0xe0 | nSequenceParamSets;
23893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 6;
23903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
23913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mSeqParamSets.end(); ++it) {
23923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit sequence parameter set length
23933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t seqParamSetLength = it->mLength;
23943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = seqParamSetLength >> 8;
23953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = seqParamSetLength & 0xff;
23963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
23973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // SPS NAL unit (sequence parameter length bytes)
23983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, seqParamSetLength);
23993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + seqParamSetLength);
24003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
24013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
24023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 8-bit nPictureParameterSets
24033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nPictureParamSets = mPicParamSets.size();
24043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = nPictureParamSets;
24053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 1;
24063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
24073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mPicParamSets.end(); ++it) {
24083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit picture parameter set length
24093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t picParamSetLength = it->mLength;
24103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = picParamSetLength >> 8;
24113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = picParamSetLength & 0xff;
24123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
24133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // PPS Nal unit (picture parameter set length bytes)
24143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, picParamSetLength);
24153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + picParamSetLength);
24163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
241703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
241803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
241903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
242003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
24219aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24229aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::parseHEVCCodecSpecificData(
24239aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size, HevcParameterSets &paramSets) {
24249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24259aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ALOGV("parseHEVCCodecSpecificData");
24269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const uint8_t *tmp = data;
24279aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const uint8_t *nextStartCode = data;
24289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t bytesLeft = size;
24299aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
243047d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar        nextStartCode = findNextNalStartCode(tmp + 4, bytesLeft - 4);
24319aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        status_t err = paramSets.addNalUnit(tmp + 4, (nextStartCode - tmp) - 4);
24329aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (err != OK) {
24339aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
24349aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
24359aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24369aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        // Move on to find the next parameter set
24379aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        bytesLeft -= nextStartCode - tmp;
24389aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        tmp = nextStartCode;
24399aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
24409aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24419aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t csdSize = 23;
24429aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const size_t numNalUnits = paramSets.getNumNalUnits();
24439aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    for (size_t i = 0; i < ARRAY_SIZE(kMandatoryHevcNalUnitTypes); ++i) {
24449aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        int type = kMandatoryHevcNalUnitTypes[i];
24459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        size_t numParamSets = paramSets.getNumNalUnitsOfType(type);
24469aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (numParamSets == 0) {
24479aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            ALOGE("Cound not find NAL unit of type %d", type);
24489aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
24499aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
24509aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
24519aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    for (size_t i = 0; i < ARRAY_SIZE(kHevcNalUnitTypes); ++i) {
24529aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        int type = kHevcNalUnitTypes[i];
24539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        size_t numParamSets = paramSets.getNumNalUnitsOfType(type);
24549aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (numParamSets > 0xffff) {
24559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            ALOGE("Too many seq parameter sets (%zu) found", numParamSets);
24569aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
24579aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
24589aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        csdSize += 3;
24599aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        for (size_t j = 0; j < numNalUnits; ++j) {
24609aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            if (paramSets.getType(j) != type) {
24619aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                continue;
24629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            }
24639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            csdSize += 2 + paramSets.getSize(j);
24649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
24659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
24669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificDataSize = csdSize;
24679aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return OK;
24689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
24699aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::makeHEVCCodecSpecificData(
24719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size) {
24729aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24739aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData != NULL) {
24749aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Already have codec specific data");
24759aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
24769aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
24779aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24789aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (size < 4) {
24799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Codec specific data length too short: %zu", size);
24809aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
24819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
24829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Data is in the form of HEVCCodecSpecificData
24849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (memcmp("\x00\x00\x00\x01", data, 4)) {
24859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return copyHEVCCodecSpecificData(data, size);
24869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
24879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    HevcParameterSets paramSets;
24899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (parseHEVCCodecSpecificData(data, size, paramSets) != OK) {
24903d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim        ALOGE("failed parsing codec specific data");
24919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
24929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
24939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificData = malloc(mCodecSpecificDataSize);
24959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
24969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mCodecSpecificDataSize = 0;
24979aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
24989aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
24999aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
25009aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t err = paramSets.makeHvcc((uint8_t *)mCodecSpecificData,
25013d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim            &mCodecSpecificDataSize, mOwner->useNalLengthFour() ? 4 : 2);
25029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (err != OK) {
25033d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim        ALOGE("failed constructing HVCC atom");
25049aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return err;
25059aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
25069aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
25079aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return OK;
25089aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
25099aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
2510872a481558350634a3fd5cb67939de288af00ecbJames Dong/*
2511872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that
2512872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information
2513872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio
2514872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger
2515872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5,
2516872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined.
2517872a481558350634a3fd5cb67939de288af00ecbJames Dong */
2518872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) {
2519872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t driftTimeUs = 0;
2520872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) {
2521872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t prevDriftTimeUs = mOwner->getDriftTimeUs();
2522872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1;
2523872a481558350634a3fd5cb67939de288af00ecbJames Dong        mOwner->setDriftTimeUs(timeUs);
2524872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2525872a481558350634a3fd5cb67939de288af00ecbJames Dong}
2526872a481558350634a3fd5cb67939de288af00ecbJames Dong
252762a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuangvoid MPEG4Writer::Track::dumpTimeStamps() {
252862a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang    ALOGE("Dumping %s track's last 10 frames timestamp ", getTrackType());
252962a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang    std::string timeStampString;
253062a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang    for (std::list<std::pair<int64_t, int64_t>>::iterator num = mTimestampDebugHelper.begin();
253162a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang            num != mTimestampDebugHelper.end(); ++num) {
253262a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang        timeStampString += "(" + std::to_string(num->first)+
253362a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang                "us, " + std::to_string(num->second) + "us) ";
253462a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang    }
253562a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang    ALOGE("%s", timeStampString.c_str());
253662a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang}
253762a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang
253837187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() {
253930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
254013aec890216948b0c364f8f92792129d0335f506James Dong    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
254143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    const bool hasMultipleTracks = (mOwner->numTracks() > 1);
254213aec890216948b0c364f8f92792129d0335f506James Dong    int64_t chunkTimestampUs = 0;
254313aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nChunks = 0;
25447c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar    int32_t nActualFrames = 0;        // frames containing non-CSD data (non-0 length)
254513aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nZeroLengthFrames = 0;
2546965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastTimestampUs = 0;      // Previous sample time stamp
2547965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationUs = 0;       // Between the previous two samples
2548965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t currDurationTicks = 0;    // Timescale based ticks
2549965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationTicks = 0;    // Timescale based ticks
2550965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int32_t sampleCount = 1;          // Sample count in the current stts table entry
2551000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    uint32_t previousSampleSize = 0;  // Size of the previous sample
2552a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t previousPausedDurationUs = 0;
2553965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t timestampUs = 0;
2554000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t cttsOffsetTimeUs = 0;
2555000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t currCttsOffsetTimeTicks = 0;   // Timescale based ticks
2556000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t lastCttsOffsetTimeTicks = -1;  // Timescale based ticks
255743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    int32_t cttsSampleCount = 0;           // Sample count in the current ctts table entry
2558c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t lastSamplesPerChunk = 0;
2559e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2560a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    if (mIsAudio) {
2561a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
256225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else if (mIsVideo) {
2563a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
256425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else {
256525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        prctl(PR_SET_NAME, (unsigned long)"MetadataTrackEncoding", 0, 0, 0);
2566a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    }
2567de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
2568de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (mOwner->isRealTimeRecording()) {
2569de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
2570de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    }
2571985f838934510983d8a887461e98dca60a6e858fJames Dong
2572d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong    sp<MetaData> meta_data;
257320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
257493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t err = OK;
257520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
257625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    const char *trackName = getTrackType();
257793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    while (!mDone && (err = mSource->read(&buffer)) == OK) {
257820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
257920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
258020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
258113aec890216948b0c364f8f92792129d0335f506James Dong            ++nZeroLengthFrames;
258220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
258320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
258420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2585a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // If the codec specific data has not been received yet, delay pause.
2586a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // After the codec specific data is received, discard what we received
2587a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // when the track is to be paused.
2588a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused && !mResumed) {
2589a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer->release();
2590a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer = NULL;
2591a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            continue;
2592a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2593a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
259430ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
259530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
259603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
259703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
259803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
25997c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // if config format (at track addition) already had CSD, keep that
26007c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // UNLESS we have not received any frames yet.
26017c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // TODO: for now the entire CSD has to come in one frame for encoders, even though
26027c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // they need to be spread out for decoders.
26037c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            if (mGotAllCodecSpecificData && nActualFrames > 0) {
26047c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                ALOGI("ignoring additional CSD for video track after first frame");
26057c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            } else {
26067c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                mMeta = mSource->getFormat(); // get output format after format change
26076e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang                status_t err;
26087c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                if (mIsAvc) {
26096e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang                    err = makeAVCCodecSpecificData(
26107c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            (const uint8_t *)buffer->data()
26117c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                                + buffer->range_offset(),
26127c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
26137c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                } else if (mIsHevc) {
26146e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang                    err = makeHEVCCodecSpecificData(
26157c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            (const uint8_t *)buffer->data()
26167c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                                + buffer->range_offset(),
26177c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
26187c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                } else if (mIsMPEG4) {
26197c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    copyCodecSpecificData((const uint8_t *)buffer->data() + buffer->range_offset(),
26207c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
26217c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                }
262230ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
262330ab66297501757d745b9ae10da61adcd891f497Andreas Huber
262430ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
262530ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
26266e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang            if (OK != err) {
26276e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang                mSource->stop();
26286e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang                mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
26296e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang                       mTrackId | MEDIA_RECORDER_TRACK_ERROR_GENERAL, err);
26306e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang                break;
26316e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang            }
263230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
2633548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
263430ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
2635a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2636a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2637e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang        // Per-frame metadata sample's size must be smaller than max allowed.
2638e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang        if (!mIsVideo && !mIsAudio && buffer->range_length() >= kMaxMetadataSize) {
2639e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            ALOGW("Buffer size is %zu. Maximum metadata buffer size is %lld for %s track",
2640e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang                    buffer->range_length(), (long long)kMaxMetadataSize, trackName);
2641e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            buffer->release();
2642e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            mSource->stop();
2643e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            mIsMalformed = true;
2644e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            break;
2645e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang        }
2646e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang
26477c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar        ++nActualFrames;
26487c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar
2649d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // Make a deep copy of the MediaBuffer and Metadata and release
2650d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // the original as soon as we can
2651d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
2652d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
2653d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                buffer->range_length());
2654d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        copy->set_range(0, buffer->range_length());
2655d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data = new MetaData(*buffer->meta_data().get());
2656d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer->release();
2657d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer = NULL;
2658d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
26599aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (mIsAvc || mIsHevc) StripStartcode(copy);
2660e136c3bb38e88315bf8797a464ebf2c788296b22James Dong
2661b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        size_t sampleSize = copy->range_length();
26629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (mIsAvc || mIsHevc) {
2663b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            if (mOwner->useNalLengthFour()) {
2664b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 4;
2665b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            } else {
2666b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 2;
2667b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            }
2668b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        }
2669050b28a593350047845a45a14cc5026221ac1620James Dong
2670d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        // Max file size or duration handling
26711f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mMdatSizeBytes += sampleSize;
26721f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        updateTrackSizeEstimate();
26731f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
2674d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileSizeLimit()) {
2675fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            if (mOwner->switchFd() != OK) {
2676fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                ALOGW("Recorded file size exceeds limit %" PRId64 "bytes",
2677fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                        mOwner->mMaxFileSizeLimitBytes);
2678fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                mSource->stop();
2679fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                mOwner->notify(
2680fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                        MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
2681fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            } else {
2682fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                ALOGV("%s Current recorded file size exceeds limit %" PRId64 "bytes. Switching output",
2683fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                        getTrackType(), mOwner->mMaxFileSizeLimitBytes);
2684fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            }
2685d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            copy->release();
2686d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2687d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2688fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
2689d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileDurationLimit()) {
2690316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang            ALOGW("Recorded file duration exceeds limit %" PRId64 "microseconds",
2691316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang                    mOwner->mMaxFileDurationLimitUs);
2692d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
2693d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            copy->release();
2694d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            mSource->stop();
2695d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2696d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2697d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2698fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        if (mOwner->approachingFileSizeLimit()) {
2699fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mOwner->notifyApproachingLimit();
2700fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        }
2701050b28a593350047845a45a14cc5026221ac1620James Dong
2702d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        int32_t isSync = false;
2703d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
2704d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
2705d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
2706fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        // For video, skip the first several non-key frames until getting the first key frame.
2707fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        if (mIsVideo && !mGotStartKeyFrame && !isSync) {
2708fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            ALOGD("Video skip non-key frame");
2709fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            copy->release();
2710fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            continue;
2711fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        }
2712fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        if (mIsVideo && isSync) {
2713fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mGotStartKeyFrame = true;
2714fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        }
2715d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong////////////////////////////////////////////////////////////////////////////////
2716c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (mStszTableEntries->count() == 0) {
271770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mFirstSampleTimeRealUs = systemTime() / 1000;
2718f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimestampUs = timestampUs;
2719f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mOwner->setStartTimestampUs(mStartTimestampUs);
27208428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs = mStartTimestampUs;
27213c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        }
272248c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
2723a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mResumed) {
27248428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
272511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) {
272611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
2727d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang                mSource->stop();
27289db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                mIsMalformed = true;
27299db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                break;
273011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
273111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
27328428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
273311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) {
273411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
2735d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang                mSource->stop();
27369db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                mIsMalformed = true;
27379db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                break;
273811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
273911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
27408428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs += pausedDurationUs - lastDurationUs;
2741a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mResumed = false;
2742a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
274362a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang        std::pair<int64_t, int64_t> timestampPair;
2744a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        timestampUs -= previousPausedDurationUs;
274562a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang        timestampPair.first = timestampUs;
274611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
274711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
2748d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            mSource->stop();
27499db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            mIsMalformed = true;
27509db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            break;
275111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        }
275211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
275325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        if (mIsVideo) {
2754965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            /*
2755965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Composition time: timestampUs
2756965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Decoding time: decodingTimeUs
2757000e18370baae60ffd9f25b509501dd8c26deabfJames Dong             * Composition time offset = composition time - decoding time
2758965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             */
2759965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            int64_t decodingTimeUs;
2760965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
2761965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            decodingTimeUs -= previousPausedDurationUs;
2762826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar
2763826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            // ensure non-negative, monotonic decoding time
2764826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            if (mLastDecodingTimeUs < 0) {
2765826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar                decodingTimeUs = std::max((int64_t)0, decodingTimeUs);
2766826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            } else {
276738f4cbed37d5788e488fd39ccab0c78b07e89207Hangyu Kuang                // increase decoding time by at least the larger vaule of 1 tick and
276838f4cbed37d5788e488fd39ccab0c78b07e89207Hangyu Kuang                // 0.1 milliseconds. This needs to take into account the possible
276938f4cbed37d5788e488fd39ccab0c78b07e89207Hangyu Kuang                // delta adjustment in DurationTicks in below.
277038f4cbed37d5788e488fd39ccab0c78b07e89207Hangyu Kuang                decodingTimeUs = std::max(mLastDecodingTimeUs +
277138f4cbed37d5788e488fd39ccab0c78b07e89207Hangyu Kuang                        std::max(100, divUp(1000000, mTimeScale)), decodingTimeUs);
2772826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            }
2773826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar
2774826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            mLastDecodingTimeUs = decodingTimeUs;
2775000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            cttsOffsetTimeUs =
2776000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
277711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) {
277811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
2779d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang                mSource->stop();
27809db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                mIsMalformed = true;
27819db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                break;
278211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
278311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2784965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            timestampUs = decodingTimeUs;
2785a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGV("decoding time: %" PRId64 " and ctts offset time: %" PRId64,
2786000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                timestampUs, cttsOffsetTimeUs);
2787000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2788000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts box table if necessary
2789000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            currCttsOffsetTimeTicks =
2790000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL;
279111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) {
279211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
2793d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang                mSource->stop();
27949db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                mIsMalformed = true;
27959db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                break;
279611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
279711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2798c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 0) {
279943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // Force the first ctts table entry to have one single entry
280043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // so that we can do adjustment for the initial track start
280143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // time offset easily in writeCttsBox().
280243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
280343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                addOneCttsTableEntry(1, currCttsOffsetTimeTicks);
280443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                cttsSampleCount = 0;      // No sample in ctts box is pending
280543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            } else {
280643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) {
280743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
280843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
280943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    cttsSampleCount = 1;  // One sample in ctts box is pending
281043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                } else {
281143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    ++cttsSampleCount;
281243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                }
281343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            }
2814000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2815000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts time offset range
2816c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 0) {
2817000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2818000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2819000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            } else {
2820000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) {
2821000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2822000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) {
2823000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2824000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                }
2825000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            }
2826000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2827965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        }
2828872a481558350634a3fd5cb67939de288af00ecbJames Dong
2829de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        if (mOwner->isRealTimeRecording()) {
2830872a481558350634a3fd5cb67939de288af00ecbJames Dong            if (mIsAudio) {
2831872a481558350634a3fd5cb67939de288af00ecbJames Dong                updateDriftTime(meta_data);
2832e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
2833e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
2834872a481558350634a3fd5cb67939de288af00ecbJames Dong
283511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
283611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
2837d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            mSource->stop();
28389db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            mIsMalformed = true;
28399db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            break;
284011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        }
284111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2842a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("%s media time stamp: %" PRId64 " and previous paused duration %" PRId64,
284311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                trackName, timestampUs, previousPausedDurationUs);
2844c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong        if (timestampUs > mTrackDurationUs) {
2845c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong            mTrackDurationUs = timestampUs;
28463b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        }
28473b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber
28485a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // We need to use the time scale based ticks, rather than the
28495a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // timestamp itself to determine whether we have to use a new
28505a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // stts entry, since we may have rounding errors.
28515a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // The calculation is intended to reduce the accumulated
28525a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // rounding errors.
28535a217fba010e801c255503602bda4b86ac5a6ac9James Dong        currDurationTicks =
28545a217fba010e801c255503602bda4b86ac5a6ac9James Dong            ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
28555a217fba010e801c255503602bda4b86ac5a6ac9James Dong                (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
2856c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (currDurationTicks < 0ll) {
2857f85a83af8c6a98b46c394c32b90b09214a68f3e4Hangyu Kuang            ALOGE("do not support out of order frames (timestamp: %lld < last: %lld for %s track",
2858f85a83af8c6a98b46c394c32b90b09214a68f3e4Hangyu Kuang                    (long long)timestampUs, (long long)lastTimestampUs, trackName);
285911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
28600332fadec6e91c37fe39ab92b2c02922370bc853Hangyu Kuang            mSource->stop();
28619db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            mIsMalformed = true;
28629db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            break;
28638c460498c028888c533ab442be12b6d4b669b965James Dong        }
28648c460498c028888c533ab442be12b6d4b669b965James Dong
286585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // if the duration is different for this sample, see if it is close enough to the previous
286685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // duration that we can fudge it and use the same value, to avoid filling the stts table
286785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // with lots of near-identical entries.
286885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // "close enough" here means that the current duration needs to be adjusted by less
286985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // than 0.1 milliseconds
287085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) {
287185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL
287285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                    + (mTimeScale / 2)) / mTimeScale;
287385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            if (deltaUs > -100 && deltaUs < 100) {
287485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                // use previous ticks, and adjust timestamp as if it was actually that number
287585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                // of ticks
287685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                currDurationTicks = lastDurationTicks;
287785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                timestampUs += deltaUs;
287885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            }
287985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        }
2880c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStszTableEntries->add(htonl(sampleSize));
2881c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (mStszTableEntries->count() > 2) {
2882c059860c73678a202bfa33062723e8f82fb779d9James Dong
2883a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // Force the first sample to have its own stts entry so that
2884a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // we can adjust its value later to maintain the A/V sync.
2885c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) {
288679761ab096f57c3027fad9556c2bc436672d614eJames Dong                addOneSttsTableEntry(sampleCount, lastDurationTicks);
2887be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                sampleCount = 1;
2888be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
2889be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                ++sampleCount;
2890be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
2891965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2892be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
2893be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        if (mSamplesHaveSameSize) {
2894c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) {
2895be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSamplesHaveSameSize = false;
2896be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
28978644c14618d30d9e57a69df40ed939986ebf02c4James Dong            previousSampleSize = sampleSize;
2898be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
2899a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("%s timestampUs/lastTimestampUs: %" PRId64 "/%" PRId64,
290011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                trackName, timestampUs, lastTimestampUs);
29018644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastDurationUs = timestampUs - lastTimestampUs;
2902c059860c73678a202bfa33062723e8f82fb779d9James Dong        lastDurationTicks = currDurationTicks;
29038644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastTimestampUs = timestampUs;
290462a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang        timestampPair.second = timestampUs;
290562a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang        // Insert the timestamp into the mTimestampDebugHelper
290662a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang        if (mTimestampDebugHelper.size() >= kTimestampDebugCount) {
290762a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang            mTimestampDebugHelper.pop_front();
290862a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang        }
290962a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang        mTimestampDebugHelper.push_back(timestampPair);
291020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2911d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        if (isSync != 0) {
2912c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            addOneStssTableEntry(mStszTableEntries->count());
2913d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        }
2914d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
291593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (mTrackingProgressStatus) {
291693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            if (mPreviousTrackTimeUs <= 0) {
291793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong                mPreviousTrackTimeUs = mStartTimestampUs;
291893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            }
2919faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong            trackProgressStatus(timestampUs);
292093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
292143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        if (!hasMultipleTracks) {
292280f78b773f92048944a850efb7b60629643370cdPraveen Chavan            off64_t offset = (mIsAvc || mIsHevc) ? mOwner->addMultipleLengthPrefixedSamples_l(copy)
292358ae9c530247668f8af36e30d228c716c226b3d4James Dong                                 : mOwner->addSample_l(copy);
2924c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2925c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t count = (mOwner->use32BitFileOffset()
2926c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        ? mStcoTableEntries->count()
2927c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        : mCo64TableEntries->count());
2928c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2929c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (count == 0) {
29301f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                addChunkOffset(offset);
293158ae9c530247668f8af36e30d228c716c226b3d4James Dong            }
293258ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy->release();
293358ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy = NULL;
293458ae9c530247668f8af36e30d228c716c226b3d4James Dong            continue;
293558ae9c530247668f8af36e30d228c716c226b3d4James Dong        }
293613aec890216948b0c364f8f92792129d0335f506James Dong
293713aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.push_back(copy);
293813aec890216948b0c364f8f92792129d0335f506James Dong        if (interleaveDurationUs == 0) {
29391f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStscTableEntry(++nChunks, 1);
29401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            bufferChunk(timestampUs);
294113aec890216948b0c364f8f92792129d0335f506James Dong        } else {
294213aec890216948b0c364f8f92792129d0335f506James Dong            if (chunkTimestampUs == 0) {
294313aec890216948b0c364f8f92792129d0335f506James Dong                chunkTimestampUs = timestampUs;
294413aec890216948b0c364f8f92792129d0335f506James Dong            } else {
294543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                int64_t chunkDurationUs = timestampUs - chunkTimestampUs;
294643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                if (chunkDurationUs > interleaveDurationUs) {
294743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    if (chunkDurationUs > mMaxChunkDurationUs) {
294843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                        mMaxChunkDurationUs = chunkDurationUs;
294943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    }
295013aec890216948b0c364f8f92792129d0335f506James Dong                    ++nChunks;
295113aec890216948b0c364f8f92792129d0335f506James Dong                    if (nChunks == 1 ||  // First chunk
2952c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk != mChunkSamples.size()) {
2953c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk = mChunkSamples.size();
2954c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        addOneStscTableEntry(nChunks, lastSamplesPerChunk);
295513aec890216948b0c364f8f92792129d0335f506James Dong                    }
29561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                    bufferChunk(timestampUs);
295713aec890216948b0c364f8f92792129d0335f506James Dong                    chunkTimestampUs = timestampUs;
295813aec890216948b0c364f8f92792129d0335f506James Dong                }
295913aec890216948b0c364f8f92792129d0335f506James Dong            }
296013aec890216948b0c364f8f92792129d0335f506James Dong        }
296113aec890216948b0c364f8f92792129d0335f506James Dong
296220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
296325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
296445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (isTrackMalFormed()) {
296562a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang        dumpTimeStamps();
2966690f546b0ee548dbfe997df36418e5302ec2d786James Dong        err = ERROR_MALFORMED;
2967f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    }
296845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
2969bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    mOwner->trackProgressStatus(mTrackId, -1, err);
2970be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
297113aec890216948b0c364f8f92792129d0335f506James Dong    // Last chunk
297243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (!hasMultipleTracks) {
2973c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        addOneStscTableEntry(1, mStszTableEntries->count());
297458ae9c530247668f8af36e30d228c716c226b3d4James Dong    } else if (!mChunkSamples.empty()) {
29751f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        addOneStscTableEntry(++nChunks, mChunkSamples.size());
29761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        bufferChunk(timestampUs);
297713aec890216948b0c364f8f92792129d0335f506James Dong    }
297813aec890216948b0c364f8f92792129d0335f506James Dong
2979be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // We don't really know how long the last frame lasts, since
2980be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // there is no frame time after it, just repeat the previous
2981be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // frame's duration.
2982c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() == 1) {
29838f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        lastDurationUs = 0;  // A single sample's duration
298479761ab096f57c3027fad9556c2bc436672d614eJames Dong        lastDurationTicks = 0;
2985be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    } else {
2986be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        ++sampleCount;  // Count for the last sample
2987be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    }
2988a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2989c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() <= 2) {
299079761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(1, lastDurationTicks);
2991a472613aec322e25891abf5c77bf3f7e3c244920James Dong        if (sampleCount - 1 > 0) {
299279761ab096f57c3027fad9556c2bc436672d614eJames Dong            addOneSttsTableEntry(sampleCount - 1, lastDurationTicks);
2993a472613aec322e25891abf5c77bf3f7e3c244920James Dong        }
2994a472613aec322e25891abf5c77bf3f7e3c244920James Dong    } else {
299579761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(sampleCount, lastDurationTicks);
2996a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
2997a472613aec322e25891abf5c77bf3f7e3c244920James Dong
299843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // The last ctts box may not have been written yet, and this
299943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // is to make sure that we write out the last ctts box.
300043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) {
300143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        if (cttsSampleCount > 0) {
300243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
300343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        }
300443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    }
300543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong
3006c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs += lastDurationUs;
300725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
300843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
300943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    sendTrackSummary(hasMultipleTracks);
301043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
3011df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
301211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            count, nZeroLengthFrames, mStszTableEntries->count(), trackName);
3013872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (mIsAudio) {
3014a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Audio track drift time: %" PRId64 " us", mOwner->getDriftTimeUs());
3015872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
3016365a963142093a1cd8efdcea76b5f65096a5b115James Dong
301737187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err == ERROR_END_OF_STREAM) {
301837187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
301937187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
302037187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
3021365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
3022365a963142093a1cd8efdcea76b5f65096a5b115James Dong
302345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const {
30249db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang    if (mIsMalformed) {
30259db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang        return true;
30269db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang    }
30279db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang
3028c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() == 0) {                      // no samples written
302929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("The number of recorded samples is 0");
303045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
303145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
303245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
303325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (mIsVideo && mStssTableEntries->count() == 0) {  // no sync frames for video
303429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("There are no sync frames for video track");
303545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
303645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
303745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
303845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (OK != checkCodecSpecificData()) {         // no codec specific data
303945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
304045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
304145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
304245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    return false;
304345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong}
304445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
304543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) {
304607ec01904613a0bac32caaa8444b4690998faed7James Dong
304707ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send track summary only if test mode is enabled.
304807ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
304907ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
305007ec01904613a0bac32caaa8444b4690998faed7James Dong    }
305107ec01904613a0bac32caaa8444b4690998faed7James Dong
305243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int trackNum = (mTrackId << 28);
305343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
305443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
305543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE,
305625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang                    mIsAudio ? 0: 1);
305743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
305843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
305943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS,
306043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mTrackDurationUs / 1000);
306143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
306243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
306343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES,
3064c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    mStszTableEntries->count());
306543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
306686b7f47aa7482424cf8fd248f1315311919be3b0James Dong    {
306786b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // The system delay time excluding the requested initial delay that
306886b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // is used to eliminate the recording sound.
306986b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
307086b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
307186b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
307286b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
307386b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t initialDelayUs =
307486b7f47aa7482424cf8fd248f1315311919be3b0James Dong            mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs;
307586b7f47aa7482424cf8fd248f1315311919be3b0James Dong
307686b7f47aa7482424cf8fd248f1315311919be3b0James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
307770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS,
307870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    (initialDelayUs) / 1000);
307986b7f47aa7482424cf8fd248f1315311919be3b0James Dong    }
308070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
308107ec01904613a0bac32caaa8444b4690998faed7James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
308207ec01904613a0bac32caaa8444b4690998faed7James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES,
308307ec01904613a0bac32caaa8444b4690998faed7James Dong                    mMdatSizeBytes / 1024);
308407ec01904613a0bac32caaa8444b4690998faed7James Dong
308543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (hasMultipleTracks) {
308643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
308743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS,
308843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mMaxChunkDurationUs / 1000);
308970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
309070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
309170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        if (mStartTimestampUs != moovStartTimeUs) {
309270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
309370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
309470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS,
309570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    startTimeOffsetUs / 1000);
309670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        }
309743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    }
309843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong}
309943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
3100faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
3101a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("trackProgressStatus: %" PRId64 " us", timeUs);
3102c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
3103215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    if (mTrackEveryTimeDurationUs > 0 &&
3104215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
3105a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("Fire time tracking progress status at %" PRId64 " us", timeUs);
3106bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err);
310793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        mPreviousTrackTimeUs = timeUs;
310893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
310993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
311093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
3111faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus(
3112bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        size_t trackId, int64_t timeUs, status_t err) {
3113faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    Mutex::Autolock lock(mLock);
3114bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t trackNum = (trackId << 28);
3115faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
3116faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Error notification
3117faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Do not consider ERROR_END_OF_STREAM an error
3118faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (err != OK && err != ERROR_END_OF_STREAM) {
3119bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
3120bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL,
3121faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
3122faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
3123faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
3124faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
3125faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (timeUs == -1) {
3126faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send completion notification
3127bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
3128bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS,
3129faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
3130faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    } else {
3131faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send progress status
3132bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
3133bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME,
3134faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               timeUs / 1000);
3135faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
3136faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong}
3137faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
3138d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) {
3139a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("setDriftTimeUs: %" PRId64 " us", driftTimeUs);
3140e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
3141d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    mDriftTimeUs = driftTimeUs;
3142e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
3143e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
3144e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() {
3145a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("getDriftTimeUs: %" PRId64 " us", mDriftTimeUs);
3146e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
3147e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    return mDriftTimeUs;
3148e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
3149e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
3150de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghuibool MPEG4Writer::isRealTimeRecording() const {
3151de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    return mIsRealTimeRecording;
3152de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui}
3153de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
3154b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() {
3155b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    return mUse4ByteNalLength;
3156b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong}
3157b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
31581c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
31593856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk");
31601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
31611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Chunk chunk(this, timestampUs, mChunkSamples);
31621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mOwner->bufferChunk(chunk);
316313aec890216948b0c364f8f92792129d0335f506James Dong    mChunkSamples.clear();
316420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
316520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31663b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
31676a5c19cae5b1958af824f349a5c3778255ecd9c7Robert Shih    return mTrackDurationUs + getStartTimeOffsetScaledTimeUs();
316820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
316920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3170d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
3171d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return mEstimatedTrackSizeBytes;
3172d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
3173d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
3174690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const {
3175690f546b0ee548dbfe997df36418e5302ec2d786James Dong    const char *mime;
3176690f546b0ee548dbfe997df36418e5302ec2d786James Dong    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
3177690f546b0ee548dbfe997df36418e5302ec2d786James Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
3178690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
31799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime) ||
31809aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        !strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
3181690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (!mCodecSpecificData ||
3182690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize <= 0) {
318329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Missing codec specific data");
3184690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
3185690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
3186690f546b0ee548dbfe997df36418e5302ec2d786James Dong    } else {
3187690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (mCodecSpecificData ||
3188690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize > 0) {
318929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Unexepected codec specific data found");
3190690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
3191690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
3192690f546b0ee548dbfe997df36418e5302ec2d786James Dong    }
3193690f546b0ee548dbfe997df36418e5302ec2d786James Dong    return OK;
3194690f546b0ee548dbfe997df36418e5302ec2d786James Dong}
3195690f546b0ee548dbfe997df36418e5302ec2d786James Dong
319625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangconst char *MPEG4Writer::Track::getTrackType() const {
319725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    return mIsAudio ? "Audio" : (mIsVideo ? "Video" : "Metadata");
319825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang}
31998f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
320025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) {
3201efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
3202b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("trak");
3203b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeTkhdBox(now);
3204b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("mdia");
3205b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeMdhdBox(now);
3206b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeHdlrBox();
3207b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->beginBox("minf");
3208b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                if (mIsAudio) {
3209b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeSmhdBox();
321025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang                } else if (mIsVideo) {
3211b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeVmhdBox();
321225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang                } else {
321325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang                    writeNmhdBox();
3214b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                }
3215b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeDinfBox();
3216b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeStblBox(use32BitOffset);
3217b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->endBox();  // minf
3218b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->endBox();  // mdia
3219b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // trak
3220b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3221b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3222b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) {
3223b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stbl");
3224b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsd");
3225b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);               // version=0, flags=0
3226b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);               // entry count
3227b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
3228b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAudioFourCCBox();
322925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else if (mIsVideo) {
3230b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeVideoFourCCBox();
323125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else {
323225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        writeMetadataFourCCBox();
3233b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3234b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsd
3235b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeSttsBox();
323625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (mIsVideo) {
323725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        writeCttsBox();
3238b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeStssBox();
3239b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3240b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStszBox();
3241b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStscBox();
3242b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStcoBox(use32BitOffset);
3243b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stbl
3244b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3245b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
324625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeMetadataFourCCBox() {
324725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    const char *mime;
324825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    bool success = mMeta->findCString(kKeyMIMEType, &mime);
324925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    CHECK(success);
325025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    const char *fourcc = getFourCCForMime(mime);
325125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (fourcc == NULL) {
325225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        ALOGE("Unknown mime type '%s'.", mime);
325325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        TRESPASS();
325425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    }
325525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->beginBox(fourcc);    // TextMetaDataSampleEntry
325625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->writeCString(mime);  // metadata mime_format
325725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->endBox(); // mett
325825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang}
325925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang
3260b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() {
3261b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
3262b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
3263b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
32648b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    const char *fourcc = getFourCCForMime(mime);
32658b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (fourcc == NULL) {
326629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
326725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        TRESPASS();
3268b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3269b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
32708b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    mOwner->beginBox(fourcc);        // video format
3271b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3272b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3273b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // data ref index
3274b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
3275b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3276b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
3277b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
3278b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
3279b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3280b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t width, height;
3281b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeyWidth, &width);
3282b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = success && mMeta->findInt32(kKeyHeight, &height);
3283b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
3284b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3285b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(width);
3286b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(height);
3287b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // horiz resolution
3288b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // vert resolution
3289b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3290b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // frame count
3291c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo    mOwner->writeInt8(0);            // compressor string length
3292c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo    mOwner->write("                               ", 31);
3293b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x18);        // depth
3294b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(-1);          // predefined
3295b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3296b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
3297b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4vEsdsBox();
3298b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
3299b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeD263Box();
3300b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
3301b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAvccBox();
33029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
33039aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        writeHvccBox();
3304b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3305b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3306b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writePaspBox();
330758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    writeColrBox();
3308b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // mp4v, s263 or avc1
3309b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3310b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
331158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnarvoid MPEG4Writer::Track::writeColrBox() {
331258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    ColorAspects aspects;
331358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    memset(&aspects, 0, sizeof(aspects));
331458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    // TRICKY: using | instead of || because we want to execute all findInt32-s
331558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    if (mMeta->findInt32(kKeyColorPrimaries, (int32_t*)&aspects.mPrimaries)
331658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyTransferFunction, (int32_t*)&aspects.mTransfer)
331758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyColorMatrix, (int32_t*)&aspects.mMatrixCoeffs)
331858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyColorRange, (int32_t*)&aspects.mRange)) {
331958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        int32_t primaries, transfer, coeffs;
332058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        bool fullRange;
332158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        ColorUtils::convertCodecColorAspectsToIsoAspects(
332258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar                aspects, &primaries, &transfer, &coeffs, &fullRange);
332358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->beginBox("colr");
332458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeFourcc("nclx");
332558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(primaries);
332658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(transfer);
332758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(coeffs);
3328fffb0c8fbe16ac948619b85e1eea9e65a9daa0c9Pirama Arumuga Nainar        mOwner->writeInt8(int8_t(fullRange ? 0x80 : 0x0));
332958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->endBox(); // colr
333058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    }
333158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar}
333258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
3333b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() {
3334b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
3335b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
3336b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
33378b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    const char *fourcc = getFourCCForMime(mime);
33388b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (fourcc == NULL) {
333929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
334025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        TRESPASS();
3341b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3342b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3343b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(fourcc);        // audio format
3344b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3345b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3346b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x1);         // data ref index
3347b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3348b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3349b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t nChannels;
3350b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
3351b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(nChannels);   // channel count
3352b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(16);          // sample size
3353b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
3354b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3355b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3356b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t samplerate;
3357b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeySampleRate, &samplerate);
3358b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
3359b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(samplerate << 16);
3360b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
3361b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4aEsdsBox();
3362b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
3363b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong               !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
3364b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeDamrBox();
3365b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3366b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3367b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3368b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3369b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() {
3370b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
3371b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
3372b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_GT(mCodecSpecificDataSize, 0u);
3373b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3374b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Make sure all sizes encode to a single byte.
3375b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_LT(mCodecSpecificDataSize + 23, 128u);
3376b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3377b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);     // version=0, flags=0
3378b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);   // ES_DescrTag
3379b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
3380b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);// ES_ID
3381b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x00);
3382b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3383b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
3384b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
3385b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
3386b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x15);   // streamType AudioStream
3387b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3388b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x03);  // XXX
338946f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt8(0x00);   // buffer size 24-bit (0x300)
339046f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar
339196bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t avgBitrate = 0;
339246f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyBitRate, &avgBitrate);
339396bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t maxBitrate = 0;
339446f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate);
339546f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(maxBitrate);
339646f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(avgBitrate);
3397b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3398b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
3399b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
3400b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3401b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3402b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
3403b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
3404b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
3405b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
3406b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3407b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
3408b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3409b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
3410b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3411b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3412b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() {
3413b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
3414b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_GT(mCodecSpecificDataSize, 0u);
3415bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan
3416bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan    // Make sure all sizes encode to a single byte.
3417b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_LT(23 + mCodecSpecificDataSize, 128u);
3418bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan
3419b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
3420b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3421b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);    // version=0, flags=0
3422b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3423b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);  // ES_DescrTag
3424b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
3425b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);  // ES_ID
3426b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x1f);
3427b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3428b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
3429b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
3430b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
3431b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x11);  // streamType VisualStream
3432b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3433b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData[] = {
343446f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar        0x01, 0x77, 0x00, // buffer size 96000 bytes
3435b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3436b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData, sizeof(kData));
3437b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
343896bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t avgBitrate = 0;
343946f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyBitRate, &avgBitrate);
344096bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t maxBitrate = 0;
344146f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate);
344246f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(maxBitrate);
344346f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(avgBitrate);
344446f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar
3445b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
3446b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3447b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
3448b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3449b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3450b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
3451b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
3452b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
3453b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
3454b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3455b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
3456b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3457b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
3458b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3459b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3460efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeTkhdBox(uint32_t now) {
3461b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("tkhd");
3462b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Flags = 7 to indicate that the track is enabled, and
3463b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // part of the presentation
3464b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x07);          // version=0, flags=7
3465b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
3466b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
3467219f195159f93d627af2b243732e3f9020511a46James Dong    mOwner->writeInt32(mTrackId);      // track id starts with 1
3468b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
34698f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t trakDurationUs = getDurationUs();
3470b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mvhdTimeScale = mOwner->getTimeScale();
3471b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t tkhdDuration =
3472b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
3473b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
3474b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3475b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3476b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // layer
3477b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // alternate group
3478b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
3479b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // reserved
3480b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3481b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCompositionMatrix(mRotation);       // matrix
348220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
348325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (!mIsVideo) {
3484b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
3485b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
3486b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
3487b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        int32_t width, height;
3488467743d462773ada299148ed5a210479affd1f4cHangyu Kuang        bool success = mMeta->findInt32(kKeyDisplayWidth, &width);
3489467743d462773ada299148ed5a210479affd1f4cHangyu Kuang        success = success && mMeta->findInt32(kKeyDisplayHeight, &height);
3490467743d462773ada299148ed5a210479affd1f4cHangyu Kuang
3491467743d462773ada299148ed5a210479affd1f4cHangyu Kuang        // Use width/height if display width/height are not present.
3492467743d462773ada299148ed5a210479affd1f4cHangyu Kuang        if (!success) {
3493467743d462773ada299148ed5a210479affd1f4cHangyu Kuang            success = mMeta->findInt32(kKeyWidth, &width);
3494467743d462773ada299148ed5a210479affd1f4cHangyu Kuang            success = success && mMeta->findInt32(kKeyHeight, &height);
3495467743d462773ada299148ed5a210479affd1f4cHangyu Kuang        }
3496b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(success);
3497b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3498b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
3499b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
3500b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3501b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // tkhd
3502b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3503b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3504b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() {
3505b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("vmhd");
3506b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x01);        // version=0, flags=1
3507b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // graphics mode
3508b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // opcolor
3509b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
3510b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
3511b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3512b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3513b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3514b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() {
3515b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("smhd");
3516b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // version=0, flags=0
3517b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // balance
3518b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3519b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3520b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3521b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
352225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeNmhdBox() {
352325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->beginBox("nmhd");
352425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->writeInt32(0);           // version=0, flags=0
352525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->endBox();
352625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang}
352725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang
3528b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() {
3529b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("hdlr");
3530b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
3531b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // component type: should be mhlr
353225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->writeFourcc(mIsAudio ? "soun" : (mIsVideo ? "vide" : "meta"));  // component subtype
3533b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3534b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3535b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3536b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Removing "r" for the name string just makes the string 4 byte aligned
353725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->writeCString(mIsAudio ? "SoundHandle": (mIsVideo ? "VideoHandle" : "MetadHandle"));
3538b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3539b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3540b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3541efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeMdhdBox(uint32_t now) {
3542b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t trakDurationUs = getDurationUs();
35431d515f4b608f1e6592780365857855962c0da725xiahong.bao    int64_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
3544b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("mdhd");
35451d515f4b608f1e6592780365857855962c0da725xiahong.bao
35461d515f4b608f1e6592780365857855962c0da725xiahong.bao    if (mdhdDuration > UINT32_MAX) {
35471d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt32((1 << 24));            // version=1, flags=0
35481d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt64((int64_t)now);         // creation time
35491d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt64((int64_t)now);         // modification time
35501d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt32(mTimeScale);           // media timescale
35511d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt64(mdhdDuration);         // media timescale
35521d515f4b608f1e6592780365857855962c0da725xiahong.bao    } else {
35531d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt32(0);                      // version=0, flags=0
35541d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt32(now);                    // creation time
35551d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt32(now);                    // modification time
35561d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt32(mTimeScale);             // media timescale
35571d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt32((int32_t)mdhdDuration);  // use media timescale
35581d515f4b608f1e6592780365857855962c0da725xiahong.bao    }
3559b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Language follows the three letter standard ISO-639-2/T
3560b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 'e', 'n', 'g' for "English", for instance.
3561b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Each character is packed as the difference between its ASCII value and 0x60.
3562b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // For "English", these are 00101, 01110, 00111.
3563b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // XXX: Where is the padding bit located: 0x15C7?
3564decc50efede28c5d73137c30d1a95d72dd405555David Yeh    const char *lang = NULL;
3565decc50efede28c5d73137c30d1a95d72dd405555David Yeh    int16_t langCode = 0;
3566decc50efede28c5d73137c30d1a95d72dd405555David Yeh    if (mMeta->findCString(kKeyMediaLanguage, &lang) && lang && strnlen(lang, 3) > 2) {
3567decc50efede28c5d73137c30d1a95d72dd405555David Yeh        langCode = ((lang[0] & 0x1f) << 10) | ((lang[1] & 0x1f) << 5) | (lang[2] & 0x1f);
3568decc50efede28c5d73137c30d1a95d72dd405555David Yeh    }
3569decc50efede28c5d73137c30d1a95d72dd405555David Yeh    mOwner->writeInt16(langCode);      // language code
3570b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // predefined
3571b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3572b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3573b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3574b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() {
3575b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 3gpp2 Spec AMRSampleEntry fields
3576b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("damr");
3577b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString("   ");  // vendor: 4 bytes
3578b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // decoder version
3579b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x83FF);   // mode set: all enabled
3580b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // mode change period
3581b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(1);         // frames per sample
3582b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3583b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3584b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3585b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() {
3586b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // The table index here refers to the sample description index
3587b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // in the sample table entries.
3588b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("url ");
3589b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
3590b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // url
3591b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3592b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3593b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() {
3594b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dref");
3595b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3596b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // entry count (either url or urn)
3597b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeUrlBox();
3598b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dref
3599b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3600b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3601b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() {
3602b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dinf");
3603b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeDrefBox();
3604b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dinf
3605b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3606b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3607b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() {
3608b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
3609b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_GE(mCodecSpecificDataSize, 5u);
3610b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3611b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Patch avcc's lengthSize field to match the number
3612b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // of bytes we use to indicate the size of a nal unit.
3613b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
3614b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
3615b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("avcC");
3616b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3617b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // avcC
3618b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3619b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
36209aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
36219aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimvoid MPEG4Writer::Track::writeHvccBox() {
36229aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    CHECK(mCodecSpecificData);
3623b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_GE(mCodecSpecificDataSize, 5u);
36249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
36259aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Patch avcc's lengthSize field to match the number
36269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // of bytes we use to indicate the size of a nal unit.
36279aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
36289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ptr[21] = (ptr[21] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
36299aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->beginBox("hvcC");
36309aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
36319aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->endBox();  // hvcC
36329aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
36339aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
3634b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() {
3635b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("d263");
3636b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // vendor
3637b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // decoder version
3638b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(10);  // level: 10
3639b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // profile: 0
3640b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // d263
3641b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3642b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3643b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square
3644b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() {
3645b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("pasp");
3646b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // hspacing
3647b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // vspacing
3648b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // pasp
3649b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3650b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
36516a5c19cae5b1958af824f349a5c3778255ecd9c7Robert Shihint64_t MPEG4Writer::Track::getStartTimeOffsetScaledTimeUs() const {
3652a472613aec322e25891abf5c77bf3f7e3c244920James Dong    int64_t trackStartTimeOffsetUs = 0;
3653b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
3654a9292fe1c19e8a9b43398ba3d69284c215d7589fRobert Shih    if (mStartTimestampUs != -1 && mStartTimestampUs != moovStartTimeUs) {
365543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_GT(mStartTimestampUs, moovStartTimeUs);
3656b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
3657b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
36586a5c19cae5b1958af824f349a5c3778255ecd9c7Robert Shih    return trackStartTimeOffsetUs;
36596a5c19cae5b1958af824f349a5c3778255ecd9c7Robert Shih}
36606a5c19cae5b1958af824f349a5c3778255ecd9c7Robert Shih
36616a5c19cae5b1958af824f349a5c3778255ecd9c7Robert Shihint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const {
36626a5c19cae5b1958af824f349a5c3778255ecd9c7Robert Shih    return (getStartTimeOffsetScaledTimeUs() *  mTimeScale + 500000LL) / 1000000LL;
3663000e18370baae60ffd9f25b509501dd8c26deabfJames Dong}
3664000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
3665000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() {
3666000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->beginBox("stts");
3667000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3668c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t duration;
3669c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    CHECK(mSttsTableEntries->get(duration, 1));
3670c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    duration = htonl(duration);  // Back to host byte order
3671c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1);
3672c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->write(mOwner);
3673b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stts
3674b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
367520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3676965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() {
3677000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    // There is no B frame at all
3678000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) {
3679000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        return;
3680000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    }
3681000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
3682965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    // Do not write ctts box when there is no need to have it.
3683c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mCttsTableEntries->count() == 0) {
3684965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
3685965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
3686965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3687a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("ctts box has %d entries with range [%" PRId64 ", %" PRId64 "]",
3688c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs);
3689965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3690965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->beginBox("ctts");
3691000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
36920d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka    int64_t delta = mMinCttsOffsetTimeUs - getStartTimeOffsetScaledTime();
3693c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    mCttsTableEntries->adjustEntries([delta](size_t /* ix */, uint32_t (&value)[2]) {
3694c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        // entries are <count, ctts> pairs; adjust only ctts
3695c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        uint32_t duration = htonl(value[1]); // back to host byte order
36960d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka        // Prevent overflow and underflow
36970d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka        if (delta > duration) {
36980d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka            duration = 0;
36990d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka        } else if (delta < 0 && UINT32_MAX + delta < duration) {
37000d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka            duration = UINT32_MAX;
37010d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka        } else {
37020d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka            duration -= delta;
37030d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka        }
37040d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka        value[1] = htonl(duration);
3705c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    });
3706c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->write(mOwner);
3707965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->endBox();  // ctts
3708965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
3709965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3710b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() {
3711b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stss");
3712b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3713c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->write(mOwner);
3714b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stss
3715b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
371625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
3717b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() {
3718b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsz");
3719b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3720c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mOwner->writeInt32(0);
3721c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries->write(mOwner);
3722b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsz
3723b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
372420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3725b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() {
3726b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsc");
3727b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3728c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries->write(mOwner);
3729b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsc
3730b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
373120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3732b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) {
3733b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(use32BitOffset? "stco": "co64");
3734b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3735c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (use32BitOffset) {
3736c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->write(mOwner);
3737c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
3738c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->write(mOwner);
3739b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3740b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stco or co64
374120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
374220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
374307b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() {
374407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("udta");
374507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeGeoDataBox();
374607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
374707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
374807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
3749e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeHdlr() {
3750e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("hdlr");
3751e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Version, Flags
3752e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Predefined
3753e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeFourcc("mdta");
3754e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[0]
3755e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[1]
3756e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[2]
3757e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt8(0);  // Name (empty)
3758e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3759e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3760e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3761e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeKeys() {
3762e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3763e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3764e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("keys");
3765e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0);     // Version, Flags
3766e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(count); // Entry_count
3767e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    for (size_t i = 0; i < count; i++) {
3768e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        AMessage::Type type;
3769e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        const char *key = mMetaKeys->getEntryNameAt(i, &type);
3770e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        size_t n = strlen(key);
3771e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writeInt32(n + 8);
3772e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writeFourcc("mdta");
3773e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        write(key, n); // write without the \0
3774e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3775e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3776e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3777e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3778e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeIlst() {
3779e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3780e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3781e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("ilst");
3782e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    for (size_t i = 0; i < count; i++) {
3783e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        beginBox(i + 1); // key id (1-based)
3784e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        beginBox("data");
3785e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        AMessage::Type type;
3786e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        const char *key = mMetaKeys->getEntryNameAt(i, &type);
3787e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        switch (type) {
37887c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            case AMessage::kTypeString:
37897c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            {
37907c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                AString val;
37917c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                CHECK(mMetaKeys->findString(key, &val));
37927c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(1); // type = UTF8
37937c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0); // default country/language
37947c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                write(val.c_str(), strlen(val.c_str())); // write without \0
37957c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                break;
37967c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            }
37977c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
3798e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            case AMessage::kTypeFloat:
3799e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3800e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                float val;
3801e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                CHECK(mMetaKeys->findFloat(key, &val));
38027c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(23); // type = float32
38037c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3804e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(*reinterpret_cast<int32_t *>(&val));
3805e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3806e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3807e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3808e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            case AMessage::kTypeInt32:
3809e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3810e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                int32_t val;
3811e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                CHECK(mMetaKeys->findInt32(key, &val));
38127c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(67); // type = signed int32
38137c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3814e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(val);
3815e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3816e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3817e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3818e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            default:
3819e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3820e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                ALOGW("Unsupported key type, writing 0 instead");
38217c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(77); // type = unsigned int32
38227c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3823e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(0);
3824e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3825e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3826e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        }
3827e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        endBox(); // data
3828e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        endBox(); // key id
3829e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3830e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox(); // ilst
3831e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3832e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3833e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeMetaBox() {
3834e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3835e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    if (count == 0) {
3836e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        return;
3837e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3838e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3839e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("meta");
3840e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeHdlr();
3841e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeKeys();
3842e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeIlst();
3843e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3844e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3845e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
384607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
384707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
384807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
384907b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() {
385007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("\xA9xyz");
385107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    /*
385207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * For historical reasons, any user data start
385307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * with "\0xA9", must be followed by its assoicated
385407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * language code.
3855432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x0012: text string length
3856432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x15c7: lang (locale) code: en
385707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     */
385807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt32(0x001215c7);
385907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLatitude(mLatitudex10000);
386007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLongitude(mLongitudex10000);
386107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt8(0x2F);
386207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
386307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
386407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
386520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
3866