MPEG4Writer.cpp revision 5ba45163872df39427cf18b3d640e1cd26c228bb
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);
115230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    int64_t getMinCttsOffsetTimeUs();
1161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void bufferChunk(int64_t timestampUs);
1171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAvc() const { return mIsAvc; }
1189aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    bool isHevc() const { return mIsHevc; }
1191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAudio() const { return mIsAudio; }
1201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isMPEG4() const { return mIsMPEG4; }
121c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    void addChunkOffset(off64_t offset);
12270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int32_t getTrackId() const { return mTrackId; }
123dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    status_t dump(int fd, const Vector<String16>& args) const;
1248b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    static const char *getFourCCForMime(const char *mime);
12525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    const char *getTrackType() const;
126fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    void resetInternal();
12720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
129000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    enum {
13005f4cd73b9655a6d4aad9fa215d6fc13c40633aaZhijun He        kMaxCttsOffsetTimeUs = 1000000LL,  // 1 second
1318c460498c028888c533ab442be12b6d4b669b965James Dong        kSampleArraySize = 1000,
132000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    };
133000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
134c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    // A helper class to handle faster write box with table entries
135c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    template<class TYPE, unsigned ENTRY_SIZE>
136c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    // ENTRY_SIZE: # of values in each entry
137c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    struct ListTableEntries {
138c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        static_assert(ENTRY_SIZE > 0, "ENTRY_SIZE must be positive");
139c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        ListTableEntries(uint32_t elementCapacity)
140c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            : mElementCapacity(elementCapacity),
141c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mTotalNumTableEntries(0),
142c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mNumValuesInCurrEntry(0),
143c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCurrTableEntriesElement(NULL) {
144b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross            CHECK_GT(mElementCapacity, 0u);
1452177f21c1ae5bf5cb8c1113a1adbe1fd7db34206Wei Jia            // Ensure no integer overflow on allocation in add().
146c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            CHECK_LT(ENTRY_SIZE, UINT32_MAX / mElementCapacity);
147c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
148c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
149c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Free the allocated memory.
150c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        ~ListTableEntries() {
151c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (!mTableEntryList.empty()) {
152c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                typename List<TYPE *>::iterator it = mTableEntryList.begin();
153c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                delete[] (*it);
154c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.erase(it);
155c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
156c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
157c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
158c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Replace the value at the given position by the given value.
159c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // There must be an existing value at the given position.
160c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order
161c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
162c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void set(const TYPE& value, uint32_t pos) {
163c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            CHECK_LT(pos, mTotalNumTableEntries * ENTRY_SIZE);
164c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
165c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            typename List<TYPE *>::iterator it = mTableEntryList.begin();
166c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            uint32_t iterations = (pos / (mElementCapacity * ENTRY_SIZE));
167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (it != mTableEntryList.end() && iterations > 0) {
168c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++it;
169c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                --iterations;
170c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
171c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK(it != mTableEntryList.end());
172b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross            CHECK_EQ(iterations, 0u);
173c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
174c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            (*it)[(pos % (mElementCapacity * ENTRY_SIZE))] = value;
175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
176c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
177c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Get the value at the given position by the given value.
178c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value the retrieved value at the position in network byte order.
179c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
180c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @return true if a value is found.
181c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        bool get(TYPE& value, uint32_t pos) const {
182c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            if (pos >= mTotalNumTableEntries * ENTRY_SIZE) {
183c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                return false;
184c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
186c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            typename List<TYPE *>::iterator it = mTableEntryList.begin();
187c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            uint32_t iterations = (pos / (mElementCapacity * ENTRY_SIZE));
188c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (it != mTableEntryList.end() && iterations > 0) {
189c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++it;
190c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                --iterations;
191c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
192c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK(it != mTableEntryList.end());
193b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross            CHECK_EQ(iterations, 0u);
194c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
195c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            value = (*it)[(pos % (mElementCapacity * ENTRY_SIZE))];
196c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            return true;
197c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
198c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
199c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        // adjusts all values by |adjust(value)|
200c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        void adjustEntries(
201c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                std::function<void(size_t /* ix */, TYPE(& /* entry */)[ENTRY_SIZE])> update) {
202c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            size_t nEntries = mTotalNumTableEntries + mNumValuesInCurrEntry / ENTRY_SIZE;
203c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            size_t ix = 0;
204c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            for (TYPE *entryArray : mTableEntryList) {
205c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                size_t num = std::min(nEntries, (size_t)mElementCapacity);
206c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                for (size_t i = 0; i < num; ++i) {
207c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                    update(ix++, (TYPE(&)[ENTRY_SIZE])(*entryArray));
208c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                    entryArray += ENTRY_SIZE;
209c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                }
210c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                nEntries -= num;
211c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            }
212c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        }
213c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar
214c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Store a single value.
215c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order.
216c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void add(const TYPE& value) {
217c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_LT(mNumValuesInCurrEntry, mElementCapacity);
218c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries % mElementCapacity;
219c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            uint32_t nValues  = mNumValuesInCurrEntry % ENTRY_SIZE;
220c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (nEntries == 0 && nValues == 0) {
221c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                mCurrTableEntriesElement = new TYPE[ENTRY_SIZE * mElementCapacity];
222c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                CHECK(mCurrTableEntriesElement != NULL);
223c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.push_back(mCurrTableEntriesElement);
224c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
225c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
226c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            uint32_t pos = nEntries * ENTRY_SIZE + nValues;
227c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCurrTableEntriesElement[pos] = value;
228c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
229c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            ++mNumValuesInCurrEntry;
230c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            if ((mNumValuesInCurrEntry % ENTRY_SIZE) == 0) {
231c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++mTotalNumTableEntries;
232c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mNumValuesInCurrEntry = 0;
233c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
234c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
235c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
236c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Write out the table entries:
237c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 1. the number of entries goes first
238c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 2. followed by the values in the table enties in order
239c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg writer the writer to actual write to the storage
240c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void write(MPEG4Writer *writer) const {
241b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross            CHECK_EQ(mNumValuesInCurrEntry % ENTRY_SIZE, 0u);
242c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries;
243c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            writer->writeInt32(nEntries);
244c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            for (typename List<TYPE *>::iterator it = mTableEntryList.begin();
245c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                it != mTableEntryList.end(); ++it) {
246b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross                CHECK_GT(nEntries, 0u);
247c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                if (nEntries >= mElementCapacity) {
248c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                    writer->write(*it, sizeof(TYPE) * ENTRY_SIZE, mElementCapacity);
249c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    nEntries -= mElementCapacity;
250c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                } else {
251c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                    writer->write(*it, sizeof(TYPE) * ENTRY_SIZE, nEntries);
252c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    break;
253c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                }
254c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
255c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
256c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
257c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Return the number of entries in the table.
258c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t count() const { return mTotalNumTableEntries; }
259c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
260c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    private:
261c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mElementCapacity;  // # entries in an element
262c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mTotalNumTableEntries;
263c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        uint32_t         mNumValuesInCurrEntry;  // up to ENTRY_SIZE
264c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        TYPE             *mCurrTableEntriesElement;
265c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mutable List<TYPE *>     mTableEntryList;
266c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
267c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries);
268c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    };
269c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
270c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
271c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
27220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Writer *mOwner;
27320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mMeta;
274b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen    sp<IMediaSource> mSource;
27520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    volatile bool mDone;
276a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mPaused;
277a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mResumed;
278eaae38445a340c4857c1c5569475879a728e63b7James Dong    volatile bool mStarted;
2791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAvc;
2809aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    bool mIsHevc;
2811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAudio;
28225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    bool mIsVideo;
2831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsMPEG4;
284fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    bool mGotStartKeyFrame;
2859db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang    bool mIsMalformed;
286bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t mTrackId;
287c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    int64_t mTrackDurationUs;
28843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int64_t mMaxChunkDurationUs;
289826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar    int64_t mLastDecodingTimeUs;
290e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
291d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t mEstimatedTrackSizeBytes;
2921f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t mMdatSizeBytes;
2938f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mTimeScale;
29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_t mThread;
29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
297be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
29813aec890216948b0c364f8f92792129d0335f506James Dong    List<MediaBuffer *> mChunkSamples;
2991f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
300c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    bool                mSamplesHaveSameSize;
301c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 1> *mStszTableEntries;
302be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
303c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 1> *mStcoTableEntries;
304c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<off64_t, 1> *mCo64TableEntries;
305c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 3> *mStscTableEntries;
306c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 1> *mStssTableEntries;
307c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 2> *mSttsTableEntries;
308c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 2> *mCttsTableEntries;
309965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
310000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMinCttsOffsetTimeUs;
311230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    int64_t mMinCttsOffsetTicks;
312230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    int64_t mMaxCttsOffsetTicks;
313965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
314dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang    // Save the last 10 frames' timestamp and frame type for debug.
315dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang    struct TimestampDebugHelperEntry {
316dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang        int64_t pts;
317dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang        int64_t dts;
318dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang        std::string frameType;
319dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang    };
320dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang
321dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang    std::list<TimestampDebugHelperEntry> mTimestampDebugHelper;
32262a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang
3233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Sequence parameter set or picture parameter set
3243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    struct AVCParamSet {
3253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        AVCParamSet(uint16_t length, const uint8_t *data)
3263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            : mLength(length), mData(data) {}
3273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
3283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t mLength;
3293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *mData;
3303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    };
3313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mSeqParamSets;
3323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mPicParamSets;
3333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileIdc;
3343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileCompatible;
3353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mLevelIdc;
3363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
33720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *mCodecSpecificData;
33820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t mCodecSpecificDataSize;
339548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    bool mGotAllCodecSpecificData;
34093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    bool mTrackingProgressStatus;
34120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
34225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool mReachedEOS;
3433c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    int64_t mStartTimestampUs;
34470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mStartTimeRealUs;
34570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mFirstSampleTimeRealUs;
34693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mPreviousTrackTimeUs;
34793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mTrackEveryTimeDurationUs;
34825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
349872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Update the audio track's drift information.
350872a481558350634a3fd5cb67939de288af00ecbJames Dong    void updateDriftTime(const sp<MetaData>& meta);
351872a481558350634a3fd5cb67939de288af00ecbJames Dong
35262a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang    void dumpTimeStamps();
35362a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang
354230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    int64_t getStartTimeOffsetTimeUs() const;
355000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int32_t getStartTimeOffsetScaledTime() const;
356000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static void *ThreadWrapper(void *me);
35837187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t threadEntry();
35920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *parseParamSet(
3613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen);
3623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
3639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t copyCodecSpecificData(const uint8_t *data, size_t size, size_t minLength = 0);
3649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
365b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size);
366b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size);
367b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size);
368215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong
3699aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t makeHEVCCodecSpecificData(const uint8_t *data, size_t size);
3709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t copyHEVCCodecSpecificData(const uint8_t *data, size_t size);
3719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t parseHEVCCodecSpecificData(
3729aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            const uint8_t *data, size_t size, HevcParameterSets &paramSets);
3739aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
374215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    // Track authoring progress status
375faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    void trackProgressStatus(int64_t timeUs, status_t err = OK);
37693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    void initTrackingProgressStatus(MetaData *params);
37703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
37819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    void getCodecSpecificDataFromInputFormatIfPossible();
37919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
380c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Determine the track time scale
381c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If it is an audio track, try to use the sampling rate as
382c059860c73678a202bfa33062723e8f82fb779d9James Dong    // the time scale; however, if user chooses the overwrite
383c059860c73678a202bfa33062723e8f82fb779d9James Dong    // value, the user-supplied time scale will be used.
384c059860c73678a202bfa33062723e8f82fb779d9James Dong    void setTimeScale();
385c059860c73678a202bfa33062723e8f82fb779d9James Dong
386690f546b0ee548dbfe997df36418e5302ec2d786James Dong    // Simple validation on the codec specific data
387690f546b0ee548dbfe997df36418e5302ec2d786James Dong    status_t checkCodecSpecificData() const;
38813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t mRotation;
389690f546b0ee548dbfe997df36418e5302ec2d786James Dong
3901f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void updateTrackSizeEstimate();
3911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStscTableEntry(size_t chunkId, size_t sampleId);
3921f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStssTableEntry(size_t sampleId);
39379761ab096f57c3027fad9556c2bc436672d614eJames Dong
39479761ab096f57c3027fad9556c2bc436672d614eJames Dong    // Duration is time scale based
39579761ab096f57c3027fad9556c2bc436672d614eJames Dong    void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
396965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
39745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
39845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    bool isTrackMalFormed() const;
39943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    void sendTrackSummary(bool hasMultipleTracks);
4001f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
401b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Write the boxes
402b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStcoBox(bool use32BitOffset);
403b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStscBox();
404b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStszBox();
405b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStssBox();
406b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSttsBox();
407965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void writeCttsBox();
408b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeD263Box();
409b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writePaspBox();
410b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAvccBox();
4119aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    void writeHvccBox();
412b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeUrlBox();
413b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDrefBox();
414b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDinfBox();
415b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDamrBox();
416efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeMdhdBox(uint32_t now);
417b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSmhdBox();
418b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVmhdBox();
41925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    void writeNmhdBox();
420b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeHdlrBox();
421efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeTkhdBox(uint32_t now);
42258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    void writeColrBox();
423b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4aEsdsBox();
424b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4vEsdsBox();
425b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAudioFourCCBox();
426b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVideoFourCCBox();
42725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    void writeMetadataFourCCBox();
428b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStblBox(bool use32BitOffset);
429b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
43020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track(const Track &);
43120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track &operator=(const Track &);
43220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
43320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
434fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu KuangMPEG4Writer::MPEG4Writer(int fd) {
4355ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    initInternal(fd, true /*isFirstSession*/);
43630ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
43730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
43820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
4398bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong    reset();
44020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4411f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    while (!mTracks.empty()) {
4421f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        List<Track *>::iterator it = mTracks.begin();
44320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
4441f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        (*it) = NULL;
4451f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mTracks.erase(it);
44620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
44720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
448fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
449fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mNextFd != -1) {
450fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        close(mNextFd);
451fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
452fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
453fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
4545ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuangvoid MPEG4Writer::initInternal(int fd, bool isFirstSession) {
455fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGV("initInternal");
4568fdb3fde346b446ad3b04dafa65a6844da672e23Hangyu Kuang    mFd = dup(fd);
457fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mNextFd = -1;
458fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mInitCheck = mFd < 0? NO_INIT: OK;
4595ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang
4605ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    mInterleaveDurationUs = 1000000;
4615ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang
4625ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    mStartTimestampUs = -1ll;
4635ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    mStartTimeOffsetMs = -1;
464fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mPaused = false;
465fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mStarted = false;
466fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mWriterThreadStarted = false;
467fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mSendNotify = false;
4685ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang
4695ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    // Reset following variables for all the sessions and they will be
4705ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    // initialized in start(MetaData *param).
4715ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    mIsRealTimeRecording = true;
4725ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    mUse4ByteNalLength = true;
4735ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    mUse32BitOffset = true;
474fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mOffset = 0;
475fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mMdatOffset = 0;
476fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mMoovBoxBuffer = NULL;
477fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mMoovBoxBufferOffset = 0;
478fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mWriteMoovBoxToMemory = false;
479fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mFreeBoxOffset = 0;
480fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mStreamableFile = false;
481fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mEstimatedMoovBoxSize = 0;
482fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mTimeScale = -1;
4835ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang
4845ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    // Following variables only need to be set for the first recording session.
4855ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    // And they will stay the same for all the recording sessions.
4865ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    if (isFirstSession) {
4875ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang        mMoovExtraSize = 0;
4885ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang        mMetaKeys = new AMessage();
4895ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang        addDeviceMeta();
4905ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang        mLatitudex10000 = 0;
4915ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang        mLongitudex10000 = 0;
4925ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang        mAreGeoTagsAvailable = false;
4935ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang        mSwitchPending = false;
4945ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang        mIsFileSizeLimitExplicitlyRequested = false;
4955ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    }
4965ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang
497fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    // Verify mFd is seekable
498fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    off64_t off = lseek64(mFd, 0, SEEK_SET);
499fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (off < 0) {
500fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        ALOGE("cannot seek mFd: %s (%d) %lld", strerror(errno), errno, (long long)mFd);
501fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        release();
502fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
503fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    for (List<Track *>::iterator it = mTracks.begin();
504fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         it != mTracks.end(); ++it) {
505fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        (*it)->resetInternal();
506fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
50720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
50820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
509dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump(
510dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) {
511dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
512dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
513dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
514dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "   MPEG4Writer %p\n", this);
515dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
516dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     mStarted: %s\n", mStarted? "true": "false");
517dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
518dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
519dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    for (List<Track *>::iterator it = mTracks.begin();
520dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong         it != mTracks.end(); ++it) {
521dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        (*it)->dump(fd, args);
522dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    }
523dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
524dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
525dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
526dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump(
52784333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        int fd, const Vector<String16>& /* args */) const {
528dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
529dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
530dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
53125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    snprintf(buffer, SIZE, "     %s track\n", getTrackType());
532dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
533dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "       reached EOS: %s\n",
534dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong            mReachedEOS? "true": "false");
535dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
536c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    snprintf(buffer, SIZE, "       frames encoded : %d\n", mStszTableEntries->count());
53713210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
538377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    snprintf(buffer, SIZE, "       duration encoded : %" PRId64 " us\n", mTrackDurationUs);
53913210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
540dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
541dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
542dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
543dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
5448b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan// static
5458b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavanconst char *MPEG4Writer::Track::getFourCCForMime(const char *mime) {
5468b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (mime == NULL) {
5478b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        return NULL;
5488b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    }
5498b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (!strncasecmp(mime, "audio/", 6)) {
5508b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
5518b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "samr";
5528b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
5538b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "sawb";
5548b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
5558b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "mp4a";
5568b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        }
5578b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    } else if (!strncasecmp(mime, "video/", 6)) {
5588b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
5598b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "mp4v";
5608b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
5618b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "s263";
5628b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
5638b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "avc1";
5649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
5659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return "hvc1";
5668b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        }
56725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else if (!strncasecmp(mime, "application/", 12)) {
56825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        return "mett";
5698b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    } else {
57025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        ALOGE("Track (%s) other than video/audio/metadata is not supported", mime);
5718b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    }
5728b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    return NULL;
5738b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan}
5748b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan
575b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissenstatus_t MPEG4Writer::addSource(const sp<IMediaSource> &source) {
576bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    Mutex::Autolock l(mLock);
577bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    if (mStarted) {
57829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Attempt to add source AFTER recording is started");
579bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        return UNKNOWN_ERROR;
580bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    }
581acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
582acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    CHECK(source.get() != NULL);
583acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
584acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    const char *mime;
585acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    source->getFormat()->findCString(kKeyMIMEType, &mime);
586acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
58725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (Track::getFourCCForMime(mime) == NULL) {
58825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        ALOGE("Unsupported mime '%s'", mime);
58925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        return ERROR_UNSUPPORTED;
59025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    }
59125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang
59225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    // This is a metadata track or the first track of either audio or video
593acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // Go ahead to add the track.
594219f195159f93d627af2b243732e3f9020511a46James Dong    Track *track = new Track(this, source, 1 + mTracks.size());
59520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
5962dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
5972dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
59820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
59920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
60093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) {
601acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    if (mTracks.empty()) {
602acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        ALOGE("No source added");
603acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return INVALID_OPERATION;
604acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
605acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
606a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
607a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
60893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        status_t err = (*it)->start(params);
609a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
610a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (err != OK) {
611a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            for (List<Track *>::iterator it2 = mTracks.begin();
612a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                 it2 != it; ++it2) {
613a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                (*it2)->stop();
614a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            }
615a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
616a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            return err;
617a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
618a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
619a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
620a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
621a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
6227c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangvoid MPEG4Writer::addDeviceMeta() {
6237c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // add device info and estimate space in 'moov'
6247c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    char val[PROPERTY_VALUE_MAX];
6257c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    size_t n;
6267c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // meta size is estimated by adding up the following:
6277c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // - meta header structures, which occur only once (total 66 bytes)
6287c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // - size for each key, which consists of a fixed header (32 bytes),
6297c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    //   plus key length and data length.
6307c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += 66;
6317c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.build.version.release", val, NULL)
6327c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
6337c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Version, val, n + 1);
6347c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Version) + n + 32;
6357c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
636da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang
637da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang    if (property_get_bool("media.recorder.show_manufacturer_and_model", false)) {
638da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang        if (property_get("ro.product.manufacturer", val, NULL)
639da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang                && (n = strlen(val)) > 0) {
640da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang            mMetaKeys->setString(kMetaKey_Manufacturer, val, n + 1);
641da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang            mMoovExtraSize += sizeof(kMetaKey_Manufacturer) + n + 32;
642da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang        }
643da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang        if (property_get("ro.product.model", val, NULL)
644da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang                && (n = strlen(val)) > 0) {
645da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang            mMetaKeys->setString(kMetaKey_Model, val, n + 1);
646da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang            mMoovExtraSize += sizeof(kMetaKey_Model) + n + 32;
647da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang        }
6487c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
649da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang#ifdef SHOW_MODEL_BUILD
6507c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.build.display.id", val, NULL)
6517c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
6527c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Build, val, n + 1);
6537c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Build) + n + 32;
6547c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
6557c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#endif
6567c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang}
6577c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
6582dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
6592dec2b5be2056c6d9428897dc672185872d30d17James Dong    // This implementation is highly experimental/heurisitic.
6602dec2b5be2056c6d9428897dc672185872d30d17James Dong    //
6612dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Statistical analysis shows that metadata usually accounts
6622dec2b5be2056c6d9428897dc672185872d30d17James Dong    // for a small portion of the total file size, usually < 0.6%.
6632dec2b5be2056c6d9428897dc672185872d30d17James Dong
66478a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2,
6652dec2b5be2056c6d9428897dc672185872d30d17James Dong    // where 1MB is the common file size limit for MMS application.
66678a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MAX _MOOV_BOX_SIZE value is based on about 3
6672dec2b5be2056c6d9428897dc672185872d30d17James Dong    // minute video recording with a bit rate about 3 Mbps, because
6682dec2b5be2056c6d9428897dc672185872d30d17James Dong    // statistics also show that most of the video captured are going
6692dec2b5be2056c6d9428897dc672185872d30d17James Dong    // to be less than 3 minutes.
6702dec2b5be2056c6d9428897dc672185872d30d17James Dong
6712dec2b5be2056c6d9428897dc672185872d30d17James Dong    // If the estimation is wrong, we will pay the price of wasting
6722dec2b5be2056c6d9428897dc672185872d30d17James Dong    // some reserved space. This should not happen so often statistically.
6732dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int32_t factor = mUse32BitOffset? 1: 2;
67478a1a286f736888ae7af8860b2c424af0d978848James Dong    static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024;  // 3 KB
6752dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
6762dec2b5be2056c6d9428897dc672185872d30d17James Dong    int64_t size = MIN_MOOV_BOX_SIZE;
6772dec2b5be2056c6d9428897dc672185872d30d17James Dong
67878a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file size limit is set
679a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
68078a1a286f736888ae7af8860b2c424af0d978848James Dong        size = mMaxFileSizeLimitBytes * 6 / 1000;
68178a1a286f736888ae7af8860b2c424af0d978848James Dong    }
68278a1a286f736888ae7af8860b2c424af0d978848James Dong
68378a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file duration limit is set
68478a1a286f736888ae7af8860b2c424af0d978848James Dong    if (mMaxFileDurationLimitUs != 0) {
68578a1a286f736888ae7af8860b2c424af0d978848James Dong        if (bitRate > 0) {
68678a1a286f736888ae7af8860b2c424af0d978848James Dong            int64_t size2 =
6870ca31521644b9396829850f7400d23f9b107cc64Johan Redestig                ((mMaxFileDurationLimitUs / 1000) * bitRate * 6) / 8000000;
68878a1a286f736888ae7af8860b2c424af0d978848James Dong            if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
68978a1a286f736888ae7af8860b2c424af0d978848James Dong                // When both file size and duration limits are set,
69078a1a286f736888ae7af8860b2c424af0d978848James Dong                // we use the smaller limit of the two.
69178a1a286f736888ae7af8860b2c424af0d978848James Dong                if (size > size2) {
69278a1a286f736888ae7af8860b2c424af0d978848James Dong                    size = size2;
69378a1a286f736888ae7af8860b2c424af0d978848James Dong                }
69478a1a286f736888ae7af8860b2c424af0d978848James Dong            } else {
69578a1a286f736888ae7af8860b2c424af0d978848James Dong                // Only max file duration limit is set
69678a1a286f736888ae7af8860b2c424af0d978848James Dong                size = size2;
69778a1a286f736888ae7af8860b2c424af0d978848James Dong            }
6982dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
6992dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
70078a1a286f736888ae7af8860b2c424af0d978848James Dong
7012dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size < MIN_MOOV_BOX_SIZE) {
7022dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MIN_MOOV_BOX_SIZE;
7032dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
7042dec2b5be2056c6d9428897dc672185872d30d17James Dong
7052dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Any long duration recording will be probably end up with
7062dec2b5be2056c6d9428897dc672185872d30d17James Dong    // non-streamable mp4 file.
7072dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size > MAX_MOOV_BOX_SIZE) {
7082dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MAX_MOOV_BOX_SIZE;
7092dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
7102dec2b5be2056c6d9428897dc672185872d30d17James Dong
7117c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // Account for the extra stuff (Geo, meta keys, etc.)
7127c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    size += mMoovExtraSize;
7137c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
714a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGI("limits: %" PRId64 "/%" PRId64 " bytes/us, bit rate: %d bps and the"
715a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn         " estimated moov size %" PRId64 " bytes",
7162dec2b5be2056c6d9428897dc672185872d30d17James Dong         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
7172dec2b5be2056c6d9428897dc672185872d30d17James Dong    return factor * size;
7182dec2b5be2056c6d9428897dc672185872d30d17James Dong}
7192dec2b5be2056c6d9428897dc672185872d30d17James Dong
7202dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) {
721674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
72225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
72320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
724fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mStartMeta = param;
72520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
726a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    /*
727a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * Check mMaxFileSizeLimitBytes at the beginning
728a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * since mMaxFileSizeLimitBytes may be implicitly
729a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * changed later for 32-bit file offset even if
730a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * user does not ask to set it explicitly.
731a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     */
732a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0) {
733a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong        mIsFileSizeLimitExplicitlyRequested = true;
734a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    }
735a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong
7362dec2b5be2056c6d9428897dc672185872d30d17James Dong    int32_t use64BitOffset;
7372dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (param &&
7382dec2b5be2056c6d9428897dc672185872d30d17James Dong        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
7392dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64BitOffset) {
7402dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
7412dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
7422dec2b5be2056c6d9428897dc672185872d30d17James Dong
7431f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    if (mUse32BitOffset) {
7441f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // Implicit 32 bit file size limit
7451f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes == 0) {
7461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
7471f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
7481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
7491f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // If file size is set to be larger than the 32 bit file
7501f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // size limit, treat it as an error.
7511f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
752a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGW("32-bit file size limit (%" PRId64 " bytes) too big. "
753a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                 "It is changed to %" PRId64 " bytes",
754d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                mMaxFileSizeLimitBytes, kMax32BitFileSize);
755d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
7561f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
7571f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    }
7581f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
759b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    int32_t use2ByteNalLength;
760b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (param &&
761b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) &&
762b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        use2ByteNalLength) {
763b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mUse4ByteNalLength = false;
7642dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
7652dec2b5be2056c6d9428897dc672185872d30d17James Dong
766de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    int32_t isRealTimeRecording;
767de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (param && param->findInt32(kKeyRealTimeRecording, &isRealTimeRecording)) {
768de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        mIsRealTimeRecording = isRealTimeRecording;
769de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    }
770de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
771065d1aff96818df54456053f1574aec8a234d0deJames Dong    mStartTimestampUs = -1;
77293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
773a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mStarted) {
774a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused) {
775a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mPaused = false;
77693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return startTracks(param);
777a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
778a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
779a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
780a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
7818f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (!param ||
7828f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
7838f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mTimeScale = 1000;
7848f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
78543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
7863856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("movie time scale: %d", mTimeScale);
7878f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
78877e8ae9967a078770416619e99ddb5b010def312James Dong    /*
78977e8ae9967a078770416619e99ddb5b010def312James Dong     * When the requested file size limit is small, the priority
79077e8ae9967a078770416619e99ddb5b010def312James Dong     * is to meet the file size limit requirement, rather than
7917b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to make the file streamable. mStreamableFile does not tell
7927b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * whether the actual recorded file is streamable or not.
79377e8ae9967a078770416619e99ddb5b010def312James Dong     */
79477e8ae9967a078770416619e99ddb5b010def312James Dong    mStreamableFile =
79577e8ae9967a078770416619e99ddb5b010def312James Dong        (mMaxFileSizeLimitBytes != 0 &&
79677e8ae9967a078770416619e99ddb5b010def312James Dong         mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes);
79777e8ae9967a078770416619e99ddb5b010def312James Dong
7987b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    /*
7997b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mWriteMoovBoxToMemory is true if the amount of data in moov box is
8007b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * smaller than the reserved free space at the beginning of a file, AND
8017b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * when the content of moov box is constructed. Note that video/audio
8027b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * frame data is always written to the file but not in the memory.
8037b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
8047b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * Before stop()/reset() is called, mWriteMoovBoxToMemory is always
8057b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * false. When reset() is called at the end of a recording session,
8067b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * Moov box needs to be constructed.
8077b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
8087b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 1) Right before a moov box is constructed, mWriteMoovBoxToMemory
8097b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to set to mStreamableFile so that if
8107b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * the file is intended to be streamable, it is set to true;
8117b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * otherwise, it is set to false. When the value is set to false,
8127b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * all the content of the moov box is written immediately to
8137b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * the end of the file. When the value is set to true, all the
8147b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * content of the moov box is written to an in-memory cache,
8157b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mMoovBoxBuffer, util the following condition happens. Note
8167b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * that the size of the in-memory cache is the same as the
8177b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * reserved free space at the beginning of the file.
8187b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
8197b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 2) While the data of the moov box is written to an in-memory
8207b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * cache, the data size is checked against the reserved space.
8217b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * If the data size surpasses the reserved space, subsequent moov
8227b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * data could no longer be hold in the in-memory cache. This also
8237b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * indicates that the reserved space was too small. At this point,
8247b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * _all_ moov data must be written to the end of the file.
8257b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mWriteMoovBoxToMemory must be set to false to direct the write
8267b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to the file.
8277b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
8287b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 3) If the data size in moov box is smaller than the reserved
8297b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * space after moov box is completely constructed, the in-memory
8307b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * cache copy of the moov box is written to the reserved free
8317b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * space. Thus, immediately after the moov is completedly
8327b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * constructed, mWriteMoovBoxToMemory is always set to false.
8337b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     */
8347b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    mWriteMoovBoxToMemory = false;
8357837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = NULL;
8367837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
8377837c17063a4c50bc856ba59418516fdab731de7James Dong
838b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeFtypBox(param);
83920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8407837c17063a4c50bc856ba59418516fdab731de7James Dong    mFreeBoxOffset = mOffset;
84120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8427837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mEstimatedMoovBoxSize == 0) {
8432dec2b5be2056c6d9428897dc672185872d30d17James Dong        int32_t bitRate = -1;
8442dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (param) {
8452dec2b5be2056c6d9428897dc672185872d30d17James Dong            param->findInt32(kKeyBitRate, &bitRate);
8462dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
8472dec2b5be2056c6d9428897dc672185872d30d17James Dong        mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
8487837c17063a4c50bc856ba59418516fdab731de7James Dong    }
84943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(mEstimatedMoovBoxSize, 8);
85077e8ae9967a078770416619e99ddb5b010def312James Dong    if (mStreamableFile) {
85177e8ae9967a078770416619e99ddb5b010def312James Dong        // Reserve a 'free' box only for streamable file
85277e8ae9967a078770416619e99ddb5b010def312James Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
85377e8ae9967a078770416619e99ddb5b010def312James Dong        writeInt32(mEstimatedMoovBoxSize);
85477e8ae9967a078770416619e99ddb5b010def312James Dong        write("free", 4);
85577e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
85677e8ae9967a078770416619e99ddb5b010def312James Dong    } else {
85777e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mOffset;
85877e8ae9967a078770416619e99ddb5b010def312James Dong    }
8597837c17063a4c50bc856ba59418516fdab731de7James Dong
8607837c17063a4c50bc856ba59418516fdab731de7James Dong    mOffset = mMdatOffset;
861c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mMdatOffset, SEEK_SET);
8621acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
8631acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("????mdat", 8);
8641acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
8651acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("\x00\x00\x00\x01mdat????????", 16);
8661acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
8671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    status_t err = startWriterThread();
8691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (err != OK) {
8701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return err;
8711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    err = startTracks(param);
874a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (err != OK) {
875a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return err;
87620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
8771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
878a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = true;
87925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
88020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
88120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const {
8831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    return mUse32BitOffset;
8841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
8851f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
88637187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() {
8875ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    ALOGW("MPEG4Writer: pause is not supported");
8885ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    return ERROR_UNSUPPORTED;
889a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
890a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
8911c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() {
892b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Stopping writer thread");
893411ba422e3635d534928ffd81abf54f4f291c739James Dong    if (!mWriterThreadStarted) {
894411ba422e3635d534928ffd81abf54f4f291c739James Dong        return;
895411ba422e3635d534928ffd81abf54f4f291c739James Dong    }
8961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
8981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
8991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mDone = true;
9011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkReadyCondition.signal();
9021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void *dummy;
9051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_join(mThread, &dummy);
906411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = false;
907b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Writer thread stopped");
9081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
9091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
91013f6284305e4b27395a23db7882d670bdb1bcae1James Dong/*
91113f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix:
91213f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a  b  u |
91313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c  d  v |
91413f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x  y  w |
91513f6284305e4b27395a23db7882d670bdb1bcae1James Dong *
91613f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following
91713f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w},
91813f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while
91913f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format.
92013f6284305e4b27395a23db7882d670bdb1bcae1James Dong */
92113f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) {
9223856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeCompositionMatrix");
92313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t a = 0x00010000;
92413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t b = 0;
92513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t c = 0;
92613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t d = 0x00010000;
92713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    switch (degrees) {
92813f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 0:
92913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
93013f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 90:
93113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
93213f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0x00010000;
93313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0xFFFF0000;
93413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
93513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
93613f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 180:
93713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0xFFFF0000;
93813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0xFFFF0000;
93913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
94013f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 270:
94113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
94213f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0xFFFF0000;
94313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0x00010000;
94413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
94513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
94613f6284305e4b27395a23db7882d670bdb1bcae1James Dong        default:
94713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            CHECK(!"Should never reach this unknown rotation");
94813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
94913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
95013f6284305e4b27395a23db7882d670bdb1bcae1James Dong
95113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(a);           // a
95213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(b);           // b
95313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // u
95413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(c);           // c
95513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(d);           // d
95613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // v
95713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // x
95813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // y
95913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0x40000000);  // w
96013f6284305e4b27395a23db7882d670bdb1bcae1James Dong}
96113f6284305e4b27395a23db7882d670bdb1bcae1James Dong
962411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() {
963411ba422e3635d534928ffd81abf54f4f291c739James Dong    close(mFd);
964411ba422e3635d534928ffd81abf54f4f291c739James Dong    mFd = -1;
965411ba422e3635d534928ffd81abf54f4f291c739James Dong    mInitCheck = NO_INIT;
966411ba422e3635d534928ffd81abf54f4f291c739James Dong    mStarted = false;
9674c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary    free(mMoovBoxBuffer);
9684c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary    mMoovBoxBuffer = NULL;
969411ba422e3635d534928ffd81abf54f4f291c739James Dong}
97013f6284305e4b27395a23db7882d670bdb1bcae1James Dong
971fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::finishCurrentSession() {
972fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    reset(false /* stopSource */);
973fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
974fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
975fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::switchFd() {
976fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGV("switchFd");
977fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    Mutex::Autolock l(mLock);
978fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mSwitchPending) {
979fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return OK;
980fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
981fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
982fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mNextFd == -1) {
983fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        ALOGW("No FileDescripter for next recording");
984fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return INVALID_OPERATION;
985fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
986fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
987fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mSwitchPending = true;
988fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    sp<AMessage> msg = new AMessage(kWhatSwitch, mReflector);
989fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    status_t err = msg->post();
990fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
991fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    return err;
992fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
993fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
994fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::reset(bool stopSource) {
995674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
99637187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
997411ba422e3635d534928ffd81abf54f4f291c739James Dong    } else {
998411ba422e3635d534928ffd81abf54f4f291c739James Dong        if (!mWriterThreadStarted ||
999411ba422e3635d534928ffd81abf54f4f291c739James Dong            !mStarted) {
1000411ba422e3635d534928ffd81abf54f4f291c739James Dong            if (mWriterThreadStarted) {
1001411ba422e3635d534928ffd81abf54f4f291c739James Dong                stopWriterThread();
1002411ba422e3635d534928ffd81abf54f4f291c739James Dong            }
1003411ba422e3635d534928ffd81abf54f4f291c739James Dong            release();
1004411ba422e3635d534928ffd81abf54f4f291c739James Dong            return OK;
1005411ba422e3635d534928ffd81abf54f4f291c739James Dong        }
100620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
100720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
100837187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
10098f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t maxDurationUs = 0;
101065b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    int64_t minDurationUs = 0x7fffffffffffffffLL;
101120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
101220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
1013fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        status_t status = (*it)->stop(stopSource);
101437187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK) {
101537187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
101637187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
101720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10188f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int64_t durationUs = (*it)->getDurationUs();
10198f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (durationUs > maxDurationUs) {
10208f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            maxDurationUs = durationUs;
102120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
102265b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        if (durationUs < minDurationUs) {
102365b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs = durationUs;
102465b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        }
102565b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    }
102665b3d76025c71d755b0fb3b6ead90255f25417edJames Dong
102765b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    if (mTracks.size() > 1) {
1028a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGD("Duration from tracks range is [%" PRId64 ", %" PRId64 "] us",
102965b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs, maxDurationUs);
103020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
103120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    stopWriterThread();
10337837c17063a4c50bc856ba59418516fdab731de7James Dong
103437187916a486504acaf83bea30147eb5fbf46ae5James Dong    // Do not write out movie header on error.
103537187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err != OK) {
1036411ba422e3635d534928ffd81abf54f4f291c739James Dong        release();
103737187916a486504acaf83bea30147eb5fbf46ae5James Dong        return err;
103837187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
103937187916a486504acaf83bea30147eb5fbf46ae5James Dong
104020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
10411acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
1042c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset, SEEK_SET);
10431f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad        uint32_t size = htonl(static_cast<uint32_t>(mOffset - mMdatOffset));
1044c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 4);
10451acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
1046c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset + 8, SEEK_SET);
10471f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad        uint64_t size = mOffset - mMdatOffset;
10481acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        size = hton64(size);
1049c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 8);
10501acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
1051c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mOffset, SEEK_SET);
105220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10537b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // Construct moov box now
10547837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
10557b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    mWriteMoovBoxToMemory = mStreamableFile;
10567b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mWriteMoovBoxToMemory) {
10577b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // There is no need to allocate in-memory cache
10587b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // for moov box if the file is not streamable.
10597b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
10607b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
10617b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        CHECK(mMoovBoxBuffer != NULL);
10627b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    }
1063b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMoovBox(maxDurationUs);
106420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10657b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // mWriteMoovBoxToMemory could be set to false in
10667b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // MPEG4Writer::write() method
10677b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mWriteMoovBoxToMemory) {
10687b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        mWriteMoovBoxToMemory = false;
10697b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // Content of the moov box is saved in the cache, and the in-memory
10707b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // moov box needs to be written to the file in a single shot.
10717b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
107243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize);
10737837c17063a4c50bc856ba59418516fdab731de7James Dong
10747837c17063a4c50bc856ba59418516fdab731de7James Dong        // Moov box
1075c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
10767837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset = mFreeBoxOffset;
1077674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset);
10787837c17063a4c50bc856ba59418516fdab731de7James Dong
10797837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free box
1080c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
10817837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
10827837c17063a4c50bc856ba59418516fdab731de7James Dong        write("free", 4);
10837b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    } else {
10847b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        ALOGI("The mp4 file will not be streamable.");
10857b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    }
10867837c17063a4c50bc856ba59418516fdab731de7James Dong
10877b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // Free in-memory cache for moov box
10887b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mMoovBoxBuffer != NULL) {
10897837c17063a4c50bc856ba59418516fdab731de7James Dong        free(mMoovBoxBuffer);
10907837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBuffer = NULL;
10917837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBufferOffset = 0;
10927837c17063a4c50bc856ba59418516fdab731de7James Dong    }
10937837c17063a4c50bc856ba59418516fdab731de7James Dong
10940c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
109520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1096411ba422e3635d534928ffd81abf54f4f291c739James Dong    release();
109737187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
109820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
109920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1100efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonuint32_t MPEG4Writer::getMpeg4Time() {
1101b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    time_t now = time(NULL);
1102efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // MP4 file uses time counting seconds since midnight, Jan. 1, 1904
1103efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // while time function returns Unix epoch values which starts
1104efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // at 1970-01-01. Lets add the number of seconds between them
11052b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    static const uint32_t delta = (66 * 365 + 17) * (24 * 60 * 60);
11062b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    if (now < 0 || uint32_t(now) > UINT32_MAX - delta) {
11072b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen        return 0;
11082b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    }
11092b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    uint32_t mpeg4Time = uint32_t(now) + delta;
1110efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    return mpeg4Time;
1111efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson}
1112efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson
1113efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) {
1114efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
1115b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("mvhd");
1116b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // version=0, flags=0
1117b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // creation time
1118b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // modification time
1119b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTimeScale);    // mvhd timescale
1120b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6;
1121b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(duration);
1122b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0x10000);       // rate: 1.0
1123b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0x100);         // volume
1124b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0);             // reserved
1125b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
1126b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
1127b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeCompositionMatrix(0); // matrix
1128b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1129b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1130b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1131b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1132b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1133b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1134b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTracks.size() + 1);  // nextTrackID
1135b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // mvhd
1136b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1137b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1138b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) {
1139b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("moov");
1140b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMvhdBox(durationUs);
114107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (mAreGeoTagsAvailable) {
114207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        writeUdtaBox();
114307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
1144e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeMetaBox();
1145230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    // Loop through all the tracks to get the global time offset if there is
1146230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    // any ctts table appears in a video track.
1147230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    int64_t minCttsOffsetTimeUs = kMaxCttsOffsetTimeUs;
1148b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    for (List<Track *>::iterator it = mTracks.begin();
1149230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        it != mTracks.end(); ++it) {
1150230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        minCttsOffsetTimeUs =
1151230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang            std::min(minCttsOffsetTimeUs, (*it)->getMinCttsOffsetTimeUs());
1152230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    }
1153230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    ALOGI("Ajust the moov start time from %lld us -> %lld us",
1154230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang            (long long)mStartTimestampUs,
1155230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang            (long long)(mStartTimestampUs + minCttsOffsetTimeUs - kMaxCttsOffsetTimeUs));
1156230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    // Adjust the global start time.
1157230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    mStartTimestampUs += minCttsOffsetTimeUs - kMaxCttsOffsetTimeUs;
1158230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang
1159230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    for (List<Track *>::iterator it = mTracks.begin();
1160230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        it != mTracks.end(); ++it) {
1161b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (*it)->writeTrackHeader(mUse32BitOffset);
1162b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
1163b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // moov
1164b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1165b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
11662cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) {
1167b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("ftyp");
1168b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1169b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t fileType;
1170b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (param && param->findInt32(kKeyFileType, &fileType) &&
1171b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fileType != OUTPUT_FORMAT_MPEG_4) {
1172b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("3gp4");
11738284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeInt32(0);
11748284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("isom");
11758284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("3gp4");
1176b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
11778284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("mp42");
11788284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeInt32(0);
1179b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("isom");
11808284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("mp42");
1181b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
1182b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1183b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();
1184b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1185b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
118607ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() {
118707ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5)
118807ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5"
118907ec01904613a0bac32caaa8444b4690998faed7James Dong#endif
119007ec01904613a0bac32caaa8444b4690998faed7James Dong
119107ec01904613a0bac32caaa8444b4690998faed7James Dong    // Test mode is enabled only if rw.media.record.test system
119207ec01904613a0bac32caaa8444b4690998faed7James Dong    // property is enabled.
119396626b7f9a4e5c9e1e04f7f710383631d1470364Marco Nelissen    if (property_get_bool("rw.media.record.test", false)) {
119407ec01904613a0bac32caaa8444b4690998faed7James Dong        return true;
119507ec01904613a0bac32caaa8444b4690998faed7James Dong    }
119607ec01904613a0bac32caaa8444b4690998faed7James Dong    return false;
119707ec01904613a0bac32caaa8444b4690998faed7James Dong}
119807ec01904613a0bac32caaa8444b4690998faed7James Dong
119970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() {
120007ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send session summary only if test mode is enabled
120107ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
120207ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
120307ec01904613a0bac32caaa8444b4690998faed7James Dong    }
120407ec01904613a0bac32caaa8444b4690998faed7James Dong
120570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
120670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong         it != mChunkInfos.end(); ++it) {
120770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int trackNum = it->mTrack->getTrackId() << 28;
120870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
120970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS,
121070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs);
121170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    }
121270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong}
121370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
121413aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
121513aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
121613aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
121713aec890216948b0c364f8f92792129d0335f506James Dong}
121813aec890216948b0c364f8f92792129d0335f506James Dong
121913aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() {
122013aec890216948b0c364f8f92792129d0335f506James Dong    mLock.lock();
122113aec890216948b0c364f8f92792129d0335f506James Dong}
122213aec890216948b0c364f8f92792129d0335f506James Dong
122313aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() {
122413aec890216948b0c364f8f92792129d0335f506James Dong    mLock.unlock();
122513aec890216948b0c364f8f92792129d0335f506James Dong}
122620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1227c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
1228c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
122920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1230c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    ::write(mFd,
1231c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          (const uint8_t *)buffer->data() + buffer->range_offset(),
1232c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          buffer->range_length());
123320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
123420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
123520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
123620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
123720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
123820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
123903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
124003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
124103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
124203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
124303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
124403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
124503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
124603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
124703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
124803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
124903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
125003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
125103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
125203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
125380f78b773f92048944a850efb7b60629643370cdPraveen Chavanoff64_t MPEG4Writer::addMultipleLengthPrefixedSamples_l(MediaBuffer *buffer) {
125480f78b773f92048944a850efb7b60629643370cdPraveen Chavan    off64_t old_offset = mOffset;
125580f78b773f92048944a850efb7b60629643370cdPraveen Chavan
125680f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const size_t kExtensionNALSearchRange = 64; // bytes to look for non-VCL NALUs
125780f78b773f92048944a850efb7b60629643370cdPraveen Chavan
125880f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *dataStart = (const uint8_t *)buffer->data() + buffer->range_offset();
125980f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *currentNalStart = dataStart;
126080f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *nextNalStart;
126180f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *data = dataStart;
126280f78b773f92048944a850efb7b60629643370cdPraveen Chavan    size_t nextNalSize;
126380f78b773f92048944a850efb7b60629643370cdPraveen Chavan    size_t searchSize = buffer->range_length() > kExtensionNALSearchRange ?
126480f78b773f92048944a850efb7b60629643370cdPraveen Chavan                   kExtensionNALSearchRange : buffer->range_length();
126580f78b773f92048944a850efb7b60629643370cdPraveen Chavan
126680f78b773f92048944a850efb7b60629643370cdPraveen Chavan    while (getNextNALUnit(&data, &searchSize, &nextNalStart,
126780f78b773f92048944a850efb7b60629643370cdPraveen Chavan            &nextNalSize, true) == OK) {
126810cc12c4eec9ff974edb72f9140b05762fa50907Lajos Molnar        size_t currentNalSize = nextNalStart - currentNalStart - 4 /* strip start-code */;
126980f78b773f92048944a850efb7b60629643370cdPraveen Chavan        MediaBuffer *nalBuf = new MediaBuffer((void *)currentNalStart, currentNalSize);
127080f78b773f92048944a850efb7b60629643370cdPraveen Chavan        addLengthPrefixedSample_l(nalBuf);
127180f78b773f92048944a850efb7b60629643370cdPraveen Chavan        nalBuf->release();
127280f78b773f92048944a850efb7b60629643370cdPraveen Chavan
127380f78b773f92048944a850efb7b60629643370cdPraveen Chavan        currentNalStart = nextNalStart;
127480f78b773f92048944a850efb7b60629643370cdPraveen Chavan    }
127580f78b773f92048944a850efb7b60629643370cdPraveen Chavan
127680f78b773f92048944a850efb7b60629643370cdPraveen Chavan    size_t currentNalOffset = currentNalStart - dataStart;
127780f78b773f92048944a850efb7b60629643370cdPraveen Chavan    buffer->set_range(buffer->range_offset() + currentNalOffset,
127880f78b773f92048944a850efb7b60629643370cdPraveen Chavan            buffer->range_length() - currentNalOffset);
127980f78b773f92048944a850efb7b60629643370cdPraveen Chavan    addLengthPrefixedSample_l(buffer);
128080f78b773f92048944a850efb7b60629643370cdPraveen Chavan
128180f78b773f92048944a850efb7b60629643370cdPraveen Chavan    return old_offset;
128280f78b773f92048944a850efb7b60629643370cdPraveen Chavan}
128380f78b773f92048944a850efb7b60629643370cdPraveen Chavan
1284c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
1285c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
128630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
128730ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
128803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1289b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mUse4ByteNalLength) {
1290b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 24;
1291c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1292b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 16) & 0xff;
1293c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1294b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 8) & 0xff;
1295c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1296b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
1297c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1298c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong
1299c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd,
1300c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              (const uint8_t *)buffer->data() + buffer->range_offset(),
1301c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              length);
1302b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
1303b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 4;
1304b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
1305b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross        CHECK_LT(length, 65536u);
130630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1307b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 8;
1308c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1309b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
1310c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1311c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length);
1312b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 2;
1313b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
131430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
131530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
131630ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
131730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
13187837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write(
1319674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        const void *ptr, size_t size, size_t nmemb) {
13207837c17063a4c50bc856ba59418516fdab731de7James Dong
13217837c17063a4c50bc856ba59418516fdab731de7James Dong    const size_t bytes = size * nmemb;
13227837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
13237b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
1324c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
13251acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        if (moovBoxSize > mEstimatedMoovBoxSize) {
13267b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // The reserved moov box at the beginning of the file
13277b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // is not big enough. Moov box should be written to
13287b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // the end of the file from now on, but not to the
13297b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // in-memory cache.
13307b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
13317b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // We write partial moov box that is in the memory to
13327b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // the file first.
1333c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            for (List<off64_t>::iterator it = mBoxes.begin();
13347837c17063a4c50bc856ba59418516fdab731de7James Dong                 it != mBoxes.end(); ++it) {
13357837c17063a4c50bc856ba59418516fdab731de7James Dong                (*it) += mOffset;
13367837c17063a4c50bc856ba59418516fdab731de7James Dong            }
1337674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            lseek64(mFd, mOffset, SEEK_SET);
1338674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset);
13397b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            ::write(mFd, ptr, bytes);
13407837c17063a4c50bc856ba59418516fdab731de7James Dong            mOffset += (bytes + mMoovBoxBufferOffset);
13417b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
13427b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // All subsequent moov box content will be written
13437b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // to the end of the file.
13447837c17063a4c50bc856ba59418516fdab731de7James Dong            mWriteMoovBoxToMemory = false;
13457837c17063a4c50bc856ba59418516fdab731de7James Dong        } else {
13467837c17063a4c50bc856ba59418516fdab731de7James Dong            memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
13477837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset += bytes;
13487837c17063a4c50bc856ba59418516fdab731de7James Dong        }
13497837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1350674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        ::write(mFd, ptr, size * nmemb);
13517837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset += bytes;
13527837c17063a4c50bc856ba59418516fdab731de7James Dong    }
13537837c17063a4c50bc856ba59418516fdab731de7James Dong    return bytes;
13547837c17063a4c50bc856ba59418516fdab731de7James Dong}
13557837c17063a4c50bc856ba59418516fdab731de7James Dong
1356e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::beginBox(uint32_t id) {
1357e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    mBoxes.push_back(mWriteMoovBoxToMemory?
1358e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            mMoovBoxBufferOffset: mOffset);
1359e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
1360e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0);
1361e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(id);
1362e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
1363e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
136420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
1365b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_EQ(strlen(fourcc), 4u);
136620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13677837c17063a4c50bc856ba59418516fdab731de7James Dong    mBoxes.push_back(mWriteMoovBoxToMemory?
13687837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset: mOffset);
136920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
137020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
137120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
137220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
137320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
137420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
13750c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
137620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1377c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = *--mBoxes.end();
137820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
137920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13807837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
13817837c17063a4c50bc856ba59418516fdab731de7James Dong       int32_t x = htonl(mMoovBoxBufferOffset - offset);
13827837c17063a4c50bc856ba59418516fdab731de7James Dong       memcpy(mMoovBoxBuffer + offset, &x, 4);
13837837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1384c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, offset, SEEK_SET);
13857837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mOffset - offset);
13867837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset -= 4;
1387c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
13887837c17063a4c50bc856ba59418516fdab731de7James Dong    }
138920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
139020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
139120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
1392674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 1);
139320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
139420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
139520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
139620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
1397674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 2);
139820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
139920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
140020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
140120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
1402674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 4);
140320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
140420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
140520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
140620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
1407674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 8);
140820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
140920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
141020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
141120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
1412674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, n + 1);
141320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
141420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
141520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
1416b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_EQ(strlen(s), 4u);
1417674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, 4);
141820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
141920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
142007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
142107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format
142207b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) {
142307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
142407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
142507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
142607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
142707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[9];
142807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
142907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
143007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%c%.2d.", sign, wholePart);
143107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
143207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%+.2d.", wholePart);
143307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
143407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
143507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
143607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
143707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
143807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
143907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
144007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[4], 5, "%.4d", fractionalPart);
144107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
144207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
144307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 8);
144407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
144507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
144607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format
144707b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) {
144807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
144907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
145007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
145107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
145207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[10];
145307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
145407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
145507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%c%.3d.", sign, wholePart);
145607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
145707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%+.3d.", wholePart);
145807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
145907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
146007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
146107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
146207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
146307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
146407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
146507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[5], 5, "%.4d", fractionalPart);
146607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
146707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
146807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 9);
146907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
147007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
147107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
147207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
147307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and
147407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000.
147507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and
147607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180]
147707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
147807b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) {
147907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Is latitude or longitude out of range?
148007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (latitudex10000 < -900000 || latitudex10000 > 900000 ||
148107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        longitudex10000 < -1800000 || longitudex10000 > 1800000) {
148207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        return BAD_VALUE;
148307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
148407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
148507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLatitudex10000 = latitudex10000;
148607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLongitudex10000 = longitudex10000;
148707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mAreGeoTagsAvailable = true;
14887c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += 30;
148907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    return OK;
149007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
149107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
1492e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangstatus_t MPEG4Writer::setCaptureRate(float captureFps) {
1493e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    if (captureFps <= 0.0f) {
1494e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        return BAD_VALUE;
1495e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
1496e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
14977c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMetaKeys->setFloat(kMetaKey_CaptureFps, captureFps);
14987c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += sizeof(kMetaKey_CaptureFps) + 4 + 32;
14997c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
1500e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    return OK;
1501e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
1502e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
15034dbff11975e737482537e1636051690188f3fbc4Praveen Chavanstatus_t MPEG4Writer::setTemporalLayerCount(uint32_t layerCount) {
15044dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    if (layerCount > 9) {
15054dbff11975e737482537e1636051690188f3fbc4Praveen Chavan        return BAD_VALUE;
15064dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    }
15074dbff11975e737482537e1636051690188f3fbc4Praveen Chavan
15084dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    if (layerCount > 0) {
15094dbff11975e737482537e1636051690188f3fbc4Praveen Chavan        mMetaKeys->setInt32(kMetaKey_TemporalLayerCount, layerCount);
15104dbff11975e737482537e1636051690188f3fbc4Praveen Chavan        mMoovExtraSize += sizeof(kMetaKey_TemporalLayerCount) + 4 + 32;
15114dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    }
15124dbff11975e737482537e1636051690188f3fbc4Praveen Chavan
15134dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    return OK;
15144dbff11975e737482537e1636051690188f3fbc4Praveen Chavan}
15154dbff11975e737482537e1636051690188f3fbc4Praveen Chavan
1516fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::notifyApproachingLimit() {
1517fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    Mutex::Autolock autolock(mLock);
1518fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    // Only notify once.
1519fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mSendNotify) {
1520fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return;
1521fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1522fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGW("Recorded file size is approaching limit %" PRId64 "bytes",
1523fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mMaxFileSizeLimitBytes);
1524fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING, 0);
1525fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mSendNotify = true;
1526fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
1527fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
152820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
1529674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(data, 1, size);
153020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
153120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
153278a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const {
153378a1a286f736888ae7af8860b2c424af0d978848James Dong    return mStreamableFile;
153478a1a286f736888ae7af8860b2c424af0d978848James Dong}
153578a1a286f736888ae7af8860b2c424af0d978848James Dong
1536d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() {
1537d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1538d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeLimitBytes == 0) {
1539d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1540d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1541956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
1542d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1543d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1544d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
1545d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
15461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
154777e8ae9967a078770416619e99ddb5b010def312James Dong    if (!mStreamableFile) {
154877e8ae9967a078770416619e99ddb5b010def312James Dong        // Add 1024 bytes as error tolerance
154977e8ae9967a078770416619e99ddb5b010def312James Dong        return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes;
155077e8ae9967a078770416619e99ddb5b010def312James Dong    }
1551fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1552acd234bba9f048971d66890009eeff9a8db94be3James Dong    // Be conservative in the estimate: do not exceed 95% of
1553acd234bba9f048971d66890009eeff9a8db94be3James Dong    // the target file limit. For small target file size limit, though,
1554acd234bba9f048971d66890009eeff9a8db94be3James Dong    // this will not help.
1555acd234bba9f048971d66890009eeff9a8db94be3James Dong    return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100);
1556d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1557d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1558fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangbool MPEG4Writer::approachingFileSizeLimit() {
1559fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    // No limit
1560fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mMaxFileSizeLimitBytes == 0) {
1561fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return false;
1562fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1563fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1564fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
1565fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    for (List<Track *>::iterator it = mTracks.begin();
1566fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         it != mTracks.end(); ++it) {
1567fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
1568fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1569fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1570fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (!mStreamableFile) {
1571fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        // Add 1024 bytes as error tolerance
1572fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return nTotalBytesEstimate + 1024 >= (90 * mMaxFileSizeLimitBytes) / 100;
1573fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1574fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1575fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    return (nTotalBytesEstimate >= (90 * mMaxFileSizeLimitBytes) / 100);
1576fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
1577fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1578d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() {
1579d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1580d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationLimitUs == 0) {
1581d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1582d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1583d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1584d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1585d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1586d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
1587d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            return true;
1588d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1589d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1590d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return false;
1591d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1592d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
159325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
159425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
159525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
159625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
159725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
159825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
159925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
160025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
160125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
160225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
160325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
160425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
160525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
1606f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
1607a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGI("setStartTimestampUs: %" PRId64, timeUs);
160843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(timeUs, 0ll);
16093c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
1610065d1aff96818df54456053f1574aec8a234d0deJames Dong    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
1611f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimestampUs = timeUs;
1612a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Earliest track starting time: %" PRId64, mStartTimestampUs);
16133c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    }
16143c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
16153c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
1616f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() {
16173c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
16183c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    return mStartTimestampUs;
16193c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
16203c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
162158ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() {
162258ae9c530247668f8af36e30d228c716c226b3d4James Dong    Mutex::Autolock autolock(mLock);
162358ae9c530247668f8af36e30d228c716c226b3d4James Dong    return mTracks.size();
162458ae9c530247668f8af36e30d228c716c226b3d4James Dong}
162558ae9c530247668f8af36e30d228c716c226b3d4James Dong
162620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
162720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
162820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
1629b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen        MPEG4Writer *owner, const sp<IMediaSource> &source, size_t trackId)
163020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
163125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
163220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
163320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
1634a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
1635a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mResumed(false),
1636eaae38445a340c4857c1c5569475879a728e63b7James Dong      mStarted(false),
1637fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mGotStartKeyFrame(false),
16389db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang      mIsMalformed(false),
1639bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong      mTrackId(trackId),
1640c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong      mTrackDurationUs(0),
1641956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mEstimatedTrackSizeBytes(0),
1642be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong      mSamplesHaveSameSize(true),
1643c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mStszTableEntries(new ListTableEntries<uint32_t, 1>(1000)),
1644c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mStcoTableEntries(new ListTableEntries<uint32_t, 1>(1000)),
1645c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mCo64TableEntries(new ListTableEntries<off64_t, 1>(1000)),
1646c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mStscTableEntries(new ListTableEntries<uint32_t, 3>(1000)),
1647c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mStssTableEntries(new ListTableEntries<uint32_t, 1>(1000)),
1648c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mSttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)),
1649c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mCttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)),
1650230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang      mMinCttsOffsetTimeUs(0),
1651230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang      mMinCttsOffsetTicks(0),
1652230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang      mMaxCttsOffsetTicks(0),
165320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
165425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
1655548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
165613f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mReachedEOS(false),
1657a9292fe1c19e8a9b43398ba3d69284c215d7589fRobert Shih      mStartTimestampUs(-1),
165813f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mRotation(0) {
165919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    getCodecSpecificDataFromInputFormatIfPossible();
16608f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
16611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    const char *mime;
16621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMeta->findCString(kKeyMIMEType, &mime);
16631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
16649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mIsHevc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC);
16651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAudio = !strncasecmp(mime, "audio/", 6);
166625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mIsVideo = !strncasecmp(mime, "video/", 6);
16671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
16681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
16691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1670b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar    // store temporal layer count
167125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (mIsVideo) {
1672b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar        int32_t count;
1673b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar        if (mMeta->findInt32(kKeyTemporalLayerCount, &count) && count > 1) {
1674b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar            mOwner->setTemporalLayerCount(count);
1675b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar        }
1676b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar    }
1677b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar
1678c059860c73678a202bfa33062723e8f82fb779d9James Dong    setTimeScale();
1679c059860c73678a202bfa33062723e8f82fb779d9James Dong}
1680c059860c73678a202bfa33062723e8f82fb779d9James Dong
1681fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang// Clear all the internal states except the CSD data.
1682fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::Track::resetInternal() {
1683fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mDone = false;
1684fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mPaused = false;
1685fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mResumed = false;
1686fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mStarted = false;
1687fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mGotStartKeyFrame = false;
1688fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mIsMalformed = false;
1689fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mTrackDurationUs = 0;
1690fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mEstimatedTrackSizeBytes = 0;
1691fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mSamplesHaveSameSize = 0;
1692fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mStszTableEntries != NULL) {
1693fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mStszTableEntries;
1694fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mStszTableEntries = new ListTableEntries<uint32_t, 1>(1000);
1695fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1696fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1697fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mStcoTableEntries != NULL) {
1698fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mStcoTableEntries;
1699fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mStcoTableEntries = new ListTableEntries<uint32_t, 1>(1000);
1700fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1701fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mCo64TableEntries != NULL) {
1702fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mCo64TableEntries;
1703fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mCo64TableEntries = new ListTableEntries<off64_t, 1>(1000);
1704fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1705fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1706fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mStscTableEntries != NULL) {
1707fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mStscTableEntries;
1708fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mStscTableEntries = new ListTableEntries<uint32_t, 3>(1000);
1709fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1710fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mStssTableEntries != NULL) {
1711fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mStssTableEntries;
1712fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mStssTableEntries = new ListTableEntries<uint32_t, 1>(1000);
1713fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1714fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mSttsTableEntries != NULL) {
1715fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mSttsTableEntries;
1716fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mSttsTableEntries = new ListTableEntries<uint32_t, 2>(1000);
1717fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1718fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mCttsTableEntries != NULL) {
1719fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mCttsTableEntries;
1720fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mCttsTableEntries = new ListTableEntries<uint32_t, 2>(1000);
1721fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1722fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mReachedEOS = false;
1723fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
1724fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
17251f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() {
17261f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1727c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t stcoBoxCount = (mOwner->use32BitFileOffset()
1728c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                            ? mStcoTableEntries->count()
1729c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                            : mCo64TableEntries->count());
1730c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    int64_t stcoBoxSizeBytes = stcoBoxCount * 4;
1731c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4);
17321f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
173378a1a286f736888ae7af8860b2c424af0d978848James Dong    mEstimatedTrackSizeBytes = mMdatSizeBytes;  // media data size
173478a1a286f736888ae7af8860b2c424af0d978848James Dong    if (!mOwner->isFileStreamable()) {
173578a1a286f736888ae7af8860b2c424af0d978848James Dong        // Reserved free space is not large enough to hold
173678a1a286f736888ae7af8860b2c424af0d978848James Dong        // all meta data and thus wasted.
1737c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 +  // stsc box size
1738c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mStssTableEntries->count() * 4 +   // stss box size
1739c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mSttsTableEntries->count() * 8 +   // stts box size
1740c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mCttsTableEntries->count() * 8 +   // ctts box size
174178a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stcoBoxSizeBytes +           // stco box size
174278a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stszBoxSizeBytes;            // stsz box size
174378a1a286f736888ae7af8860b2c424af0d978848James Dong    }
17441f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
17451f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
17461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry(
17471f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        size_t chunkId, size_t sampleId) {
17481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1749c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(chunkId));
1750c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(sampleId));
1751c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(1));
17521f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
17531f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
17541f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) {
1755c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->add(htonl(sampleId));
17561f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
17571f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
17581f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry(
175979761ab096f57c3027fad9556c2bc436672d614eJames Dong        size_t sampleCount, int32_t duration) {
17601f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
17615a217fba010e801c255503602bda4b86ac5a6ac9James Dong    if (duration == 0) {
1762377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGW("0-duration samples found: %zu", sampleCount);
17635a217fba010e801c255503602bda4b86ac5a6ac9James Dong    }
1764c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(sampleCount));
1765c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(duration));
17661f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
17671f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1768965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry(
1769965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        size_t sampleCount, int32_t duration) {
1770965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
177125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (!mIsVideo) {
1772965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
1773965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
1774c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(sampleCount));
1775c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(duration));
1776965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
1777965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1778fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::setNextFd(int fd) {
1779fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGV("addNextFd");
1780fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    Mutex::Autolock l(mLock);
1781fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mLooper == NULL) {
1782fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mReflector = new AHandlerReflector<MPEG4Writer>(this);
1783fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mLooper = new ALooper;
1784fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mLooper->registerHandler(mReflector);
1785fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mLooper->start();
1786fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1787fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1788fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mNextFd != -1) {
1789fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        // No need to set a new FD yet.
1790fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return INVALID_OPERATION;
1791fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1792fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mNextFd = fd;
1793fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    return OK;
1794fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
1795fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1796c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) {
1797c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mOwner->use32BitFileOffset()) {
1798c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t value = offset;
1799c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->add(htonl(value));
1800c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
1801c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->add(hton64(offset));
1802c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    }
18031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
18041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1805c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() {
18063856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setTimeScale");
1807c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Default time scale
1808c059860c73678a202bfa33062723e8f82fb779d9James Dong    mTimeScale = 90000;
1809c059860c73678a202bfa33062723e8f82fb779d9James Dong
1810c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mIsAudio) {
1811c059860c73678a202bfa33062723e8f82fb779d9James Dong        // Use the sampling rate as the default time scale for audio track.
1812c059860c73678a202bfa33062723e8f82fb779d9James Dong        int32_t sampleRate;
1813c059860c73678a202bfa33062723e8f82fb779d9James Dong        bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
1814c059860c73678a202bfa33062723e8f82fb779d9James Dong        CHECK(success);
1815c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = sampleRate;
1816c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1817c059860c73678a202bfa33062723e8f82fb779d9James Dong
1818c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If someone would like to overwrite the timescale, use user-supplied value.
1819c059860c73678a202bfa33062723e8f82fb779d9James Dong    int32_t timeScale;
1820c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
1821c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = timeScale;
1822c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1823c059860c73678a202bfa33062723e8f82fb779d9James Dong
182443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
182519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber}
182619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
1827fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::onMessageReceived(const sp<AMessage> &msg) {
1828fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    switch (msg->what()) {
1829fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        case kWhatSwitch:
1830fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        {
1831fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            finishCurrentSession();
1832fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mLock.lock();
1833fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            int fd = mNextFd;
1834fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mNextFd = -1;
1835fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mLock.unlock();
18365ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang            initInternal(fd, false /*isFirstSession*/);
1837fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            start(mStartMeta.get());
1838fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mSwitchPending = false;
1839fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED, 0);
1840fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            break;
1841fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        }
1842fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        default:
1843fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        TRESPASS();
1844fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1845fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
1846fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
184719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
184819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    const char *mime;
1849fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
185019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
185119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
18529aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    uint32_t type;
18539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const void *data = NULL;
18549aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t size = 0;
185519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
18569aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mMeta->findData(kKeyAVCC, &type, &data, &size);
18579aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
18589aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mMeta->findData(kKeyHVCC, &type, &data, &size);
185919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
186019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
186119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
186219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            ESDS esds(data, size);
1863212335cbc6e8795c3cfb332e7b119e03cf33f603Pawin Vongmasa            if (esds.getCodecSpecificInfo(&data, &size) == OK &&
1864212335cbc6e8795c3cfb332e7b119e03cf33f603Pawin Vongmasa                    data != NULL &&
1865212335cbc6e8795c3cfb332e7b119e03cf33f603Pawin Vongmasa                    copyCodecSpecificData((uint8_t*)data, size) == OK) {
1866212335cbc6e8795c3cfb332e7b119e03cf33f603Pawin Vongmasa                mGotAllCodecSpecificData = true;
186719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            }
1868212335cbc6e8795c3cfb332e7b119e03cf33f603Pawin Vongmasa            return;
186919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
187019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
18719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (data != NULL && copyCodecSpecificData((uint8_t *)data, size) == OK) {
18729aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mGotAllCodecSpecificData = true;
18739aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
187420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
187520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
187620111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
187720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
187820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1879c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStszTableEntries;
1880c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStcoTableEntries;
1881c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCo64TableEntries;
1882c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStscTableEntries;
1883c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mSttsTableEntries;
1884c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStssTableEntries;
1885c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCttsTableEntries;
1886c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
1887c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries = NULL;
1888c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStcoTableEntries = NULL;
1889c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCo64TableEntries = NULL;
1890c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries = NULL;
1891c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries = NULL;
1892c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries = NULL;
1893c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries = NULL;
1894c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
189520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
189620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
189720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
189820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
189920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
190020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
190193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
19023856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("initTrackingProgressStatus");
190393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mPreviousTrackTimeUs = -1;
190493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackingProgressStatus = false;
190593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
190693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    {
190793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeUs;
190893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
1909a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGV("Receive request to track progress status for every %" PRId64 " us", timeUs);
191093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackEveryTimeDurationUs = timeUs;
191193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackingProgressStatus = true;
191293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
191393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
191493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
191593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
19161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static
19171c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) {
19183856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("ThreadWrapper: %p", me);
19191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
19201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    writer->threadFunc();
19211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return NULL;
19221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
19231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
19241c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) {
19253856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk: %p", chunk.mTrack);
19261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Mutex::Autolock autolock(mLock);
19271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK_EQ(mDone, false);
19281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
19291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
19301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
19311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
19321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (chunk.mTrack == it->mTrack) {  // Found owner
19331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            it->mChunks.push_back(chunk);
19341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.signal();
19351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            return;
19361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
19371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
19381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
193943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK(!"Received a chunk for a unknown track");
19401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
19411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1942fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) {
1943a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("writeChunkToFile: %" PRId64 " from %s track",
194425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        chunk->mTimeStampUs, chunk->mTrack->getTrackType());
1945fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1946fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    int32_t isFirstSample = true;
1947fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    while (!chunk->mSamples.empty()) {
1948fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        List<MediaBuffer *>::iterator it = chunk->mSamples.begin();
1949fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
19509aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        off64_t offset = (chunk->mTrack->isAvc() || chunk->mTrack->isHevc())
195180f78b773f92048944a850efb7b60629643370cdPraveen Chavan                                ? addMultipleLengthPrefixedSamples_l(*it)
1952fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong                                : addSample_l(*it);
1953fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1954fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (isFirstSample) {
1955fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            chunk->mTrack->addChunkOffset(offset);
1956fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            isFirstSample = false;
19571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
19581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
19591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it)->release();
19601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it) = NULL;
1961fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        chunk->mSamples.erase(it);
19621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1963fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    chunk->mSamples.clear();
19641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
19651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1966fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() {
19673856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeAllChunks");
19681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    size_t outstandingChunks = 0;
196970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    Chunk chunk;
197070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    while (findChunkToWrite(&chunk)) {
1971e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong        writeChunkToFile(&chunk);
197270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        ++outstandingChunks;
19731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
197470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
197570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    sendSessionSummary();
197670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
19771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mChunkInfos.clear();
1978377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    ALOGD("%zu chunks are written in the last batch", outstandingChunks);
19791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
19801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1981fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) {
19823856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("findChunkToWrite");
19831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
19841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
19851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Track *track = NULL;
19861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
19871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
19881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (!it->mChunks.empty()) {
19891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            List<Chunk>::iterator chunkIt = it->mChunks.begin();
19901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (chunkIt->mTimeStampUs < minTimestampUs) {
19911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                minTimestampUs = chunkIt->mTimeStampUs;
19921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                track = it->mTrack;
19931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            }
19941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
19951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
19961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
19971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (track == NULL) {
19983856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Nothing to be written after all");
1999fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        return false;
20001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
20011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
20021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mIsFirstChunk) {
20031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsFirstChunk = false;
20041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
2005fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
20061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
20071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
20081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it->mTrack == track) {
2009fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            *chunk = *(it->mChunks.begin());
2010fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            it->mChunks.erase(it->mChunks.begin());
2011fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            CHECK_EQ(chunk->mTrack, track);
201270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
201370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t interChunkTimeUs =
201470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                chunk->mTimeStampUs - it->mPrevChunkTimestampUs;
201570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            if (interChunkTimeUs > it->mPrevChunkTimestampUs) {
201670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs = interChunkTimeUs;
201770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            }
201870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
2019fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            return true;
20201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
20211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
2022fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
2023fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    return false;
20241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
20251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
20261c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() {
20273856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("threadFunc");
20281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
2029a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0);
2030fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
2031fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    Mutex::Autolock autoLock(mLock);
20321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mDone) {
2033fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        Chunk chunk;
2034fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        bool chunkFound = false;
2035fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
2036fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) {
20371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.wait(mLock);
20381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
20391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
2040de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // In real time recording mode, write without holding the lock in order
2041de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // to reduce the blocking time for media track threads.
2042de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // Otherwise, hold the lock until the existing chunks get written to the
2043de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // file.
2044fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (chunkFound) {
2045de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            if (mIsRealTimeRecording) {
2046de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui                mLock.unlock();
2047de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            }
2048fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            writeChunkToFile(&chunk);
2049de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            if (mIsRealTimeRecording) {
2050de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui                mLock.lock();
2051de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            }
2052fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        }
20531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
2054fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
2055fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    writeAllChunks();
20561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
20571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
20581c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() {
20593856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("startWriterThread");
20601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
20611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mDone = false;
20621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsFirstChunk = true;
2063e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    mDriftTimeUs = 0;
20641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<Track *>::iterator it = mTracks.begin();
20651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mTracks.end(); ++it) {
20661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        ChunkInfo info;
20671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        info.mTrack = *it;
206870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mPrevChunkTimestampUs = 0;
206970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mMaxInterChunkDurUs = 0;
20701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.push_back(info);
20711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
20721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
20731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_t attr;
20741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_init(&attr);
20751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
20761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_create(&mThread, &attr, ThreadWrapper, this);
20771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_destroy(&attr);
2078411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = true;
20791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
20801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
20811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
20821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
208393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) {
2084a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (!mDone && mPaused) {
2085a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mPaused = false;
2086a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mResumed = true;
2087a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
2088a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
208925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
209093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t startTimeUs;
209119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
209219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        startTimeUs = 0;
209319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
209470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    mStartTimeRealUs = startTimeUs;
209519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
209613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t rotationDegrees;
209725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (mIsVideo && params && params->findInt32(kKeyRotation, &rotationDegrees)) {
209813f6284305e4b27395a23db7882d670bdb1bcae1James Dong        mRotation = rotationDegrees;
209913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
210013f6284305e4b27395a23db7882d670bdb1bcae1James Dong
210193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    initTrackingProgressStatus(params);
210293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
2103f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    sp<MetaData> meta = new MetaData;
2104de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) {
2105a472613aec322e25891abf5c77bf3f7e3c244920James Dong        /*
2106a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * This extra delay of accepting incoming audio/video signals
2107a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * helps to align a/v start time at the beginning of a recording
2108a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * session, and it also helps eliminate the "recording" sound for
2109a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * camcorder applications.
2110a472613aec322e25891abf5c77bf3f7e3c244920James Dong         *
211186b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * If client does not set the start time offset, we fall back to
211286b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * use the default initial delay value.
2113a472613aec322e25891abf5c77bf3f7e3c244920James Dong         */
211486b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
211586b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
211686b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
211786b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
211886b7f47aa7482424cf8fd248f1315311919be3b0James Dong        startTimeUs += startTimeOffsetUs;
2119a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Start time offset: %" PRId64 " us", startTimeOffsetUs);
2120a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
2121a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2122f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    meta->setInt64(kKeyTime, startTimeUs);
2123a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2124f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    status_t err = mSource->start(meta.get());
212525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
212625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
212725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
212825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
212920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
213020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
213120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
213220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
213320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
213420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
2135eaae38445a340c4857c1c5569475879a728e63b7James Dong    mStarted = true;
2136c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs = 0;
213725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
2138956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mEstimatedTrackSizeBytes = 0;
21391f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mMdatSizeBytes = 0;
214043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mMaxChunkDurationUs = 0;
2141826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar    mLastDecodingTimeUs = -1;
214220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
214325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
214420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
214525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
214625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
214720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
214820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
214937187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() {
2150a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
215137187916a486504acaf83bea30147eb5fbf46ae5James Dong    return OK;
2152a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
2153a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2154fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::Track::stop(bool stopSource) {
2155fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGD("%s track stopping. %s source", getTrackType(), stopSource ? "Stop" : "Not Stop");
2156eaae38445a340c4857c1c5569475879a728e63b7James Dong    if (!mStarted) {
215729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Stop() called but track is not started");
2158eaae38445a340c4857c1c5569475879a728e63b7James Dong        return ERROR_END_OF_STREAM;
2159eaae38445a340c4857c1c5569475879a728e63b7James Dong    }
2160eaae38445a340c4857c1c5569475879a728e63b7James Dong
216120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
216237187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
216320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
2164f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang
2165fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (stopSource) {
2166fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        ALOGD("%s track source stopping", getTrackType());
2167fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mSource->stop();
2168fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        ALOGD("%s track source stopped", getTrackType());
2169fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
217072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
2171f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang    // Set mDone to be true after sucessfully stop mSource as mSource may be still outputting
2172f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang    // buffers to the writer.
2173f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang    mDone = true;
2174f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang
217520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
217620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
2177377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy));
217837187916a486504acaf83bea30147eb5fbf46ae5James Dong
2179fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGD("%s track stopped. %s source", getTrackType(), stopSource ? "Stop" : "Not Stop");
218037187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
218120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
218220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
218325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
218425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
218525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
218625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
218720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
218820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
218920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
219020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
219137187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = track->threadEntry();
2192377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    return (void *)(uintptr_t)err;
219320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
219420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) {
21963856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("getNalUnitType: %d", byte);
21973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // nal_unit_type: 5-bit unsigned integer
21993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *type = (byte & 0x1F);
22003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
22013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet(
22033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
22043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22053856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseParamSet");
22063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    CHECK(type == kNalUnitTypeSeqParamSet ||
22073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong          type == kNalUnitTypePicParamSet);
22083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
220947d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar    const uint8_t *nextStartCode = findNextNalStartCode(data, length);
22103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *paramSetLen = nextStartCode - data;
22113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (*paramSetLen == 0) {
221229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Param set is malformed, since its length is 0");
22133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return NULL;
22143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
22153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    AVCParamSet paramSet(*paramSetLen, data);
22173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (type == kNalUnitTypeSeqParamSet) {
22183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (*paramSetLen < 4) {
221929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Seq parameter set malformed");
22203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return NULL;
22213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
22223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mSeqParamSets.empty()) {
22233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc = data[1];
22243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileCompatible = data[2];
22253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mLevelIdc = data[3];
22263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
22273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (mProfileIdc != data[1] ||
22283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mProfileCompatible != data[2] ||
22293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mLevelIdc != data[3]) {
223007b2fbfb40770f3be0f674596f2e51d257c6d2bdLajos Molnar                // COULD DO: set profile/level to the lowest required to support all SPSs
223129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Inconsistent profile/level found in seq parameter sets");
22323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return NULL;
22333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
22343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
22353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mSeqParamSets.push_back(paramSet);
22363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    } else {
22373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mPicParamSets.push_back(paramSet);
22383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
22393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return nextStartCode;
22403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
22413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData(
22433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
22443856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("copyAVCCodecSpecificData");
22453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 2 bytes for each of the parameter set length field
22473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // plus the 7 bytes for the header
22489aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return copyCodecSpecificData(data, size, 4 + 7);
22499aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
22509aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22519aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyHEVCCodecSpecificData(
22529aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size) {
22539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ALOGV("copyHEVCCodecSpecificData");
22549aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Min length of HEVC CSD is 23. (ISO/IEC 14496-15:2014 Chapter 8.3.3.1.2)
22569aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return copyCodecSpecificData(data, size, 23);
22579aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
22589aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22599aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyCodecSpecificData(
22609aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size, size_t minLength) {
22619aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (size < minLength) {
2262377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGE("Codec specific data length too short: %zu", size);
22633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return ERROR_MALFORMED;
22643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
22653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificData = malloc(size);
22679aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
22689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
22699aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
22709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
22719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificDataSize = size;
22723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    memcpy(mCodecSpecificData, data, size);
22733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
22743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
22753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData(
22773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
22783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22793856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseAVCCodecSpecificData");
22803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data starts with a start code.
22813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // SPS and PPS are separated with start codes.
22823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Also, SPS must come before PPS
22833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t type = kNalUnitTypeSeqParamSet;
22843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotSps = false;
22853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotPps = false;
22863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *tmp = data;
22873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = data;
22883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = size;
22893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t paramSetLen = 0;
22903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = 0;
22913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
22923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        getNalUnitType(*(tmp + 4), &type);
22933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (type == kNalUnitTypeSeqParamSet) {
22943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (gotPps) {
229529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
22963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
22973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
22983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
22993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotSps = true;
23003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
23013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
23023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else if (type == kNalUnitTypePicParamSet) {
23033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
230429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
23053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
23063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
23073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotPps) {
23083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotPps = true;
23093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
23103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
23113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
231229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Only SPS and PPS Nal units are expected");
23133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
23143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
23153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
23163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nextStartCode == NULL) {
23173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
23183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
23193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
23203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Move on to find the next parameter set
23213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft -= nextStartCode - tmp;
23223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        tmp = nextStartCode;
23233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mCodecSpecificDataSize += (2 + paramSetLen);
23243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
23253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
23263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
23273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of seq parameter sets
23283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nSeqParamSets = mSeqParamSets.size();
23293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets == 0) {
233029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find sequence parameter set");
23313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
23323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
23333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
23343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets > 0x1F) {
2335377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets);
23363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
23373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
23383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
23393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
23403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
23413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of pic parameter sets
23423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nPicParamSets = mPicParamSets.size();
23433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets == 0) {
234429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find picture parameter set");
23453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
23463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
23473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets > 0xFF) {
2348377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets);
23493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
23503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
23513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
23521374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME:
23531374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above
23541374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0
23551374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0
23563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
23573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the profiles
23583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // These profiles requires additional parameter set extensions
23593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mProfileIdc == 100 || mProfileIdc == 110 ||
23603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc == 122 || mProfileIdc == 144) {
236129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
23623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return BAD_VALUE;
23633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
23643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
23651374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif
23663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
23673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
2368548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
236903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
237003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
2371548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
237203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
237329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Already have codec specific data");
237403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
237503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
237603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
23773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4) {
2378377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGE("Codec specific data length too short: %zu", size);
237903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
238003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
238103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
23823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data is in the form of AVCCodecSpecificData
23833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (memcmp("\x00\x00\x00\x01", data, 4)) {
23843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return copyAVCCodecSpecificData(data, size);
238503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
238603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
23873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (parseAVCCodecSpecificData(data, size) != OK) {
238803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
238903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
239003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
23913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // ISO 14496-15: AVC file format
23923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize += 7;  // 7 more bytes in the header
239303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
23949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
23959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mCodecSpecificDataSize = 0;
23969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
23979aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
23989aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
239903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
24003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = 1;                     // version
24013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[1] = mProfileIdc;           // profile indication
24023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[2] = mProfileCompatible;    // profile compatibility
24033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[3] = mLevelIdc;
240403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
24053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
2406b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mOwner->useNalLengthFour()) {
2407b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 3;  // length size == 4 bytes
2408b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
2409b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 1;  // length size == 2 bytes
2410b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
241103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
24123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 3-bit '111' followed by 5-bit numSequenceParameterSets
24133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nSequenceParamSets = mSeqParamSets.size();
24143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[5] = 0xe0 | nSequenceParamSets;
24153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 6;
24163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
24173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mSeqParamSets.end(); ++it) {
24183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit sequence parameter set length
24193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t seqParamSetLength = it->mLength;
24203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = seqParamSetLength >> 8;
24213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = seqParamSetLength & 0xff;
24223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
24233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // SPS NAL unit (sequence parameter length bytes)
24243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, seqParamSetLength);
24253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + seqParamSetLength);
24263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
24273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
24283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 8-bit nPictureParameterSets
24293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nPictureParamSets = mPicParamSets.size();
24303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = nPictureParamSets;
24313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 1;
24323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
24333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mPicParamSets.end(); ++it) {
24343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit picture parameter set length
24353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t picParamSetLength = it->mLength;
24363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = picParamSetLength >> 8;
24373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = picParamSetLength & 0xff;
24383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
24393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // PPS Nal unit (picture parameter set length bytes)
24403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, picParamSetLength);
24413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + picParamSetLength);
24423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
244303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
244403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
244503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
244603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
24479aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24489aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::parseHEVCCodecSpecificData(
24499aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size, HevcParameterSets &paramSets) {
24509aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24519aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ALOGV("parseHEVCCodecSpecificData");
24529aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const uint8_t *tmp = data;
24539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const uint8_t *nextStartCode = data;
24549aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t bytesLeft = size;
24559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
245647d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar        nextStartCode = findNextNalStartCode(tmp + 4, bytesLeft - 4);
24579aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        status_t err = paramSets.addNalUnit(tmp + 4, (nextStartCode - tmp) - 4);
24589aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (err != OK) {
24599aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
24609aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
24619aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        // Move on to find the next parameter set
24639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        bytesLeft -= nextStartCode - tmp;
24649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        tmp = nextStartCode;
24659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
24669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24679aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t csdSize = 23;
24689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const size_t numNalUnits = paramSets.getNumNalUnits();
24699aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    for (size_t i = 0; i < ARRAY_SIZE(kMandatoryHevcNalUnitTypes); ++i) {
24709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        int type = kMandatoryHevcNalUnitTypes[i];
24719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        size_t numParamSets = paramSets.getNumNalUnitsOfType(type);
24729aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (numParamSets == 0) {
24739aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            ALOGE("Cound not find NAL unit of type %d", type);
24749aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
24759aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
24769aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
24779aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    for (size_t i = 0; i < ARRAY_SIZE(kHevcNalUnitTypes); ++i) {
24789aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        int type = kHevcNalUnitTypes[i];
24799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        size_t numParamSets = paramSets.getNumNalUnitsOfType(type);
24809aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (numParamSets > 0xffff) {
24819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            ALOGE("Too many seq parameter sets (%zu) found", numParamSets);
24829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
24839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
24849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        csdSize += 3;
24859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        for (size_t j = 0; j < numNalUnits; ++j) {
24869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            if (paramSets.getType(j) != type) {
24879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                continue;
24889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            }
24899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            csdSize += 2 + paramSets.getSize(j);
24909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
24919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
24929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificDataSize = csdSize;
24939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return OK;
24949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
24959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::makeHEVCCodecSpecificData(
24979aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size) {
24989aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24999aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData != NULL) {
25009aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Already have codec specific data");
25019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
25029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
25039aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
25049aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (size < 4) {
25059aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Codec specific data length too short: %zu", size);
25069aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
25079aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
25089aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
25099aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Data is in the form of HEVCCodecSpecificData
25109aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (memcmp("\x00\x00\x00\x01", data, 4)) {
25119aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return copyHEVCCodecSpecificData(data, size);
25129aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
25139aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
25149aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    HevcParameterSets paramSets;
25159aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (parseHEVCCodecSpecificData(data, size, paramSets) != OK) {
25163d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim        ALOGE("failed parsing codec specific data");
25179aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
25189aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
25199aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
25209aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificData = malloc(mCodecSpecificDataSize);
25219aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
25229aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mCodecSpecificDataSize = 0;
25239aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
25249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
25259aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
25269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t err = paramSets.makeHvcc((uint8_t *)mCodecSpecificData,
25273d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim            &mCodecSpecificDataSize, mOwner->useNalLengthFour() ? 4 : 2);
25289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (err != OK) {
25293d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim        ALOGE("failed constructing HVCC atom");
25309aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return err;
25319aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
25329aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
25339aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return OK;
25349aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
25359aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
2536872a481558350634a3fd5cb67939de288af00ecbJames Dong/*
2537872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that
2538872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information
2539872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio
2540872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger
2541872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5,
2542872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined.
2543872a481558350634a3fd5cb67939de288af00ecbJames Dong */
2544872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) {
2545872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t driftTimeUs = 0;
2546872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) {
2547872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t prevDriftTimeUs = mOwner->getDriftTimeUs();
2548872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1;
2549872a481558350634a3fd5cb67939de288af00ecbJames Dong        mOwner->setDriftTimeUs(timeUs);
2550872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2551872a481558350634a3fd5cb67939de288af00ecbJames Dong}
2552872a481558350634a3fd5cb67939de288af00ecbJames Dong
255362a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuangvoid MPEG4Writer::Track::dumpTimeStamps() {
2554dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang    ALOGE("Dumping %s track's last 10 frames timestamp and frame type ", getTrackType());
255562a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang    std::string timeStampString;
2556dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang    for (std::list<TimestampDebugHelperEntry>::iterator entry = mTimestampDebugHelper.begin();
2557dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang            entry != mTimestampDebugHelper.end(); ++entry) {
2558dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang        timeStampString += "(" + std::to_string(entry->pts)+
2559dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang                "us, " + std::to_string(entry->dts) + "us " + entry->frameType + ") ";
256062a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang    }
256162a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang    ALOGE("%s", timeStampString.c_str());
256262a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang}
256362a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang
256437187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() {
256530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
256613aec890216948b0c364f8f92792129d0335f506James Dong    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
256743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    const bool hasMultipleTracks = (mOwner->numTracks() > 1);
256813aec890216948b0c364f8f92792129d0335f506James Dong    int64_t chunkTimestampUs = 0;
256913aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nChunks = 0;
25707c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar    int32_t nActualFrames = 0;        // frames containing non-CSD data (non-0 length)
257113aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nZeroLengthFrames = 0;
2572965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastTimestampUs = 0;      // Previous sample time stamp
2573965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationUs = 0;       // Between the previous two samples
2574965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t currDurationTicks = 0;    // Timescale based ticks
2575965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationTicks = 0;    // Timescale based ticks
2576965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int32_t sampleCount = 1;          // Sample count in the current stts table entry
2577000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    uint32_t previousSampleSize = 0;  // Size of the previous sample
2578a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t previousPausedDurationUs = 0;
2579965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t timestampUs = 0;
2580000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t cttsOffsetTimeUs = 0;
2581000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t currCttsOffsetTimeTicks = 0;   // Timescale based ticks
2582000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t lastCttsOffsetTimeTicks = -1;  // Timescale based ticks
258343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    int32_t cttsSampleCount = 0;           // Sample count in the current ctts table entry
2584c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t lastSamplesPerChunk = 0;
2585e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2586a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    if (mIsAudio) {
2587a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
258825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else if (mIsVideo) {
2589a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
259025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else {
259125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        prctl(PR_SET_NAME, (unsigned long)"MetadataTrackEncoding", 0, 0, 0);
2592a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    }
2593de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
2594de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (mOwner->isRealTimeRecording()) {
2595de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
2596de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    }
2597985f838934510983d8a887461e98dca60a6e858fJames Dong
2598d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong    sp<MetaData> meta_data;
259920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
260093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t err = OK;
260120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
260225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    const char *trackName = getTrackType();
260393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    while (!mDone && (err = mSource->read(&buffer)) == OK) {
260420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
260520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
260620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
260713aec890216948b0c364f8f92792129d0335f506James Dong            ++nZeroLengthFrames;
260820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
260920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
261020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2611a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // If the codec specific data has not been received yet, delay pause.
2612a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // After the codec specific data is received, discard what we received
2613a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // when the track is to be paused.
2614a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused && !mResumed) {
2615a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer->release();
2616a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer = NULL;
2617a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            continue;
2618a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2619a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
262030ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
262130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
262203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
262303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
262403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
26257c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // if config format (at track addition) already had CSD, keep that
26267c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // UNLESS we have not received any frames yet.
26277c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // TODO: for now the entire CSD has to come in one frame for encoders, even though
26287c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // they need to be spread out for decoders.
26297c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            if (mGotAllCodecSpecificData && nActualFrames > 0) {
26307c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                ALOGI("ignoring additional CSD for video track after first frame");
26317c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            } else {
26327c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                mMeta = mSource->getFormat(); // get output format after format change
26336e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang                status_t err;
26347c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                if (mIsAvc) {
26356e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang                    err = makeAVCCodecSpecificData(
26367c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            (const uint8_t *)buffer->data()
26377c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                                + buffer->range_offset(),
26387c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
26397c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                } else if (mIsHevc) {
26406e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang                    err = makeHEVCCodecSpecificData(
26417c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            (const uint8_t *)buffer->data()
26427c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                                + buffer->range_offset(),
26437c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
26447c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                } else if (mIsMPEG4) {
26457c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    copyCodecSpecificData((const uint8_t *)buffer->data() + buffer->range_offset(),
26467c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
26477c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                }
264830ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
264930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
265030ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
265130ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
26526e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang            if (OK != err) {
26536e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang                mSource->stop();
26546e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang                mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
26556e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang                       mTrackId | MEDIA_RECORDER_TRACK_ERROR_GENERAL, err);
26566e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang                break;
26576e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang            }
265830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
2659548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
266030ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
2661a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2662a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2663e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang        // Per-frame metadata sample's size must be smaller than max allowed.
2664e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang        if (!mIsVideo && !mIsAudio && buffer->range_length() >= kMaxMetadataSize) {
2665e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            ALOGW("Buffer size is %zu. Maximum metadata buffer size is %lld for %s track",
2666e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang                    buffer->range_length(), (long long)kMaxMetadataSize, trackName);
2667e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            buffer->release();
2668e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            mSource->stop();
2669e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            mIsMalformed = true;
2670e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            break;
2671e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang        }
2672e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang
26737c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar        ++nActualFrames;
26747c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar
2675d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // Make a deep copy of the MediaBuffer and Metadata and release
2676d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // the original as soon as we can
2677d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
2678d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
2679d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                buffer->range_length());
2680d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        copy->set_range(0, buffer->range_length());
2681d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data = new MetaData(*buffer->meta_data().get());
2682d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer->release();
2683d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer = NULL;
2684d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
26859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (mIsAvc || mIsHevc) StripStartcode(copy);
2686e136c3bb38e88315bf8797a464ebf2c788296b22James Dong
2687b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        size_t sampleSize = copy->range_length();
26889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (mIsAvc || mIsHevc) {
2689b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            if (mOwner->useNalLengthFour()) {
2690b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 4;
2691b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            } else {
2692b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 2;
2693b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            }
2694b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        }
2695050b28a593350047845a45a14cc5026221ac1620James Dong
2696d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        // Max file size or duration handling
26971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mMdatSizeBytes += sampleSize;
26981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        updateTrackSizeEstimate();
26991f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
2700d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileSizeLimit()) {
2701fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            if (mOwner->switchFd() != OK) {
2702fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                ALOGW("Recorded file size exceeds limit %" PRId64 "bytes",
2703fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                        mOwner->mMaxFileSizeLimitBytes);
2704fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                mSource->stop();
2705fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                mOwner->notify(
2706fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                        MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
2707fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            } else {
2708fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                ALOGV("%s Current recorded file size exceeds limit %" PRId64 "bytes. Switching output",
2709fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                        getTrackType(), mOwner->mMaxFileSizeLimitBytes);
2710fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            }
2711d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            copy->release();
2712d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2713d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2714fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
2715d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileDurationLimit()) {
2716316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang            ALOGW("Recorded file duration exceeds limit %" PRId64 "microseconds",
2717316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang                    mOwner->mMaxFileDurationLimitUs);
2718d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
2719d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            copy->release();
2720d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            mSource->stop();
2721d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2722d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2723d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2724fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        if (mOwner->approachingFileSizeLimit()) {
2725fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mOwner->notifyApproachingLimit();
2726fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        }
2727050b28a593350047845a45a14cc5026221ac1620James Dong
2728d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        int32_t isSync = false;
2729d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
2730d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
2731d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
2732fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        // For video, skip the first several non-key frames until getting the first key frame.
2733fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        if (mIsVideo && !mGotStartKeyFrame && !isSync) {
2734fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            ALOGD("Video skip non-key frame");
2735fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            copy->release();
2736fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            continue;
2737fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        }
2738fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        if (mIsVideo && isSync) {
2739fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mGotStartKeyFrame = true;
2740fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        }
2741d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong////////////////////////////////////////////////////////////////////////////////
2742c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (mStszTableEntries->count() == 0) {
274370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mFirstSampleTimeRealUs = systemTime() / 1000;
2744f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimestampUs = timestampUs;
2745f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mOwner->setStartTimestampUs(mStartTimestampUs);
27468428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs = mStartTimestampUs;
27473c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        }
274848c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
2749a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mResumed) {
27508428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
275111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) {
275211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
2753d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang                mSource->stop();
27549db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                mIsMalformed = true;
27559db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                break;
275611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
275711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
27588428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
275911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) {
276011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
2761d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang                mSource->stop();
27629db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                mIsMalformed = true;
27639db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                break;
276411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
276511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
27668428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs += pausedDurationUs - lastDurationUs;
2767a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mResumed = false;
2768a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2769dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang        TimestampDebugHelperEntry timestampDebugEntry;
2770a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        timestampUs -= previousPausedDurationUs;
2771dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang        timestampDebugEntry.pts = timestampUs;
277211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
277311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
2774d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            mSource->stop();
27759db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            mIsMalformed = true;
27769db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            break;
277711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        }
277811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
277925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        if (mIsVideo) {
2780965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            /*
2781965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Composition time: timestampUs
2782965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Decoding time: decodingTimeUs
2783000e18370baae60ffd9f25b509501dd8c26deabfJames Dong             * Composition time offset = composition time - decoding time
2784965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             */
2785965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            int64_t decodingTimeUs;
2786965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
2787965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            decodingTimeUs -= previousPausedDurationUs;
2788826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar
2789826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            // ensure non-negative, monotonic decoding time
2790826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            if (mLastDecodingTimeUs < 0) {
2791826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar                decodingTimeUs = std::max((int64_t)0, decodingTimeUs);
2792826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            } else {
279338f4cbed37d5788e488fd39ccab0c78b07e89207Hangyu Kuang                // increase decoding time by at least the larger vaule of 1 tick and
279438f4cbed37d5788e488fd39ccab0c78b07e89207Hangyu Kuang                // 0.1 milliseconds. This needs to take into account the possible
279538f4cbed37d5788e488fd39ccab0c78b07e89207Hangyu Kuang                // delta adjustment in DurationTicks in below.
279638f4cbed37d5788e488fd39ccab0c78b07e89207Hangyu Kuang                decodingTimeUs = std::max(mLastDecodingTimeUs +
279738f4cbed37d5788e488fd39ccab0c78b07e89207Hangyu Kuang                        std::max(100, divUp(1000000, mTimeScale)), decodingTimeUs);
2798826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            }
2799826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar
2800826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            mLastDecodingTimeUs = decodingTimeUs;
2801dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang            timestampDebugEntry.dts = decodingTimeUs;
2802dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang            timestampDebugEntry.frameType = isSync ? "Key frame" : "Non-Key frame";
2803dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang            // Insert the timestamp into the mTimestampDebugHelper
2804dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang            if (mTimestampDebugHelper.size() >= kTimestampDebugCount) {
2805dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang                mTimestampDebugHelper.pop_front();
2806dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang            }
2807dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang            mTimestampDebugHelper.push_back(timestampDebugEntry);
2808dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang
2809000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            cttsOffsetTimeUs =
2810000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
281111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) {
281211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
2813d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang                mSource->stop();
28149db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                mIsMalformed = true;
28159db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                break;
281611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
281711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2818965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            timestampUs = decodingTimeUs;
2819a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGV("decoding time: %" PRId64 " and ctts offset time: %" PRId64,
2820000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                timestampUs, cttsOffsetTimeUs);
2821000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2822000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts box table if necessary
2823000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            currCttsOffsetTimeTicks =
2824000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL;
282511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) {
282611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
2827d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang                mSource->stop();
28289db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                mIsMalformed = true;
28299db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                break;
283011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
283111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2832c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 0) {
283343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // Force the first ctts table entry to have one single entry
283443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // so that we can do adjustment for the initial track start
283543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // time offset easily in writeCttsBox().
283643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
283743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                addOneCttsTableEntry(1, currCttsOffsetTimeTicks);
283843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                cttsSampleCount = 0;      // No sample in ctts box is pending
283943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            } else {
284043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) {
284143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
284243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
284343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    cttsSampleCount = 1;  // One sample in ctts box is pending
284443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                } else {
284543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    ++cttsSampleCount;
284643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                }
284743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            }
2848000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2849000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts time offset range
2850c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 0) {
2851230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang                mMinCttsOffsetTicks = currCttsOffsetTimeTicks;
2852230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang                mMaxCttsOffsetTicks = currCttsOffsetTimeTicks;
2853000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            } else {
2854230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang                if (currCttsOffsetTimeTicks > mMaxCttsOffsetTicks) {
2855230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang                    mMaxCttsOffsetTicks = currCttsOffsetTimeTicks;
2856230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang                } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTicks) {
2857230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang                    mMinCttsOffsetTicks = currCttsOffsetTimeTicks;
2858230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang                    mMinCttsOffsetTimeUs = cttsOffsetTimeUs;
2859000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                }
2860000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            }
2861965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        }
2862872a481558350634a3fd5cb67939de288af00ecbJames Dong
2863de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        if (mOwner->isRealTimeRecording()) {
2864872a481558350634a3fd5cb67939de288af00ecbJames Dong            if (mIsAudio) {
2865872a481558350634a3fd5cb67939de288af00ecbJames Dong                updateDriftTime(meta_data);
2866e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
2867e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
2868872a481558350634a3fd5cb67939de288af00ecbJames Dong
286911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
287011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
2871d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            mSource->stop();
28729db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            mIsMalformed = true;
28739db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            break;
287411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        }
287511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2876a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("%s media time stamp: %" PRId64 " and previous paused duration %" PRId64,
287711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                trackName, timestampUs, previousPausedDurationUs);
2878c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong        if (timestampUs > mTrackDurationUs) {
2879c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong            mTrackDurationUs = timestampUs;
28803b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        }
28813b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber
28825a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // We need to use the time scale based ticks, rather than the
28835a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // timestamp itself to determine whether we have to use a new
28845a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // stts entry, since we may have rounding errors.
28855a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // The calculation is intended to reduce the accumulated
28865a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // rounding errors.
28875a217fba010e801c255503602bda4b86ac5a6ac9James Dong        currDurationTicks =
28885a217fba010e801c255503602bda4b86ac5a6ac9James Dong            ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
28895a217fba010e801c255503602bda4b86ac5a6ac9James Dong                (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
2890c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (currDurationTicks < 0ll) {
2891f85a83af8c6a98b46c394c32b90b09214a68f3e4Hangyu Kuang            ALOGE("do not support out of order frames (timestamp: %lld < last: %lld for %s track",
2892f85a83af8c6a98b46c394c32b90b09214a68f3e4Hangyu Kuang                    (long long)timestampUs, (long long)lastTimestampUs, trackName);
289311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
28940332fadec6e91c37fe39ab92b2c02922370bc853Hangyu Kuang            mSource->stop();
28959db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            mIsMalformed = true;
28969db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            break;
28978c460498c028888c533ab442be12b6d4b669b965James Dong        }
28988c460498c028888c533ab442be12b6d4b669b965James Dong
289985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // if the duration is different for this sample, see if it is close enough to the previous
290085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // duration that we can fudge it and use the same value, to avoid filling the stts table
290185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // with lots of near-identical entries.
290285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // "close enough" here means that the current duration needs to be adjusted by less
290385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // than 0.1 milliseconds
290485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) {
290585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL
290685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                    + (mTimeScale / 2)) / mTimeScale;
290785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            if (deltaUs > -100 && deltaUs < 100) {
290885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                // use previous ticks, and adjust timestamp as if it was actually that number
290985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                // of ticks
291085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                currDurationTicks = lastDurationTicks;
291185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                timestampUs += deltaUs;
291285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            }
291385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        }
2914c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStszTableEntries->add(htonl(sampleSize));
2915c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (mStszTableEntries->count() > 2) {
2916c059860c73678a202bfa33062723e8f82fb779d9James Dong
2917a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // Force the first sample to have its own stts entry so that
2918a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // we can adjust its value later to maintain the A/V sync.
2919c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) {
292079761ab096f57c3027fad9556c2bc436672d614eJames Dong                addOneSttsTableEntry(sampleCount, lastDurationTicks);
2921be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                sampleCount = 1;
2922be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
2923be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                ++sampleCount;
2924be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
2925965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2926be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
2927be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        if (mSamplesHaveSameSize) {
2928c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) {
2929be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSamplesHaveSameSize = false;
2930be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
29318644c14618d30d9e57a69df40ed939986ebf02c4James Dong            previousSampleSize = sampleSize;
2932be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
2933a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("%s timestampUs/lastTimestampUs: %" PRId64 "/%" PRId64,
293411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                trackName, timestampUs, lastTimestampUs);
29358644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastDurationUs = timestampUs - lastTimestampUs;
2936c059860c73678a202bfa33062723e8f82fb779d9James Dong        lastDurationTicks = currDurationTicks;
29378644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastTimestampUs = timestampUs;
293820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2939d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        if (isSync != 0) {
2940c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            addOneStssTableEntry(mStszTableEntries->count());
2941d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        }
2942d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
294393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (mTrackingProgressStatus) {
294493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            if (mPreviousTrackTimeUs <= 0) {
294593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong                mPreviousTrackTimeUs = mStartTimestampUs;
294693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            }
2947faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong            trackProgressStatus(timestampUs);
294893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
294943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        if (!hasMultipleTracks) {
295080f78b773f92048944a850efb7b60629643370cdPraveen Chavan            off64_t offset = (mIsAvc || mIsHevc) ? mOwner->addMultipleLengthPrefixedSamples_l(copy)
295158ae9c530247668f8af36e30d228c716c226b3d4James Dong                                 : mOwner->addSample_l(copy);
2952c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2953c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t count = (mOwner->use32BitFileOffset()
2954c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        ? mStcoTableEntries->count()
2955c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        : mCo64TableEntries->count());
2956c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2957c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (count == 0) {
29581f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                addChunkOffset(offset);
295958ae9c530247668f8af36e30d228c716c226b3d4James Dong            }
296058ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy->release();
296158ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy = NULL;
296258ae9c530247668f8af36e30d228c716c226b3d4James Dong            continue;
296358ae9c530247668f8af36e30d228c716c226b3d4James Dong        }
296413aec890216948b0c364f8f92792129d0335f506James Dong
296513aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.push_back(copy);
296613aec890216948b0c364f8f92792129d0335f506James Dong        if (interleaveDurationUs == 0) {
29671f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStscTableEntry(++nChunks, 1);
29681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            bufferChunk(timestampUs);
296913aec890216948b0c364f8f92792129d0335f506James Dong        } else {
297013aec890216948b0c364f8f92792129d0335f506James Dong            if (chunkTimestampUs == 0) {
297113aec890216948b0c364f8f92792129d0335f506James Dong                chunkTimestampUs = timestampUs;
297213aec890216948b0c364f8f92792129d0335f506James Dong            } else {
297343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                int64_t chunkDurationUs = timestampUs - chunkTimestampUs;
297443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                if (chunkDurationUs > interleaveDurationUs) {
297543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    if (chunkDurationUs > mMaxChunkDurationUs) {
297643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                        mMaxChunkDurationUs = chunkDurationUs;
297743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    }
297813aec890216948b0c364f8f92792129d0335f506James Dong                    ++nChunks;
297913aec890216948b0c364f8f92792129d0335f506James Dong                    if (nChunks == 1 ||  // First chunk
2980c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk != mChunkSamples.size()) {
2981c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk = mChunkSamples.size();
2982c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        addOneStscTableEntry(nChunks, lastSamplesPerChunk);
298313aec890216948b0c364f8f92792129d0335f506James Dong                    }
29841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                    bufferChunk(timestampUs);
298513aec890216948b0c364f8f92792129d0335f506James Dong                    chunkTimestampUs = timestampUs;
298613aec890216948b0c364f8f92792129d0335f506James Dong                }
298713aec890216948b0c364f8f92792129d0335f506James Dong            }
298813aec890216948b0c364f8f92792129d0335f506James Dong        }
298913aec890216948b0c364f8f92792129d0335f506James Dong
299020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
299125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
299245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (isTrackMalFormed()) {
299362a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang        dumpTimeStamps();
2994690f546b0ee548dbfe997df36418e5302ec2d786James Dong        err = ERROR_MALFORMED;
2995f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    }
299645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
2997bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    mOwner->trackProgressStatus(mTrackId, -1, err);
2998be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
299913aec890216948b0c364f8f92792129d0335f506James Dong    // Last chunk
300043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (!hasMultipleTracks) {
3001c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        addOneStscTableEntry(1, mStszTableEntries->count());
300258ae9c530247668f8af36e30d228c716c226b3d4James Dong    } else if (!mChunkSamples.empty()) {
30031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        addOneStscTableEntry(++nChunks, mChunkSamples.size());
30041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        bufferChunk(timestampUs);
300513aec890216948b0c364f8f92792129d0335f506James Dong    }
300613aec890216948b0c364f8f92792129d0335f506James Dong
3007be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // We don't really know how long the last frame lasts, since
3008be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // there is no frame time after it, just repeat the previous
3009be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // frame's duration.
3010c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() == 1) {
30118f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        lastDurationUs = 0;  // A single sample's duration
301279761ab096f57c3027fad9556c2bc436672d614eJames Dong        lastDurationTicks = 0;
3013be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    } else {
3014be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        ++sampleCount;  // Count for the last sample
3015be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    }
3016a472613aec322e25891abf5c77bf3f7e3c244920James Dong
3017c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() <= 2) {
301879761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(1, lastDurationTicks);
3019a472613aec322e25891abf5c77bf3f7e3c244920James Dong        if (sampleCount - 1 > 0) {
302079761ab096f57c3027fad9556c2bc436672d614eJames Dong            addOneSttsTableEntry(sampleCount - 1, lastDurationTicks);
3021a472613aec322e25891abf5c77bf3f7e3c244920James Dong        }
3022a472613aec322e25891abf5c77bf3f7e3c244920James Dong    } else {
302379761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(sampleCount, lastDurationTicks);
3024a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
3025a472613aec322e25891abf5c77bf3f7e3c244920James Dong
302643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // The last ctts box may not have been written yet, and this
302743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // is to make sure that we write out the last ctts box.
302843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) {
302943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        if (cttsSampleCount > 0) {
303043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
303143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        }
303243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    }
303343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong
3034c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs += lastDurationUs;
303525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
303643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
303743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    sendTrackSummary(hasMultipleTracks);
303843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
3039df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
304011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            count, nZeroLengthFrames, mStszTableEntries->count(), trackName);
3041872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (mIsAudio) {
3042a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Audio track drift time: %" PRId64 " us", mOwner->getDriftTimeUs());
3043872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
3044365a963142093a1cd8efdcea76b5f65096a5b115James Dong
304537187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err == ERROR_END_OF_STREAM) {
304637187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
304737187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
304837187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
3049365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
3050365a963142093a1cd8efdcea76b5f65096a5b115James Dong
305145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const {
30529db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang    if (mIsMalformed) {
30539db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang        return true;
30549db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang    }
30559db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang
3056c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() == 0) {                      // no samples written
305729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("The number of recorded samples is 0");
305845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
305945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
306045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
306125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (mIsVideo && mStssTableEntries->count() == 0) {  // no sync frames for video
306229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("There are no sync frames for video track");
306345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
306445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
306545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
306645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (OK != checkCodecSpecificData()) {         // no codec specific data
306745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
306845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
306945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
307045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    return false;
307145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong}
307245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
307343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) {
307407ec01904613a0bac32caaa8444b4690998faed7James Dong
307507ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send track summary only if test mode is enabled.
307607ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
307707ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
307807ec01904613a0bac32caaa8444b4690998faed7James Dong    }
307907ec01904613a0bac32caaa8444b4690998faed7James Dong
308043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int trackNum = (mTrackId << 28);
308143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
308243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
308343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE,
308425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang                    mIsAudio ? 0: 1);
308543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
308643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
308743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS,
308843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mTrackDurationUs / 1000);
308943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
309043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
309143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES,
3092c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    mStszTableEntries->count());
309343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
309486b7f47aa7482424cf8fd248f1315311919be3b0James Dong    {
309586b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // The system delay time excluding the requested initial delay that
309686b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // is used to eliminate the recording sound.
309786b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
309886b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
309986b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
310086b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
310186b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t initialDelayUs =
310286b7f47aa7482424cf8fd248f1315311919be3b0James Dong            mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs;
310386b7f47aa7482424cf8fd248f1315311919be3b0James Dong
310486b7f47aa7482424cf8fd248f1315311919be3b0James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
310570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS,
310670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    (initialDelayUs) / 1000);
310786b7f47aa7482424cf8fd248f1315311919be3b0James Dong    }
310870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
310907ec01904613a0bac32caaa8444b4690998faed7James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
311007ec01904613a0bac32caaa8444b4690998faed7James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES,
311107ec01904613a0bac32caaa8444b4690998faed7James Dong                    mMdatSizeBytes / 1024);
311207ec01904613a0bac32caaa8444b4690998faed7James Dong
311343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (hasMultipleTracks) {
311443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
311543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS,
311643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mMaxChunkDurationUs / 1000);
311770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
311870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
311970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        if (mStartTimestampUs != moovStartTimeUs) {
312070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
312170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
312270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS,
312370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    startTimeOffsetUs / 1000);
312470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        }
312543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    }
312643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong}
312743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
3128faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
3129a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("trackProgressStatus: %" PRId64 " us", timeUs);
3130c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
3131215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    if (mTrackEveryTimeDurationUs > 0 &&
3132215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
3133a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("Fire time tracking progress status at %" PRId64 " us", timeUs);
3134bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err);
313593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        mPreviousTrackTimeUs = timeUs;
313693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
313793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
313893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
3139faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus(
3140bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        size_t trackId, int64_t timeUs, status_t err) {
3141faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    Mutex::Autolock lock(mLock);
3142bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t trackNum = (trackId << 28);
3143faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
3144faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Error notification
3145faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Do not consider ERROR_END_OF_STREAM an error
3146faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (err != OK && err != ERROR_END_OF_STREAM) {
3147bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
3148bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL,
3149faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
3150faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
3151faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
3152faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
3153faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (timeUs == -1) {
3154faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send completion notification
3155bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
3156bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS,
3157faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
3158faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    } else {
3159faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send progress status
3160bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
3161bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME,
3162faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               timeUs / 1000);
3163faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
3164faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong}
3165faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
3166d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) {
3167a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("setDriftTimeUs: %" PRId64 " us", driftTimeUs);
3168e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
3169d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    mDriftTimeUs = driftTimeUs;
3170e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
3171e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
3172e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() {
3173a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("getDriftTimeUs: %" PRId64 " us", mDriftTimeUs);
3174e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
3175e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    return mDriftTimeUs;
3176e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
3177e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
3178de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghuibool MPEG4Writer::isRealTimeRecording() const {
3179de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    return mIsRealTimeRecording;
3180de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui}
3181de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
3182b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() {
3183b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    return mUse4ByteNalLength;
3184b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong}
3185b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
31861c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
31873856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk");
31881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
31891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Chunk chunk(this, timestampUs, mChunkSamples);
31901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mOwner->bufferChunk(chunk);
319113aec890216948b0c364f8f92792129d0335f506James Dong    mChunkSamples.clear();
319220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
319320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31943b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
3195230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    return mTrackDurationUs + getStartTimeOffsetTimeUs();
319620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
319720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3198d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
3199d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return mEstimatedTrackSizeBytes;
3200d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
3201d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
3202690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const {
3203690f546b0ee548dbfe997df36418e5302ec2d786James Dong    const char *mime;
3204690f546b0ee548dbfe997df36418e5302ec2d786James Dong    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
3205690f546b0ee548dbfe997df36418e5302ec2d786James Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
3206690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
32079aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime) ||
32089aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        !strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
3209690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (!mCodecSpecificData ||
3210690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize <= 0) {
321129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Missing codec specific data");
3212690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
3213690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
3214690f546b0ee548dbfe997df36418e5302ec2d786James Dong    } else {
3215690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (mCodecSpecificData ||
3216690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize > 0) {
321729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Unexepected codec specific data found");
3218690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
3219690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
3220690f546b0ee548dbfe997df36418e5302ec2d786James Dong    }
3221690f546b0ee548dbfe997df36418e5302ec2d786James Dong    return OK;
3222690f546b0ee548dbfe997df36418e5302ec2d786James Dong}
3223690f546b0ee548dbfe997df36418e5302ec2d786James Dong
322425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangconst char *MPEG4Writer::Track::getTrackType() const {
322525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    return mIsAudio ? "Audio" : (mIsVideo ? "Video" : "Metadata");
322625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang}
32278f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
322825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) {
3229efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
3230b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("trak");
3231b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeTkhdBox(now);
3232b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("mdia");
3233b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeMdhdBox(now);
3234b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeHdlrBox();
3235b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->beginBox("minf");
3236b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                if (mIsAudio) {
3237b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeSmhdBox();
323825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang                } else if (mIsVideo) {
3239b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeVmhdBox();
324025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang                } else {
324125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang                    writeNmhdBox();
3242b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                }
3243b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeDinfBox();
3244b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeStblBox(use32BitOffset);
3245b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->endBox();  // minf
3246b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->endBox();  // mdia
3247b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // trak
3248b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3249b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3250230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuangint64_t MPEG4Writer::Track::getMinCttsOffsetTimeUs() {
3251230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    // For video tracks with ctts table, this should return the minimum ctts
3252230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    // offset in the table. For non-video tracks or video tracks without ctts
3253230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    // table, this will return kMaxCttsOffsetTimeUs.
3254230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    if (mMinCttsOffsetTicks == mMaxCttsOffsetTicks) {
3255230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        return kMaxCttsOffsetTimeUs;
3256230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    }
3257230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    return mMinCttsOffsetTimeUs;
3258230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang}
3259230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang
3260b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) {
3261b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stbl");
3262b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsd");
3263b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);               // version=0, flags=0
3264b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);               // entry count
3265b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
3266b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAudioFourCCBox();
326725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else if (mIsVideo) {
3268b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeVideoFourCCBox();
326925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else {
327025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        writeMetadataFourCCBox();
3271b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3272b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsd
3273b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeSttsBox();
327425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (mIsVideo) {
327525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        writeCttsBox();
3276b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeStssBox();
3277b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3278b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStszBox();
3279b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStscBox();
3280b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStcoBox(use32BitOffset);
3281b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stbl
3282b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3283b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
328425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeMetadataFourCCBox() {
328525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    const char *mime;
328625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    bool success = mMeta->findCString(kKeyMIMEType, &mime);
328725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    CHECK(success);
328825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    const char *fourcc = getFourCCForMime(mime);
328925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (fourcc == NULL) {
329025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        ALOGE("Unknown mime type '%s'.", mime);
329125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        TRESPASS();
329225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    }
329325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->beginBox(fourcc);    // TextMetaDataSampleEntry
329425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->writeCString(mime);  // metadata mime_format
329525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->endBox(); // mett
329625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang}
329725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang
3298b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() {
3299b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
3300b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
3301b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
33028b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    const char *fourcc = getFourCCForMime(mime);
33038b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (fourcc == NULL) {
330429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
330525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        TRESPASS();
3306b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3307b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
33088b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    mOwner->beginBox(fourcc);        // video format
3309b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3310b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3311b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // data ref index
3312b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
3313b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3314b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
3315b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
3316b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
3317b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3318b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t width, height;
3319b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeyWidth, &width);
3320b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = success && mMeta->findInt32(kKeyHeight, &height);
3321b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
3322b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3323b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(width);
3324b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(height);
3325b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // horiz resolution
3326b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // vert resolution
3327b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3328b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // frame count
3329c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo    mOwner->writeInt8(0);            // compressor string length
3330c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo    mOwner->write("                               ", 31);
3331b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x18);        // depth
3332b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(-1);          // predefined
3333b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3334b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
3335b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4vEsdsBox();
3336b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
3337b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeD263Box();
3338b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
3339b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAvccBox();
33409aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
33419aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        writeHvccBox();
3342b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3343b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3344b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writePaspBox();
334558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    writeColrBox();
3346b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // mp4v, s263 or avc1
3347b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3348b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
334958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnarvoid MPEG4Writer::Track::writeColrBox() {
335058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    ColorAspects aspects;
335158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    memset(&aspects, 0, sizeof(aspects));
335258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    // TRICKY: using | instead of || because we want to execute all findInt32-s
335358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    if (mMeta->findInt32(kKeyColorPrimaries, (int32_t*)&aspects.mPrimaries)
335458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyTransferFunction, (int32_t*)&aspects.mTransfer)
335558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyColorMatrix, (int32_t*)&aspects.mMatrixCoeffs)
335658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyColorRange, (int32_t*)&aspects.mRange)) {
335758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        int32_t primaries, transfer, coeffs;
335858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        bool fullRange;
335958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        ColorUtils::convertCodecColorAspectsToIsoAspects(
336058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar                aspects, &primaries, &transfer, &coeffs, &fullRange);
336158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->beginBox("colr");
336258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeFourcc("nclx");
336358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(primaries);
336458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(transfer);
336558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(coeffs);
3366fffb0c8fbe16ac948619b85e1eea9e65a9daa0c9Pirama Arumuga Nainar        mOwner->writeInt8(int8_t(fullRange ? 0x80 : 0x0));
336758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->endBox(); // colr
336858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    }
336958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar}
337058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
3371b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() {
3372b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
3373b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
3374b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
33758b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    const char *fourcc = getFourCCForMime(mime);
33768b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (fourcc == NULL) {
337729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
337825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        TRESPASS();
3379b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3380b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3381b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(fourcc);        // audio format
3382b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3383b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3384b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x1);         // data ref index
3385b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3386b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3387b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t nChannels;
3388b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
3389b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(nChannels);   // channel count
3390b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(16);          // sample size
3391b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
3392b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3393b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3394b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t samplerate;
3395b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeySampleRate, &samplerate);
3396b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
3397b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(samplerate << 16);
3398b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
3399b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4aEsdsBox();
3400b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
3401b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong               !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
3402b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeDamrBox();
3403b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3404b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3405b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3406b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3407b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() {
3408b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
3409b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
3410b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_GT(mCodecSpecificDataSize, 0u);
3411b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3412b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Make sure all sizes encode to a single byte.
3413b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_LT(mCodecSpecificDataSize + 23, 128u);
3414b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3415b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);     // version=0, flags=0
3416b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);   // ES_DescrTag
3417b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
3418b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);// ES_ID
3419b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x00);
3420b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3421b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
3422b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
3423b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
3424b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x15);   // streamType AudioStream
3425b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3426b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x03);  // XXX
342746f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt8(0x00);   // buffer size 24-bit (0x300)
342846f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar
342996bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t avgBitrate = 0;
343046f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyBitRate, &avgBitrate);
343196bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t maxBitrate = 0;
343246f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate);
343346f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(maxBitrate);
343446f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(avgBitrate);
3435b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3436b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
3437b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
3438b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3439b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3440b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
3441b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
3442b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
3443b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
3444b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3445b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
3446b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3447b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
3448b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3449b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3450b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() {
3451b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
3452b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_GT(mCodecSpecificDataSize, 0u);
3453bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan
3454bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan    // Make sure all sizes encode to a single byte.
3455b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_LT(23 + mCodecSpecificDataSize, 128u);
3456bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan
3457b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
3458b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3459b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);    // version=0, flags=0
3460b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3461b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);  // ES_DescrTag
3462b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
3463b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);  // ES_ID
3464b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x1f);
3465b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3466b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
3467b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
3468b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
3469b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x11);  // streamType VisualStream
3470b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3471b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData[] = {
347246f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar        0x01, 0x77, 0x00, // buffer size 96000 bytes
3473b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3474b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData, sizeof(kData));
3475b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
347696bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t avgBitrate = 0;
347746f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyBitRate, &avgBitrate);
347896bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t maxBitrate = 0;
347946f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate);
348046f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(maxBitrate);
348146f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(avgBitrate);
348246f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar
3483b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
3484b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3485b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
3486b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3487b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3488b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
3489b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
3490b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
3491b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
3492b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3493b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
3494b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3495b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
3496b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3497b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3498efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeTkhdBox(uint32_t now) {
3499b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("tkhd");
3500b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Flags = 7 to indicate that the track is enabled, and
3501b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // part of the presentation
3502b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x07);          // version=0, flags=7
3503b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
3504b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
3505219f195159f93d627af2b243732e3f9020511a46James Dong    mOwner->writeInt32(mTrackId);      // track id starts with 1
3506b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
35078f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t trakDurationUs = getDurationUs();
3508b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mvhdTimeScale = mOwner->getTimeScale();
3509b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t tkhdDuration =
3510b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
3511b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
3512b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3513b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3514b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // layer
3515b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // alternate group
3516b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
3517b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // reserved
3518b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3519b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCompositionMatrix(mRotation);       // matrix
352020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
352125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (!mIsVideo) {
3522b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
3523b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
3524b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
3525b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        int32_t width, height;
3526467743d462773ada299148ed5a210479affd1f4cHangyu Kuang        bool success = mMeta->findInt32(kKeyDisplayWidth, &width);
3527467743d462773ada299148ed5a210479affd1f4cHangyu Kuang        success = success && mMeta->findInt32(kKeyDisplayHeight, &height);
3528467743d462773ada299148ed5a210479affd1f4cHangyu Kuang
3529467743d462773ada299148ed5a210479affd1f4cHangyu Kuang        // Use width/height if display width/height are not present.
3530467743d462773ada299148ed5a210479affd1f4cHangyu Kuang        if (!success) {
3531467743d462773ada299148ed5a210479affd1f4cHangyu Kuang            success = mMeta->findInt32(kKeyWidth, &width);
3532467743d462773ada299148ed5a210479affd1f4cHangyu Kuang            success = success && mMeta->findInt32(kKeyHeight, &height);
3533467743d462773ada299148ed5a210479affd1f4cHangyu Kuang        }
3534b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(success);
3535b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3536b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
3537b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
3538b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3539b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // tkhd
3540b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3541b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3542b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() {
3543b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("vmhd");
3544b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x01);        // version=0, flags=1
3545b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // graphics mode
3546b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // opcolor
3547b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
3548b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
3549b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3550b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3551b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3552b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() {
3553b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("smhd");
3554b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // version=0, flags=0
3555b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // balance
3556b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3557b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3558b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3559b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
356025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeNmhdBox() {
356125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->beginBox("nmhd");
356225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->writeInt32(0);           // version=0, flags=0
356325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->endBox();
356425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang}
356525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang
3566b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() {
3567b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("hdlr");
3568b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
3569b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // component type: should be mhlr
357025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->writeFourcc(mIsAudio ? "soun" : (mIsVideo ? "vide" : "meta"));  // component subtype
3571b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3572b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3573b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3574b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Removing "r" for the name string just makes the string 4 byte aligned
357525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->writeCString(mIsAudio ? "SoundHandle": (mIsVideo ? "VideoHandle" : "MetadHandle"));
3576b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3577b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3578b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3579efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeMdhdBox(uint32_t now) {
3580b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t trakDurationUs = getDurationUs();
35811d515f4b608f1e6592780365857855962c0da725xiahong.bao    int64_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
3582b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("mdhd");
35831d515f4b608f1e6592780365857855962c0da725xiahong.bao
35841d515f4b608f1e6592780365857855962c0da725xiahong.bao    if (mdhdDuration > UINT32_MAX) {
35851d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt32((1 << 24));            // version=1, flags=0
35861d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt64((int64_t)now);         // creation time
35871d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt64((int64_t)now);         // modification time
35881d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt32(mTimeScale);           // media timescale
35891d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt64(mdhdDuration);         // media timescale
35901d515f4b608f1e6592780365857855962c0da725xiahong.bao    } else {
35911d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt32(0);                      // version=0, flags=0
35921d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt32(now);                    // creation time
35931d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt32(now);                    // modification time
35941d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt32(mTimeScale);             // media timescale
35951d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt32((int32_t)mdhdDuration);  // use media timescale
35961d515f4b608f1e6592780365857855962c0da725xiahong.bao    }
3597b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Language follows the three letter standard ISO-639-2/T
3598b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 'e', 'n', 'g' for "English", for instance.
3599b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Each character is packed as the difference between its ASCII value and 0x60.
3600b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // For "English", these are 00101, 01110, 00111.
3601b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // XXX: Where is the padding bit located: 0x15C7?
3602decc50efede28c5d73137c30d1a95d72dd405555David Yeh    const char *lang = NULL;
3603decc50efede28c5d73137c30d1a95d72dd405555David Yeh    int16_t langCode = 0;
3604decc50efede28c5d73137c30d1a95d72dd405555David Yeh    if (mMeta->findCString(kKeyMediaLanguage, &lang) && lang && strnlen(lang, 3) > 2) {
3605decc50efede28c5d73137c30d1a95d72dd405555David Yeh        langCode = ((lang[0] & 0x1f) << 10) | ((lang[1] & 0x1f) << 5) | (lang[2] & 0x1f);
3606decc50efede28c5d73137c30d1a95d72dd405555David Yeh    }
3607decc50efede28c5d73137c30d1a95d72dd405555David Yeh    mOwner->writeInt16(langCode);      // language code
3608b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // predefined
3609b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3610b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3611b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3612b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() {
3613b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 3gpp2 Spec AMRSampleEntry fields
3614b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("damr");
3615b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString("   ");  // vendor: 4 bytes
3616b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // decoder version
3617b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x83FF);   // mode set: all enabled
3618b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // mode change period
3619b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(1);         // frames per sample
3620b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3621b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3622b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3623b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() {
3624b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // The table index here refers to the sample description index
3625b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // in the sample table entries.
3626b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("url ");
3627b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
3628b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // url
3629b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3630b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3631b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() {
3632b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dref");
3633b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3634b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // entry count (either url or urn)
3635b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeUrlBox();
3636b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dref
3637b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3638b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3639b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() {
3640b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dinf");
3641b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeDrefBox();
3642b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dinf
3643b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3644b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3645b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() {
3646b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
3647b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_GE(mCodecSpecificDataSize, 5u);
3648b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3649b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Patch avcc's lengthSize field to match the number
3650b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // of bytes we use to indicate the size of a nal unit.
3651b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
3652b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
3653b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("avcC");
3654b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3655b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // avcC
3656b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3657b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
36589aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
36599aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimvoid MPEG4Writer::Track::writeHvccBox() {
36609aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    CHECK(mCodecSpecificData);
3661b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_GE(mCodecSpecificDataSize, 5u);
36629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
36639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Patch avcc's lengthSize field to match the number
36649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // of bytes we use to indicate the size of a nal unit.
36659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
36669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ptr[21] = (ptr[21] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
36679aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->beginBox("hvcC");
36689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
36699aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->endBox();  // hvcC
36709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
36719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
3672b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() {
3673b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("d263");
3674b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // vendor
3675b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // decoder version
3676b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(10);  // level: 10
3677b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // profile: 0
3678b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // d263
3679b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3680b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3681b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square
3682b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() {
3683b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("pasp");
3684b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // hspacing
3685b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // vspacing
3686b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // pasp
3687b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3688b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3689230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuangint64_t MPEG4Writer::Track::getStartTimeOffsetTimeUs() const {
3690a472613aec322e25891abf5c77bf3f7e3c244920James Dong    int64_t trackStartTimeOffsetUs = 0;
3691b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
3692a9292fe1c19e8a9b43398ba3d69284c215d7589fRobert Shih    if (mStartTimestampUs != -1 && mStartTimestampUs != moovStartTimeUs) {
369343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_GT(mStartTimestampUs, moovStartTimeUs);
3694b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
3695b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
36966a5c19cae5b1958af824f349a5c3778255ecd9c7Robert Shih    return trackStartTimeOffsetUs;
36976a5c19cae5b1958af824f349a5c3778255ecd9c7Robert Shih}
36986a5c19cae5b1958af824f349a5c3778255ecd9c7Robert Shih
36996a5c19cae5b1958af824f349a5c3778255ecd9c7Robert Shihint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const {
3700230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    return (getStartTimeOffsetTimeUs() * mTimeScale + 500000LL) / 1000000LL;
3701000e18370baae60ffd9f25b509501dd8c26deabfJames Dong}
3702000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
3703000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() {
3704000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->beginBox("stts");
3705000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3706230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    if (mMinCttsOffsetTicks == mMaxCttsOffsetTicks) {
3707230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        // For non-vdeio tracks or video tracks without ctts table,
3708230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        // adjust duration of first sample for tracks to account for
3709230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        // first sample not starting at the media start time.
3710230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        // TODO: consider signaling this using some offset
3711230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        // as this is not quite correct.
3712230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        uint32_t duration;
3713230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        CHECK(mSttsTableEntries->get(duration, 1));
3714230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        duration = htonl(duration);  // Back to host byte order
3715230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1);
3716230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    }
3717c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->write(mOwner);
3718b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stts
3719b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
372020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3721965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() {
3722000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    // There is no B frame at all
3723230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    if (mMinCttsOffsetTicks == mMaxCttsOffsetTicks) {
3724000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        return;
3725000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    }
3726000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
3727965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    // Do not write ctts box when there is no need to have it.
3728c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mCttsTableEntries->count() == 0) {
3729965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
3730965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
3731965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3732a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("ctts box has %d entries with range [%" PRId64 ", %" PRId64 "]",
3733230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang            mCttsTableEntries->count(), mMinCttsOffsetTicks, mMaxCttsOffsetTicks);
3734965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3735965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->beginBox("ctts");
3736000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3737230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    int64_t deltaTimeUs = kMaxCttsOffsetTimeUs - getStartTimeOffsetTimeUs();
3738230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    int64_t delta = (deltaTimeUs * mTimeScale + 500000LL) / 1000000LL;
3739c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    mCttsTableEntries->adjustEntries([delta](size_t /* ix */, uint32_t (&value)[2]) {
3740c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        // entries are <count, ctts> pairs; adjust only ctts
3741c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        uint32_t duration = htonl(value[1]); // back to host byte order
37420d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka        // Prevent overflow and underflow
37430d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka        if (delta > duration) {
37440d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka            duration = 0;
37450d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka        } else if (delta < 0 && UINT32_MAX + delta < duration) {
37460d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka            duration = UINT32_MAX;
37470d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka        } else {
37480d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka            duration -= delta;
37490d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka        }
37500d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka        value[1] = htonl(duration);
3751c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    });
3752c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->write(mOwner);
3753965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->endBox();  // ctts
3754965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
3755965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3756b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() {
3757b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stss");
3758b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3759c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->write(mOwner);
3760b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stss
3761b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
376225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
3763b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() {
3764b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsz");
3765b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3766c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mOwner->writeInt32(0);
3767c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries->write(mOwner);
3768b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsz
3769b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
377020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3771b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() {
3772b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsc");
3773b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3774c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries->write(mOwner);
3775b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsc
3776b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
377720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3778b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) {
3779b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(use32BitOffset? "stco": "co64");
3780b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3781c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (use32BitOffset) {
3782c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->write(mOwner);
3783c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
3784c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->write(mOwner);
3785b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3786b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stco or co64
378720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
378820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
378907b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() {
379007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("udta");
379107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeGeoDataBox();
379207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
379307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
379407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
3795e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeHdlr() {
3796e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("hdlr");
3797e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Version, Flags
3798e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Predefined
3799e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeFourcc("mdta");
3800e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[0]
3801e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[1]
3802e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[2]
3803e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt8(0);  // Name (empty)
3804e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3805e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3806e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3807e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeKeys() {
3808e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3809e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3810e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("keys");
3811e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0);     // Version, Flags
3812e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(count); // Entry_count
3813e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    for (size_t i = 0; i < count; i++) {
3814e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        AMessage::Type type;
3815e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        const char *key = mMetaKeys->getEntryNameAt(i, &type);
3816e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        size_t n = strlen(key);
3817e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writeInt32(n + 8);
3818e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writeFourcc("mdta");
3819e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        write(key, n); // write without the \0
3820e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3821e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3822e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3823e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3824e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeIlst() {
3825e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3826e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3827e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("ilst");
3828e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    for (size_t i = 0; i < count; i++) {
3829e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        beginBox(i + 1); // key id (1-based)
3830e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        beginBox("data");
3831e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        AMessage::Type type;
3832e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        const char *key = mMetaKeys->getEntryNameAt(i, &type);
3833e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        switch (type) {
38347c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            case AMessage::kTypeString:
38357c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            {
38367c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                AString val;
38377c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                CHECK(mMetaKeys->findString(key, &val));
38387c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(1); // type = UTF8
38397c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0); // default country/language
38407c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                write(val.c_str(), strlen(val.c_str())); // write without \0
38417c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                break;
38427c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            }
38437c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
3844e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            case AMessage::kTypeFloat:
3845e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3846e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                float val;
3847e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                CHECK(mMetaKeys->findFloat(key, &val));
38487c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(23); // type = float32
38497c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3850e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(*reinterpret_cast<int32_t *>(&val));
3851e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3852e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3853e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3854e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            case AMessage::kTypeInt32:
3855e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3856e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                int32_t val;
3857e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                CHECK(mMetaKeys->findInt32(key, &val));
38587c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(67); // type = signed int32
38597c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3860e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(val);
3861e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3862e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3863e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3864e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            default:
3865e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3866e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                ALOGW("Unsupported key type, writing 0 instead");
38677c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(77); // type = unsigned int32
38687c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3869e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(0);
3870e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3871e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3872e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        }
3873e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        endBox(); // data
3874e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        endBox(); // key id
3875e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3876e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox(); // ilst
3877e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3878e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3879e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeMetaBox() {
3880e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3881e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    if (count == 0) {
3882e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        return;
3883e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3884e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3885e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("meta");
3886e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeHdlr();
3887e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeKeys();
3888e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeIlst();
3889e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3890e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3891e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
389207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
389307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
389407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
389507b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() {
389607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("\xA9xyz");
389707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    /*
389807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * For historical reasons, any user data start
389907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * with "\0xA9", must be followed by its assoicated
390007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * language code.
3901432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x0012: text string length
3902432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x15c7: lang (locale) code: en
390307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     */
390407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt32(0x001215c7);
390507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLatitude(mLatitudex10000);
390607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLongitude(mLongitudex10000);
390707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt8(0x2F);
390807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
390907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
391007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
391120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
3912