MPEG4Writer.cpp revision 96626b7f9a4e5c9e1e04f7f710383631d1470364
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";
753b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnar#ifdef SHOW_MODEL_BUILD
763b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnarstatic const char kMetaKey_Model[]      = "com.android.model";
777c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Build[]      = "com.android.build";
783b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnar#endif
797c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_CaptureFps[] = "com.android.capture.fps";
804dbff11975e737482537e1636051690188f3fbc4Praveen Chavanstatic const char kMetaKey_TemporalLayerCount[] = "com.android.video.temporal_layers_count";
817c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatic const uint8_t kMandatoryHevcNalUnitTypes[3] = {
839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeVps,
849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeSps,
859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypePps,
869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim};
879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatic const uint8_t kHevcNalUnitTypes[5] = {
889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeVps,
899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeSps,
909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypePps,
919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypePrefixSei,
929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeSuffixSei,
939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim};
947c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang/* uncomment to include model and build in meta */
957c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang//#define SHOW_MODEL_BUILD 1
967c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
9720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track {
9820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
99b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen    Track(MPEG4Writer *owner, const sp<IMediaSource> &source, size_t trackId);
1008f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ~Track();
10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t start(MetaData *params);
10437187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t stop();
10537187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t pause();
10625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool reachedEOS();
10720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1083b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    int64_t getDurationUs() const;
109d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t getEstimatedTrackSizeBytes() const;
110b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeTrackHeader(bool use32BitOffset = true);
1111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void bufferChunk(int64_t timestampUs);
1121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAvc() const { return mIsAvc; }
1139aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    bool isHevc() const { return mIsHevc; }
1141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAudio() const { return mIsAudio; }
1151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isMPEG4() const { return mIsMPEG4; }
116c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    void addChunkOffset(off64_t offset);
11770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int32_t getTrackId() const { return mTrackId; }
118dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    status_t dump(int fd, const Vector<String16>& args) const;
1198b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    static const char *getFourCCForMime(const char *mime);
12025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    const char *getTrackType() const;
12120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
123000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    enum {
124000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        kMaxCttsOffsetTimeUs = 1000000LL,  // 1 second
1258c460498c028888c533ab442be12b6d4b669b965James Dong        kSampleArraySize = 1000,
126000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    };
127000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
128c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    // A helper class to handle faster write box with table entries
129c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    template<class TYPE, unsigned ENTRY_SIZE>
130c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    // ENTRY_SIZE: # of values in each entry
131c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    struct ListTableEntries {
132c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        static_assert(ENTRY_SIZE > 0, "ENTRY_SIZE must be positive");
133c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        ListTableEntries(uint32_t elementCapacity)
134c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            : mElementCapacity(elementCapacity),
135c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mTotalNumTableEntries(0),
136c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mNumValuesInCurrEntry(0),
137c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCurrTableEntriesElement(NULL) {
138c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_GT(mElementCapacity, 0);
1392177f21c1ae5bf5cb8c1113a1adbe1fd7db34206Wei Jia            // Ensure no integer overflow on allocation in add().
140c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            CHECK_LT(ENTRY_SIZE, UINT32_MAX / mElementCapacity);
141c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
142c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
143c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Free the allocated memory.
144c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        ~ListTableEntries() {
145c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (!mTableEntryList.empty()) {
146c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                typename List<TYPE *>::iterator it = mTableEntryList.begin();
147c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                delete[] (*it);
148c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.erase(it);
149c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
150c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
151c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
152c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Replace the value at the given position by the given value.
153c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // There must be an existing value at the given position.
154c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order
155c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
156c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void set(const TYPE& value, uint32_t pos) {
157c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            CHECK_LT(pos, mTotalNumTableEntries * ENTRY_SIZE);
158c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
159c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            typename List<TYPE *>::iterator it = mTableEntryList.begin();
160c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            uint32_t iterations = (pos / (mElementCapacity * ENTRY_SIZE));
161c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (it != mTableEntryList.end() && iterations > 0) {
162c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++it;
163c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                --iterations;
164c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
165c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK(it != mTableEntryList.end());
166c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_EQ(iterations, 0);
167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
168c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            (*it)[(pos % (mElementCapacity * ENTRY_SIZE))] = value;
169c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
170c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
171c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Get the value at the given position by the given value.
172c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value the retrieved value at the position in network byte order.
173c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
174c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @return true if a value is found.
175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        bool get(TYPE& value, uint32_t pos) const {
176c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            if (pos >= mTotalNumTableEntries * ENTRY_SIZE) {
177c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                return false;
178c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
179c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
180c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            typename List<TYPE *>::iterator it = mTableEntryList.begin();
181c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            uint32_t iterations = (pos / (mElementCapacity * ENTRY_SIZE));
182c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (it != mTableEntryList.end() && iterations > 0) {
183c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++it;
184c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                --iterations;
185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
186c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK(it != mTableEntryList.end());
187c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_EQ(iterations, 0);
188c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
189c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            value = (*it)[(pos % (mElementCapacity * ENTRY_SIZE))];
190c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            return true;
191c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
192c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
193c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        // adjusts all values by |adjust(value)|
194c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        void adjustEntries(
195c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                std::function<void(size_t /* ix */, TYPE(& /* entry */)[ENTRY_SIZE])> update) {
196c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            size_t nEntries = mTotalNumTableEntries + mNumValuesInCurrEntry / ENTRY_SIZE;
197c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            size_t ix = 0;
198c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            for (TYPE *entryArray : mTableEntryList) {
199c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                size_t num = std::min(nEntries, (size_t)mElementCapacity);
200c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                for (size_t i = 0; i < num; ++i) {
201c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                    update(ix++, (TYPE(&)[ENTRY_SIZE])(*entryArray));
202c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                    entryArray += ENTRY_SIZE;
203c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                }
204c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                nEntries -= num;
205c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            }
206c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        }
207c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar
208c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Store a single value.
209c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order.
210c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void add(const TYPE& value) {
211c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_LT(mNumValuesInCurrEntry, mElementCapacity);
212c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries % mElementCapacity;
213c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            uint32_t nValues  = mNumValuesInCurrEntry % ENTRY_SIZE;
214c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (nEntries == 0 && nValues == 0) {
215c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                mCurrTableEntriesElement = new TYPE[ENTRY_SIZE * mElementCapacity];
216c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                CHECK(mCurrTableEntriesElement != NULL);
217c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.push_back(mCurrTableEntriesElement);
218c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
219c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
220c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            uint32_t pos = nEntries * ENTRY_SIZE + nValues;
221c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCurrTableEntriesElement[pos] = value;
222c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
223c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            ++mNumValuesInCurrEntry;
224c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            if ((mNumValuesInCurrEntry % ENTRY_SIZE) == 0) {
225c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++mTotalNumTableEntries;
226c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mNumValuesInCurrEntry = 0;
227c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
228c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
229c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
230c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Write out the table entries:
231c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 1. the number of entries goes first
232c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 2. followed by the values in the table enties in order
233c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg writer the writer to actual write to the storage
234c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void write(MPEG4Writer *writer) const {
235c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            CHECK_EQ(mNumValuesInCurrEntry % ENTRY_SIZE, 0);
236c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries;
237c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            writer->writeInt32(nEntries);
238c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            for (typename List<TYPE *>::iterator it = mTableEntryList.begin();
239c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                it != mTableEntryList.end(); ++it) {
240c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                CHECK_GT(nEntries, 0);
241c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                if (nEntries >= mElementCapacity) {
242c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                    writer->write(*it, sizeof(TYPE) * ENTRY_SIZE, mElementCapacity);
243c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    nEntries -= mElementCapacity;
244c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                } else {
245c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                    writer->write(*it, sizeof(TYPE) * ENTRY_SIZE, nEntries);
246c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    break;
247c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                }
248c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
249c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
250c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
251c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Return the number of entries in the table.
252c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t count() const { return mTotalNumTableEntries; }
253c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
254c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    private:
255c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mElementCapacity;  // # entries in an element
256c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mTotalNumTableEntries;
257c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        uint32_t         mNumValuesInCurrEntry;  // up to ENTRY_SIZE
258c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        TYPE             *mCurrTableEntriesElement;
259c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mutable List<TYPE *>     mTableEntryList;
260c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
261c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries);
262c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    };
263c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
264c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
265c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
26620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Writer *mOwner;
26720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mMeta;
268b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen    sp<IMediaSource> mSource;
26920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    volatile bool mDone;
270a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mPaused;
271a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mResumed;
272eaae38445a340c4857c1c5569475879a728e63b7James Dong    volatile bool mStarted;
2731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAvc;
2749aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    bool mIsHevc;
2751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAudio;
27625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    bool mIsVideo;
2771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsMPEG4;
2789db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang    bool mIsMalformed;
279bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t mTrackId;
280c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    int64_t mTrackDurationUs;
28143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int64_t mMaxChunkDurationUs;
282826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar    int64_t mLastDecodingTimeUs;
283e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
284d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t mEstimatedTrackSizeBytes;
2851f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t mMdatSizeBytes;
2868f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mTimeScale;
28720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_t mThread;
28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
290be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
29113aec890216948b0c364f8f92792129d0335f506James Dong    List<MediaBuffer *> mChunkSamples;
2921f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
293c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    bool                mSamplesHaveSameSize;
294c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 1> *mStszTableEntries;
295be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
296c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 1> *mStcoTableEntries;
297c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<off64_t, 1> *mCo64TableEntries;
298c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 3> *mStscTableEntries;
299c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 1> *mStssTableEntries;
300c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 2> *mSttsTableEntries;
301c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 2> *mCttsTableEntries;
302965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
303000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMinCttsOffsetTimeUs;
304000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMaxCttsOffsetTimeUs;
305965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Sequence parameter set or picture parameter set
3073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    struct AVCParamSet {
3083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        AVCParamSet(uint16_t length, const uint8_t *data)
3093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            : mLength(length), mData(data) {}
3103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
3113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t mLength;
3123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *mData;
3133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    };
3143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mSeqParamSets;
3153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mPicParamSets;
3163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileIdc;
3173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileCompatible;
3183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mLevelIdc;
3193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
32020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *mCodecSpecificData;
32120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t mCodecSpecificDataSize;
322548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    bool mGotAllCodecSpecificData;
32393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    bool mTrackingProgressStatus;
32420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool mReachedEOS;
3263c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    int64_t mStartTimestampUs;
32770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mStartTimeRealUs;
32870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mFirstSampleTimeRealUs;
32993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mPreviousTrackTimeUs;
33093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mTrackEveryTimeDurationUs;
33125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
332872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Update the audio track's drift information.
333872a481558350634a3fd5cb67939de288af00ecbJames Dong    void updateDriftTime(const sp<MetaData>& meta);
334872a481558350634a3fd5cb67939de288af00ecbJames Dong
335000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int32_t getStartTimeOffsetScaledTime() const;
336000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
33720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static void *ThreadWrapper(void *me);
33837187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t threadEntry();
33920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *parseParamSet(
3413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen);
3423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
3439aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t copyCodecSpecificData(const uint8_t *data, size_t size, size_t minLength = 0);
3449aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
345b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size);
346b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size);
347b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size);
348215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong
3499aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t makeHEVCCodecSpecificData(const uint8_t *data, size_t size);
3509aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t copyHEVCCodecSpecificData(const uint8_t *data, size_t size);
3519aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t parseHEVCCodecSpecificData(
3529aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            const uint8_t *data, size_t size, HevcParameterSets &paramSets);
3539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
354215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    // Track authoring progress status
355faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    void trackProgressStatus(int64_t timeUs, status_t err = OK);
35693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    void initTrackingProgressStatus(MetaData *params);
35703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
35819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    void getCodecSpecificDataFromInputFormatIfPossible();
35919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
360c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Determine the track time scale
361c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If it is an audio track, try to use the sampling rate as
362c059860c73678a202bfa33062723e8f82fb779d9James Dong    // the time scale; however, if user chooses the overwrite
363c059860c73678a202bfa33062723e8f82fb779d9James Dong    // value, the user-supplied time scale will be used.
364c059860c73678a202bfa33062723e8f82fb779d9James Dong    void setTimeScale();
365c059860c73678a202bfa33062723e8f82fb779d9James Dong
366690f546b0ee548dbfe997df36418e5302ec2d786James Dong    // Simple validation on the codec specific data
367690f546b0ee548dbfe997df36418e5302ec2d786James Dong    status_t checkCodecSpecificData() const;
36813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t mRotation;
369690f546b0ee548dbfe997df36418e5302ec2d786James Dong
3701f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void updateTrackSizeEstimate();
3711f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStscTableEntry(size_t chunkId, size_t sampleId);
3721f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStssTableEntry(size_t sampleId);
37379761ab096f57c3027fad9556c2bc436672d614eJames Dong
37479761ab096f57c3027fad9556c2bc436672d614eJames Dong    // Duration is time scale based
37579761ab096f57c3027fad9556c2bc436672d614eJames Dong    void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
376965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
37745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
37845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    bool isTrackMalFormed() const;
37943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    void sendTrackSummary(bool hasMultipleTracks);
3801f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
381b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Write the boxes
382b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStcoBox(bool use32BitOffset);
383b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStscBox();
384b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStszBox();
385b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStssBox();
386b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSttsBox();
387965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void writeCttsBox();
388b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeD263Box();
389b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writePaspBox();
390b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAvccBox();
3919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    void writeHvccBox();
392b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeUrlBox();
393b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDrefBox();
394b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDinfBox();
395b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDamrBox();
396efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeMdhdBox(uint32_t now);
397b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSmhdBox();
398b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVmhdBox();
39925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    void writeNmhdBox();
400b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeHdlrBox();
401efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeTkhdBox(uint32_t now);
40258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    void writeColrBox();
403b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4aEsdsBox();
404b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4vEsdsBox();
405b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAudioFourCCBox();
406b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVideoFourCCBox();
40725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    void writeMetadataFourCCBox();
408b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStblBox(bool use32BitOffset);
409b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
41020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track(const Track &);
41120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track &operator=(const Track &);
41220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
41320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
41430ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd)
415674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    : mFd(dup(fd)),
416674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong      mInitCheck(mFd < 0? NO_INIT: OK),
417de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui      mIsRealTimeRecording(true),
418b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong      mUse4ByteNalLength(true),
4191acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
420a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong      mIsFileSizeLimitExplicitlyRequested(false),
421a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
422a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
423411ba422e3635d534928ffd81abf54f4f291c739James Dong      mWriterThreadStarted(false),
42430ab66297501757d745b9ae10da61adcd891f497Andreas Huber      mOffset(0),
42513aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
426e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mMoovBoxBuffer(NULL),
427e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mMoovBoxBufferOffset(0),
428e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mWriteMoovBoxToMemory(false),
429e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mFreeBoxOffset(0),
430e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mStreamableFile(false),
4317837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
4327c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang      mMoovExtraSize(0),
43307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mInterleaveDurationUs(1000000),
434e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mTimeScale(-1),
435e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mStartTimestampUs(-1ll),
43607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLatitudex10000(0),
43707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLongitudex10000(0),
43825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang      mHasAudioTrack(false),
43925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang      mHasVideoTrack(false),
44086b7f47aa7482424cf8fd248f1315311919be3b0James Dong      mAreGeoTagsAvailable(false),
441ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar      mStartTimeOffsetMs(-1),
442ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar      mMetaKeys(new AMessage()) {
4437c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    addDeviceMeta();
4442aa74dc097fe860abc84769abf2b6e0962718471Robert Shih
4452aa74dc097fe860abc84769abf2b6e0962718471Robert Shih    // Verify mFd is seekable
4462aa74dc097fe860abc84769abf2b6e0962718471Robert Shih    off64_t off = lseek64(mFd, 0, SEEK_SET);
4472aa74dc097fe860abc84769abf2b6e0962718471Robert Shih    if (off < 0) {
4482aa74dc097fe860abc84769abf2b6e0962718471Robert Shih        ALOGE("cannot seek mFd: %s (%d)", strerror(errno), errno);
4492aa74dc097fe860abc84769abf2b6e0962718471Robert Shih        release();
4502aa74dc097fe860abc84769abf2b6e0962718471Robert Shih    }
45130ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
45230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
45320111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
4548bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong    reset();
45520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4561f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    while (!mTracks.empty()) {
4571f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        List<Track *>::iterator it = mTracks.begin();
45820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
4591f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        (*it) = NULL;
4601f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mTracks.erase(it);
46120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
46220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
46320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
46420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
465dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump(
466dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) {
467dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
468dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
469dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
470dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "   MPEG4Writer %p\n", this);
471dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
472dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     mStarted: %s\n", mStarted? "true": "false");
473dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
474dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
475dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    for (List<Track *>::iterator it = mTracks.begin();
476dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong         it != mTracks.end(); ++it) {
477dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        (*it)->dump(fd, args);
478dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    }
479dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
480dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
481dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
482dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump(
48384333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        int fd, const Vector<String16>& /* args */) const {
484dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
485dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
486dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
48725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    snprintf(buffer, SIZE, "     %s track\n", getTrackType());
488dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
489dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "       reached EOS: %s\n",
490dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong            mReachedEOS? "true": "false");
491dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
492c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    snprintf(buffer, SIZE, "       frames encoded : %d\n", mStszTableEntries->count());
49313210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
494377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    snprintf(buffer, SIZE, "       duration encoded : %" PRId64 " us\n", mTrackDurationUs);
49513210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
496dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
497dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
498dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
499dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
5008b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan// static
5018b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavanconst char *MPEG4Writer::Track::getFourCCForMime(const char *mime) {
5028b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (mime == NULL) {
5038b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        return NULL;
5048b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    }
5058b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (!strncasecmp(mime, "audio/", 6)) {
5068b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
5078b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "samr";
5088b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
5098b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "sawb";
5108b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
5118b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "mp4a";
5128b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        }
5138b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    } else if (!strncasecmp(mime, "video/", 6)) {
5148b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
5158b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "mp4v";
5168b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
5178b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "s263";
5188b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
5198b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "avc1";
5209aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
5219aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return "hvc1";
5228b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        }
52325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else if (!strncasecmp(mime, "application/", 12)) {
52425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        return "mett";
5258b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    } else {
52625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        ALOGE("Track (%s) other than video/audio/metadata is not supported", mime);
5278b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    }
5288b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    return NULL;
5298b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan}
5308b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan
531b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissenstatus_t MPEG4Writer::addSource(const sp<IMediaSource> &source) {
532bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    Mutex::Autolock l(mLock);
533bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    if (mStarted) {
53429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Attempt to add source AFTER recording is started");
535bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        return UNKNOWN_ERROR;
536bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    }
537acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
538acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    CHECK(source.get() != NULL);
539acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
540acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    const char *mime;
541acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    source->getFormat()->findCString(kKeyMIMEType, &mime);
542acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
54325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (!strncasecmp(mime, "audio/", 6)) {
54425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        if (mHasAudioTrack) {
54525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang            ALOGE("At most one audio track can be added");
54625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang            return ERROR_UNSUPPORTED;
54725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        }
54825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        mHasAudioTrack = true;
54925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    }
550acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
55125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (!strncasecmp(mime, "video/", 6)) {
55225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        if (mHasVideoTrack) {
55325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang            ALOGE("At most one video track can be added");
554acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong            return ERROR_UNSUPPORTED;
555acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        }
55625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        mHasVideoTrack = true;
557acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
558acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
55925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (Track::getFourCCForMime(mime) == NULL) {
56025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        ALOGE("Unsupported mime '%s'", mime);
56125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        return ERROR_UNSUPPORTED;
56225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    }
56325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang
56425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    // This is a metadata track or the first track of either audio or video
565acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // Go ahead to add the track.
566219f195159f93d627af2b243732e3f9020511a46James Dong    Track *track = new Track(this, source, 1 + mTracks.size());
56720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
5682dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
5692dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
57020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
57120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
57293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) {
573acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    if (mTracks.empty()) {
574acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        ALOGE("No source added");
575acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return INVALID_OPERATION;
576acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
577acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
578a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
579a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
58093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        status_t err = (*it)->start(params);
581a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
582a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (err != OK) {
583a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            for (List<Track *>::iterator it2 = mTracks.begin();
584a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                 it2 != it; ++it2) {
585a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                (*it2)->stop();
586a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            }
587a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
588a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            return err;
589a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
590a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
591a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
592a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
593a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
5947c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangvoid MPEG4Writer::addDeviceMeta() {
5957c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // add device info and estimate space in 'moov'
5967c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    char val[PROPERTY_VALUE_MAX];
5977c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    size_t n;
5987c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // meta size is estimated by adding up the following:
5997c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // - meta header structures, which occur only once (total 66 bytes)
6007c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // - size for each key, which consists of a fixed header (32 bytes),
6017c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    //   plus key length and data length.
6027c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += 66;
6037c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.build.version.release", val, NULL)
6047c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
6057c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Version, val, n + 1);
6067c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Version) + n + 32;
6077c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
6087c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#ifdef SHOW_MODEL_BUILD
6097c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.product.model", val, NULL)
6107c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
6117c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Model, val, n + 1);
6127c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Model) + n + 32;
6137c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
6147c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.build.display.id", val, NULL)
6157c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
6167c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Build, val, n + 1);
6177c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Build) + n + 32;
6187c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
6197c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#endif
6207c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang}
6217c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
6222dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
6232dec2b5be2056c6d9428897dc672185872d30d17James Dong    // This implementation is highly experimental/heurisitic.
6242dec2b5be2056c6d9428897dc672185872d30d17James Dong    //
6252dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Statistical analysis shows that metadata usually accounts
6262dec2b5be2056c6d9428897dc672185872d30d17James Dong    // for a small portion of the total file size, usually < 0.6%.
6272dec2b5be2056c6d9428897dc672185872d30d17James Dong
62878a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2,
6292dec2b5be2056c6d9428897dc672185872d30d17James Dong    // where 1MB is the common file size limit for MMS application.
63078a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MAX _MOOV_BOX_SIZE value is based on about 3
6312dec2b5be2056c6d9428897dc672185872d30d17James Dong    // minute video recording with a bit rate about 3 Mbps, because
6322dec2b5be2056c6d9428897dc672185872d30d17James Dong    // statistics also show that most of the video captured are going
6332dec2b5be2056c6d9428897dc672185872d30d17James Dong    // to be less than 3 minutes.
6342dec2b5be2056c6d9428897dc672185872d30d17James Dong
6352dec2b5be2056c6d9428897dc672185872d30d17James Dong    // If the estimation is wrong, we will pay the price of wasting
6362dec2b5be2056c6d9428897dc672185872d30d17James Dong    // some reserved space. This should not happen so often statistically.
6372dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int32_t factor = mUse32BitOffset? 1: 2;
63878a1a286f736888ae7af8860b2c424af0d978848James Dong    static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024;  // 3 KB
6392dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
6402dec2b5be2056c6d9428897dc672185872d30d17James Dong    int64_t size = MIN_MOOV_BOX_SIZE;
6412dec2b5be2056c6d9428897dc672185872d30d17James Dong
64278a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file size limit is set
643a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
64478a1a286f736888ae7af8860b2c424af0d978848James Dong        size = mMaxFileSizeLimitBytes * 6 / 1000;
64578a1a286f736888ae7af8860b2c424af0d978848James Dong    }
64678a1a286f736888ae7af8860b2c424af0d978848James Dong
64778a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file duration limit is set
64878a1a286f736888ae7af8860b2c424af0d978848James Dong    if (mMaxFileDurationLimitUs != 0) {
64978a1a286f736888ae7af8860b2c424af0d978848James Dong        if (bitRate > 0) {
65078a1a286f736888ae7af8860b2c424af0d978848James Dong            int64_t size2 =
6510ca31521644b9396829850f7400d23f9b107cc64Johan Redestig                ((mMaxFileDurationLimitUs / 1000) * bitRate * 6) / 8000000;
65278a1a286f736888ae7af8860b2c424af0d978848James Dong            if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
65378a1a286f736888ae7af8860b2c424af0d978848James Dong                // When both file size and duration limits are set,
65478a1a286f736888ae7af8860b2c424af0d978848James Dong                // we use the smaller limit of the two.
65578a1a286f736888ae7af8860b2c424af0d978848James Dong                if (size > size2) {
65678a1a286f736888ae7af8860b2c424af0d978848James Dong                    size = size2;
65778a1a286f736888ae7af8860b2c424af0d978848James Dong                }
65878a1a286f736888ae7af8860b2c424af0d978848James Dong            } else {
65978a1a286f736888ae7af8860b2c424af0d978848James Dong                // Only max file duration limit is set
66078a1a286f736888ae7af8860b2c424af0d978848James Dong                size = size2;
66178a1a286f736888ae7af8860b2c424af0d978848James Dong            }
6622dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
6632dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
66478a1a286f736888ae7af8860b2c424af0d978848James Dong
6652dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size < MIN_MOOV_BOX_SIZE) {
6662dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MIN_MOOV_BOX_SIZE;
6672dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
6682dec2b5be2056c6d9428897dc672185872d30d17James Dong
6692dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Any long duration recording will be probably end up with
6702dec2b5be2056c6d9428897dc672185872d30d17James Dong    // non-streamable mp4 file.
6712dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size > MAX_MOOV_BOX_SIZE) {
6722dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MAX_MOOV_BOX_SIZE;
6732dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
6742dec2b5be2056c6d9428897dc672185872d30d17James Dong
6757c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // Account for the extra stuff (Geo, meta keys, etc.)
6767c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    size += mMoovExtraSize;
6777c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
678a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGI("limits: %" PRId64 "/%" PRId64 " bytes/us, bit rate: %d bps and the"
679a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn         " estimated moov size %" PRId64 " bytes",
6802dec2b5be2056c6d9428897dc672185872d30d17James Dong         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
6812dec2b5be2056c6d9428897dc672185872d30d17James Dong    return factor * size;
6822dec2b5be2056c6d9428897dc672185872d30d17James Dong}
6832dec2b5be2056c6d9428897dc672185872d30d17James Dong
6842dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) {
685674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
68625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
68720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
68820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
689a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    /*
690a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * Check mMaxFileSizeLimitBytes at the beginning
691a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * since mMaxFileSizeLimitBytes may be implicitly
692a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * changed later for 32-bit file offset even if
693a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * user does not ask to set it explicitly.
694a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     */
695a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0) {
696a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong        mIsFileSizeLimitExplicitlyRequested = true;
697a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    }
698a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong
6992dec2b5be2056c6d9428897dc672185872d30d17James Dong    int32_t use64BitOffset;
7002dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (param &&
7012dec2b5be2056c6d9428897dc672185872d30d17James Dong        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
7022dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64BitOffset) {
7032dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
7042dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
7052dec2b5be2056c6d9428897dc672185872d30d17James Dong
7061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    if (mUse32BitOffset) {
7071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // Implicit 32 bit file size limit
7081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes == 0) {
7091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
7101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
7111f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
7121f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // If file size is set to be larger than the 32 bit file
7131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // size limit, treat it as an error.
7141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
715a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGW("32-bit file size limit (%" PRId64 " bytes) too big. "
716a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                 "It is changed to %" PRId64 " bytes",
717d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                mMaxFileSizeLimitBytes, kMax32BitFileSize);
718d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
7191f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
7201f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    }
7211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
722b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    int32_t use2ByteNalLength;
723b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (param &&
724b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) &&
725b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        use2ByteNalLength) {
726b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mUse4ByteNalLength = false;
7272dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
7282dec2b5be2056c6d9428897dc672185872d30d17James Dong
729de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    int32_t isRealTimeRecording;
730de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (param && param->findInt32(kKeyRealTimeRecording, &isRealTimeRecording)) {
731de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        mIsRealTimeRecording = isRealTimeRecording;
732de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    }
733de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
734065d1aff96818df54456053f1574aec8a234d0deJames Dong    mStartTimestampUs = -1;
73593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
736a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mStarted) {
737a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused) {
738a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mPaused = false;
73993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return startTracks(param);
740a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
741a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
742a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
743a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
7448f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (!param ||
7458f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
7468f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mTimeScale = 1000;
7478f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
74843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
7493856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("movie time scale: %d", mTimeScale);
7508f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
75177e8ae9967a078770416619e99ddb5b010def312James Dong    /*
75277e8ae9967a078770416619e99ddb5b010def312James Dong     * When the requested file size limit is small, the priority
75377e8ae9967a078770416619e99ddb5b010def312James Dong     * is to meet the file size limit requirement, rather than
7547b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to make the file streamable. mStreamableFile does not tell
7557b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * whether the actual recorded file is streamable or not.
75677e8ae9967a078770416619e99ddb5b010def312James Dong     */
75777e8ae9967a078770416619e99ddb5b010def312James Dong    mStreamableFile =
75877e8ae9967a078770416619e99ddb5b010def312James Dong        (mMaxFileSizeLimitBytes != 0 &&
75977e8ae9967a078770416619e99ddb5b010def312James Dong         mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes);
76077e8ae9967a078770416619e99ddb5b010def312James Dong
7617b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    /*
7627b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mWriteMoovBoxToMemory is true if the amount of data in moov box is
7637b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * smaller than the reserved free space at the beginning of a file, AND
7647b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * when the content of moov box is constructed. Note that video/audio
7657b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * frame data is always written to the file but not in the memory.
7667b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7677b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * Before stop()/reset() is called, mWriteMoovBoxToMemory is always
7687b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * false. When reset() is called at the end of a recording session,
7697b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * Moov box needs to be constructed.
7707b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7717b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 1) Right before a moov box is constructed, mWriteMoovBoxToMemory
7727b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to set to mStreamableFile so that if
7737b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * the file is intended to be streamable, it is set to true;
7747b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * otherwise, it is set to false. When the value is set to false,
7757b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * all the content of the moov box is written immediately to
7767b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * the end of the file. When the value is set to true, all the
7777b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * content of the moov box is written to an in-memory cache,
7787b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mMoovBoxBuffer, util the following condition happens. Note
7797b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * that the size of the in-memory cache is the same as the
7807b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * reserved free space at the beginning of the file.
7817b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7827b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 2) While the data of the moov box is written to an in-memory
7837b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * cache, the data size is checked against the reserved space.
7847b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * If the data size surpasses the reserved space, subsequent moov
7857b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * data could no longer be hold in the in-memory cache. This also
7867b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * indicates that the reserved space was too small. At this point,
7877b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * _all_ moov data must be written to the end of the file.
7887b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mWriteMoovBoxToMemory must be set to false to direct the write
7897b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to the file.
7907b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7917b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 3) If the data size in moov box is smaller than the reserved
7927b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * space after moov box is completely constructed, the in-memory
7937b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * cache copy of the moov box is written to the reserved free
7947b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * space. Thus, immediately after the moov is completedly
7957b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * constructed, mWriteMoovBoxToMemory is always set to false.
7967b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     */
7977b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    mWriteMoovBoxToMemory = false;
7987837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = NULL;
7997837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
8007837c17063a4c50bc856ba59418516fdab731de7James Dong
801b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeFtypBox(param);
80220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8037837c17063a4c50bc856ba59418516fdab731de7James Dong    mFreeBoxOffset = mOffset;
80420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8057837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mEstimatedMoovBoxSize == 0) {
8062dec2b5be2056c6d9428897dc672185872d30d17James Dong        int32_t bitRate = -1;
8072dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (param) {
8082dec2b5be2056c6d9428897dc672185872d30d17James Dong            param->findInt32(kKeyBitRate, &bitRate);
8092dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
8102dec2b5be2056c6d9428897dc672185872d30d17James Dong        mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
8117837c17063a4c50bc856ba59418516fdab731de7James Dong    }
81243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(mEstimatedMoovBoxSize, 8);
81377e8ae9967a078770416619e99ddb5b010def312James Dong    if (mStreamableFile) {
81477e8ae9967a078770416619e99ddb5b010def312James Dong        // Reserve a 'free' box only for streamable file
81577e8ae9967a078770416619e99ddb5b010def312James Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
81677e8ae9967a078770416619e99ddb5b010def312James Dong        writeInt32(mEstimatedMoovBoxSize);
81777e8ae9967a078770416619e99ddb5b010def312James Dong        write("free", 4);
81877e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
81977e8ae9967a078770416619e99ddb5b010def312James Dong    } else {
82077e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mOffset;
82177e8ae9967a078770416619e99ddb5b010def312James Dong    }
8227837c17063a4c50bc856ba59418516fdab731de7James Dong
8237837c17063a4c50bc856ba59418516fdab731de7James Dong    mOffset = mMdatOffset;
824c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mMdatOffset, SEEK_SET);
8251acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
8261acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("????mdat", 8);
8271acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
8281acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("\x00\x00\x00\x01mdat????????", 16);
8291acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
8301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    status_t err = startWriterThread();
8321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (err != OK) {
8331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return err;
8341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    err = startTracks(param);
837a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (err != OK) {
838a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return err;
83920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
8401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
841a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = true;
84225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
84320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
84420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8451f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const {
8461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    return mUse32BitOffset;
8471f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
8481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
84937187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() {
850674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
85137187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
852a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
853a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
85437187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
855a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
856a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
85737187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->pause();
85837187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (status != OK) {
85937187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
86037187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
861a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
86237187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
863a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
864a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
8651c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() {
866b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Stopping writer thread");
867411ba422e3635d534928ffd81abf54f4f291c739James Dong    if (!mWriterThreadStarted) {
868411ba422e3635d534928ffd81abf54f4f291c739James Dong        return;
869411ba422e3635d534928ffd81abf54f4f291c739James Dong    }
8701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
8721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
8731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mDone = true;
8751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkReadyCondition.signal();
8761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void *dummy;
8791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_join(mThread, &dummy);
880411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = false;
881b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Writer thread stopped");
8821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
8831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
88413f6284305e4b27395a23db7882d670bdb1bcae1James Dong/*
88513f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix:
88613f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a  b  u |
88713f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c  d  v |
88813f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x  y  w |
88913f6284305e4b27395a23db7882d670bdb1bcae1James Dong *
89013f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following
89113f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w},
89213f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while
89313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format.
89413f6284305e4b27395a23db7882d670bdb1bcae1James Dong */
89513f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) {
8963856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeCompositionMatrix");
89713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t a = 0x00010000;
89813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t b = 0;
89913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t c = 0;
90013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t d = 0x00010000;
90113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    switch (degrees) {
90213f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 0:
90313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
90413f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 90:
90513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
90613f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0x00010000;
90713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0xFFFF0000;
90813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
90913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
91013f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 180:
91113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0xFFFF0000;
91213f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0xFFFF0000;
91313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
91413f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 270:
91513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
91613f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0xFFFF0000;
91713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0x00010000;
91813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
91913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
92013f6284305e4b27395a23db7882d670bdb1bcae1James Dong        default:
92113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            CHECK(!"Should never reach this unknown rotation");
92213f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
92313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
92413f6284305e4b27395a23db7882d670bdb1bcae1James Dong
92513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(a);           // a
92613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(b);           // b
92713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // u
92813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(c);           // c
92913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(d);           // d
93013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // v
93113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // x
93213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // y
93313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0x40000000);  // w
93413f6284305e4b27395a23db7882d670bdb1bcae1James Dong}
93513f6284305e4b27395a23db7882d670bdb1bcae1James Dong
936411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() {
937411ba422e3635d534928ffd81abf54f4f291c739James Dong    close(mFd);
938411ba422e3635d534928ffd81abf54f4f291c739James Dong    mFd = -1;
939411ba422e3635d534928ffd81abf54f4f291c739James Dong    mInitCheck = NO_INIT;
940411ba422e3635d534928ffd81abf54f4f291c739James Dong    mStarted = false;
9414c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary    free(mMoovBoxBuffer);
9424c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary    mMoovBoxBuffer = NULL;
943411ba422e3635d534928ffd81abf54f4f291c739James Dong}
94413f6284305e4b27395a23db7882d670bdb1bcae1James Dong
9458bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dongstatus_t MPEG4Writer::reset() {
946674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
94737187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
948411ba422e3635d534928ffd81abf54f4f291c739James Dong    } else {
949411ba422e3635d534928ffd81abf54f4f291c739James Dong        if (!mWriterThreadStarted ||
950411ba422e3635d534928ffd81abf54f4f291c739James Dong            !mStarted) {
951411ba422e3635d534928ffd81abf54f4f291c739James Dong            if (mWriterThreadStarted) {
952411ba422e3635d534928ffd81abf54f4f291c739James Dong                stopWriterThread();
953411ba422e3635d534928ffd81abf54f4f291c739James Dong            }
954411ba422e3635d534928ffd81abf54f4f291c739James Dong            release();
955411ba422e3635d534928ffd81abf54f4f291c739James Dong            return OK;
956411ba422e3635d534928ffd81abf54f4f291c739James Dong        }
95720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
95820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
95937187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
9608f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t maxDurationUs = 0;
96165b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    int64_t minDurationUs = 0x7fffffffffffffffLL;
96220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
96320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
96437187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->stop();
96537187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK) {
96637187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
96737187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
96820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9698f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int64_t durationUs = (*it)->getDurationUs();
9708f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (durationUs > maxDurationUs) {
9718f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            maxDurationUs = durationUs;
97220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
97365b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        if (durationUs < minDurationUs) {
97465b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs = durationUs;
97565b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        }
97665b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    }
97765b3d76025c71d755b0fb3b6ead90255f25417edJames Dong
97865b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    if (mTracks.size() > 1) {
979a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGD("Duration from tracks range is [%" PRId64 ", %" PRId64 "] us",
98065b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs, maxDurationUs);
98120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
98220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    stopWriterThread();
9847837c17063a4c50bc856ba59418516fdab731de7James Dong
98537187916a486504acaf83bea30147eb5fbf46ae5James Dong    // Do not write out movie header on error.
98637187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err != OK) {
987411ba422e3635d534928ffd81abf54f4f291c739James Dong        release();
98837187916a486504acaf83bea30147eb5fbf46ae5James Dong        return err;
98937187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
99037187916a486504acaf83bea30147eb5fbf46ae5James Dong
99120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
9921acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
993c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset, SEEK_SET);
9941f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad        uint32_t size = htonl(static_cast<uint32_t>(mOffset - mMdatOffset));
995c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 4);
9961acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
997c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset + 8, SEEK_SET);
9981f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad        uint64_t size = mOffset - mMdatOffset;
9991acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        size = hton64(size);
1000c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 8);
10011acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
1002c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mOffset, SEEK_SET);
100320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10047b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // Construct moov box now
10057837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
10067b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    mWriteMoovBoxToMemory = mStreamableFile;
10077b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mWriteMoovBoxToMemory) {
10087b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // There is no need to allocate in-memory cache
10097b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // for moov box if the file is not streamable.
10107b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
10117b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
10127b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        CHECK(mMoovBoxBuffer != NULL);
10137b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    }
1014b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMoovBox(maxDurationUs);
101520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10167b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // mWriteMoovBoxToMemory could be set to false in
10177b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // MPEG4Writer::write() method
10187b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mWriteMoovBoxToMemory) {
10197b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        mWriteMoovBoxToMemory = false;
10207b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // Content of the moov box is saved in the cache, and the in-memory
10217b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // moov box needs to be written to the file in a single shot.
10227b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
102343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize);
10247837c17063a4c50bc856ba59418516fdab731de7James Dong
10257837c17063a4c50bc856ba59418516fdab731de7James Dong        // Moov box
1026c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
10277837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset = mFreeBoxOffset;
1028674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset);
10297837c17063a4c50bc856ba59418516fdab731de7James Dong
10307837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free box
1031c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
10327837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
10337837c17063a4c50bc856ba59418516fdab731de7James Dong        write("free", 4);
10347b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    } else {
10357b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        ALOGI("The mp4 file will not be streamable.");
10367b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    }
10377837c17063a4c50bc856ba59418516fdab731de7James Dong
10387b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // Free in-memory cache for moov box
10397b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mMoovBoxBuffer != NULL) {
10407837c17063a4c50bc856ba59418516fdab731de7James Dong        free(mMoovBoxBuffer);
10417837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBuffer = NULL;
10427837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBufferOffset = 0;
10437837c17063a4c50bc856ba59418516fdab731de7James Dong    }
10447837c17063a4c50bc856ba59418516fdab731de7James Dong
10450c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
104620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1047411ba422e3635d534928ffd81abf54f4f291c739James Dong    release();
104837187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
104920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
105020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1051efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonuint32_t MPEG4Writer::getMpeg4Time() {
1052b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    time_t now = time(NULL);
1053efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // MP4 file uses time counting seconds since midnight, Jan. 1, 1904
1054efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // while time function returns Unix epoch values which starts
1055efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // at 1970-01-01. Lets add the number of seconds between them
10562b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    static const uint32_t delta = (66 * 365 + 17) * (24 * 60 * 60);
10572b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    if (now < 0 || uint32_t(now) > UINT32_MAX - delta) {
10582b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen        return 0;
10592b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    }
10602b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    uint32_t mpeg4Time = uint32_t(now) + delta;
1061efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    return mpeg4Time;
1062efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson}
1063efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson
1064efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) {
1065efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
1066b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("mvhd");
1067b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // version=0, flags=0
1068b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // creation time
1069b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // modification time
1070b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTimeScale);    // mvhd timescale
1071b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6;
1072b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(duration);
1073b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0x10000);       // rate: 1.0
1074b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0x100);         // volume
1075b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0);             // reserved
1076b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
1077b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
1078b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeCompositionMatrix(0); // matrix
1079b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1080b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1081b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1082b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1083b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1084b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1085b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTracks.size() + 1);  // nextTrackID
1086b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // mvhd
1087b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1088b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1089b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) {
1090b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("moov");
1091b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMvhdBox(durationUs);
109207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (mAreGeoTagsAvailable) {
109307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        writeUdtaBox();
109407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
1095e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeMetaBox();
1096b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t id = 1;
1097b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    for (List<Track *>::iterator it = mTracks.begin();
1098b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        it != mTracks.end(); ++it, ++id) {
1099b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (*it)->writeTrackHeader(mUse32BitOffset);
1100b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
1101b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // moov
1102b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1103b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
11042cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) {
1105b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("ftyp");
1106b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1107b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t fileType;
1108b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (param && param->findInt32(kKeyFileType, &fileType) &&
1109b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fileType != OUTPUT_FORMAT_MPEG_4) {
1110b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("3gp4");
11118284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeInt32(0);
11128284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("isom");
11138284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("3gp4");
1114b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
11158284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("mp42");
11168284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeInt32(0);
1117b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("isom");
11188284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("mp42");
1119b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
1120b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1121b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();
1122b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1123b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
112407ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() {
112507ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5)
112607ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5"
112707ec01904613a0bac32caaa8444b4690998faed7James Dong#endif
112807ec01904613a0bac32caaa8444b4690998faed7James Dong
112907ec01904613a0bac32caaa8444b4690998faed7James Dong    // Test mode is enabled only if rw.media.record.test system
113007ec01904613a0bac32caaa8444b4690998faed7James Dong    // property is enabled.
113196626b7f9a4e5c9e1e04f7f710383631d1470364Marco Nelissen    if (property_get_bool("rw.media.record.test", false)) {
113207ec01904613a0bac32caaa8444b4690998faed7James Dong        return true;
113307ec01904613a0bac32caaa8444b4690998faed7James Dong    }
113407ec01904613a0bac32caaa8444b4690998faed7James Dong    return false;
113507ec01904613a0bac32caaa8444b4690998faed7James Dong}
113607ec01904613a0bac32caaa8444b4690998faed7James Dong
113770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() {
113807ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send session summary only if test mode is enabled
113907ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
114007ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
114107ec01904613a0bac32caaa8444b4690998faed7James Dong    }
114207ec01904613a0bac32caaa8444b4690998faed7James Dong
114370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
114470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong         it != mChunkInfos.end(); ++it) {
114570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int trackNum = it->mTrack->getTrackId() << 28;
114670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
114770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS,
114870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs);
114970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    }
115070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong}
115170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
115213aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
115313aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
115413aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
115513aec890216948b0c364f8f92792129d0335f506James Dong}
115613aec890216948b0c364f8f92792129d0335f506James Dong
115713aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() {
115813aec890216948b0c364f8f92792129d0335f506James Dong    mLock.lock();
115913aec890216948b0c364f8f92792129d0335f506James Dong}
116013aec890216948b0c364f8f92792129d0335f506James Dong
116113aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() {
116213aec890216948b0c364f8f92792129d0335f506James Dong    mLock.unlock();
116313aec890216948b0c364f8f92792129d0335f506James Dong}
116420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1165c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
1166c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
116720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1168c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    ::write(mFd,
1169c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          (const uint8_t *)buffer->data() + buffer->range_offset(),
1170c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          buffer->range_length());
117120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
117220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
117320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
117420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
117520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
117620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
117703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
117803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
117903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
118003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
118103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
118203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
118303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
118403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
118503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
118603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
118703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
118803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
118903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
119003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
119180f78b773f92048944a850efb7b60629643370cdPraveen Chavanoff64_t MPEG4Writer::addMultipleLengthPrefixedSamples_l(MediaBuffer *buffer) {
119280f78b773f92048944a850efb7b60629643370cdPraveen Chavan    off64_t old_offset = mOffset;
119380f78b773f92048944a850efb7b60629643370cdPraveen Chavan
119480f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const size_t kExtensionNALSearchRange = 64; // bytes to look for non-VCL NALUs
119580f78b773f92048944a850efb7b60629643370cdPraveen Chavan
119680f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *dataStart = (const uint8_t *)buffer->data() + buffer->range_offset();
119780f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *currentNalStart = dataStart;
119880f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *nextNalStart;
119980f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *data = dataStart;
120080f78b773f92048944a850efb7b60629643370cdPraveen Chavan    size_t nextNalSize;
120180f78b773f92048944a850efb7b60629643370cdPraveen Chavan    size_t searchSize = buffer->range_length() > kExtensionNALSearchRange ?
120280f78b773f92048944a850efb7b60629643370cdPraveen Chavan                   kExtensionNALSearchRange : buffer->range_length();
120380f78b773f92048944a850efb7b60629643370cdPraveen Chavan
120480f78b773f92048944a850efb7b60629643370cdPraveen Chavan    while (getNextNALUnit(&data, &searchSize, &nextNalStart,
120580f78b773f92048944a850efb7b60629643370cdPraveen Chavan            &nextNalSize, true) == OK) {
120610cc12c4eec9ff974edb72f9140b05762fa50907Lajos Molnar        size_t currentNalSize = nextNalStart - currentNalStart - 4 /* strip start-code */;
120780f78b773f92048944a850efb7b60629643370cdPraveen Chavan        MediaBuffer *nalBuf = new MediaBuffer((void *)currentNalStart, currentNalSize);
120880f78b773f92048944a850efb7b60629643370cdPraveen Chavan        addLengthPrefixedSample_l(nalBuf);
120980f78b773f92048944a850efb7b60629643370cdPraveen Chavan        nalBuf->release();
121080f78b773f92048944a850efb7b60629643370cdPraveen Chavan
121180f78b773f92048944a850efb7b60629643370cdPraveen Chavan        currentNalStart = nextNalStart;
121280f78b773f92048944a850efb7b60629643370cdPraveen Chavan    }
121380f78b773f92048944a850efb7b60629643370cdPraveen Chavan
121480f78b773f92048944a850efb7b60629643370cdPraveen Chavan    size_t currentNalOffset = currentNalStart - dataStart;
121580f78b773f92048944a850efb7b60629643370cdPraveen Chavan    buffer->set_range(buffer->range_offset() + currentNalOffset,
121680f78b773f92048944a850efb7b60629643370cdPraveen Chavan            buffer->range_length() - currentNalOffset);
121780f78b773f92048944a850efb7b60629643370cdPraveen Chavan    addLengthPrefixedSample_l(buffer);
121880f78b773f92048944a850efb7b60629643370cdPraveen Chavan
121980f78b773f92048944a850efb7b60629643370cdPraveen Chavan    return old_offset;
122080f78b773f92048944a850efb7b60629643370cdPraveen Chavan}
122180f78b773f92048944a850efb7b60629643370cdPraveen Chavan
1222c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
1223c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
122430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
122530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
122603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1227b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mUse4ByteNalLength) {
1228b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 24;
1229c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1230b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 16) & 0xff;
1231c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1232b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 8) & 0xff;
1233c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1234b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
1235c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1236c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong
1237c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd,
1238c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              (const uint8_t *)buffer->data() + buffer->range_offset(),
1239c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              length);
1240b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
1241b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 4;
1242b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
124343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_LT(length, 65536);
124430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1245b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 8;
1246c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1247b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
1248c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1249c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length);
1250b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 2;
1251b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
125230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
125330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
125430ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
125530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
12567837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write(
1257674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        const void *ptr, size_t size, size_t nmemb) {
12587837c17063a4c50bc856ba59418516fdab731de7James Dong
12597837c17063a4c50bc856ba59418516fdab731de7James Dong    const size_t bytes = size * nmemb;
12607837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
12617b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
1262c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
12631acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        if (moovBoxSize > mEstimatedMoovBoxSize) {
12647b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // The reserved moov box at the beginning of the file
12657b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // is not big enough. Moov box should be written to
12667b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // the end of the file from now on, but not to the
12677b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // in-memory cache.
12687b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
12697b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // We write partial moov box that is in the memory to
12707b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // the file first.
1271c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            for (List<off64_t>::iterator it = mBoxes.begin();
12727837c17063a4c50bc856ba59418516fdab731de7James Dong                 it != mBoxes.end(); ++it) {
12737837c17063a4c50bc856ba59418516fdab731de7James Dong                (*it) += mOffset;
12747837c17063a4c50bc856ba59418516fdab731de7James Dong            }
1275674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            lseek64(mFd, mOffset, SEEK_SET);
1276674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset);
12777b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            ::write(mFd, ptr, bytes);
12787837c17063a4c50bc856ba59418516fdab731de7James Dong            mOffset += (bytes + mMoovBoxBufferOffset);
12797b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
12807b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // All subsequent moov box content will be written
12817b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // to the end of the file.
12827837c17063a4c50bc856ba59418516fdab731de7James Dong            mWriteMoovBoxToMemory = false;
12837837c17063a4c50bc856ba59418516fdab731de7James Dong        } else {
12847837c17063a4c50bc856ba59418516fdab731de7James Dong            memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
12857837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset += bytes;
12867837c17063a4c50bc856ba59418516fdab731de7James Dong        }
12877837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1288674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        ::write(mFd, ptr, size * nmemb);
12897837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset += bytes;
12907837c17063a4c50bc856ba59418516fdab731de7James Dong    }
12917837c17063a4c50bc856ba59418516fdab731de7James Dong    return bytes;
12927837c17063a4c50bc856ba59418516fdab731de7James Dong}
12937837c17063a4c50bc856ba59418516fdab731de7James Dong
1294e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::beginBox(uint32_t id) {
1295e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    mBoxes.push_back(mWriteMoovBoxToMemory?
1296e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            mMoovBoxBufferOffset: mOffset);
1297e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
1298e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0);
1299e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(id);
1300e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
1301e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
130220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
13030c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(fourcc), 4);
130420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13057837c17063a4c50bc856ba59418516fdab731de7James Dong    mBoxes.push_back(mWriteMoovBoxToMemory?
13067837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset: mOffset);
130720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
130820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
130920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
131020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
131120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
131220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
13130c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
131420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1315c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = *--mBoxes.end();
131620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
131720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13187837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
13197837c17063a4c50bc856ba59418516fdab731de7James Dong       int32_t x = htonl(mMoovBoxBufferOffset - offset);
13207837c17063a4c50bc856ba59418516fdab731de7James Dong       memcpy(mMoovBoxBuffer + offset, &x, 4);
13217837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1322c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, offset, SEEK_SET);
13237837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mOffset - offset);
13247837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset -= 4;
1325c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
13267837c17063a4c50bc856ba59418516fdab731de7James Dong    }
132720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
132820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
132920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
1330674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 1);
133120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
133220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
133320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
133420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
1335674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 2);
133620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
133720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
133820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
133920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
1340674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 4);
134120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
134220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
134320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
134420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
1345674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 8);
134620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
134720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
134820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
134920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
1350674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, n + 1);
135120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
135220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
135320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
13540c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(s), 4);
1355674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, 4);
135620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
135720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
135807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
135907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format
136007b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) {
136107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
136207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
136307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
136407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
136507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[9];
136607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
136707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
136807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%c%.2d.", sign, wholePart);
136907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
137007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%+.2d.", wholePart);
137107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
137207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
137307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
137407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
137507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
137607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
137707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
137807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[4], 5, "%.4d", fractionalPart);
137907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
138007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
138107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 8);
138207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
138307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
138407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format
138507b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) {
138607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
138707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
138807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
138907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
139007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[10];
139107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
139207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
139307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%c%.3d.", sign, wholePart);
139407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
139507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%+.3d.", wholePart);
139607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
139707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
139807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
139907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
140007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
140107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
140207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
140307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[5], 5, "%.4d", fractionalPart);
140407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
140507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
140607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 9);
140707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
140807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
140907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
141007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
141107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and
141207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000.
141307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and
141407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180]
141507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
141607b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) {
141707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Is latitude or longitude out of range?
141807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (latitudex10000 < -900000 || latitudex10000 > 900000 ||
141907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        longitudex10000 < -1800000 || longitudex10000 > 1800000) {
142007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        return BAD_VALUE;
142107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
142207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
142307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLatitudex10000 = latitudex10000;
142407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLongitudex10000 = longitudex10000;
142507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mAreGeoTagsAvailable = true;
14267c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += 30;
142707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    return OK;
142807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
142907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
1430e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangstatus_t MPEG4Writer::setCaptureRate(float captureFps) {
1431e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    if (captureFps <= 0.0f) {
1432e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        return BAD_VALUE;
1433e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
1434e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
14357c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMetaKeys->setFloat(kMetaKey_CaptureFps, captureFps);
14367c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += sizeof(kMetaKey_CaptureFps) + 4 + 32;
14377c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
1438e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    return OK;
1439e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
1440e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
14414dbff11975e737482537e1636051690188f3fbc4Praveen Chavanstatus_t MPEG4Writer::setTemporalLayerCount(uint32_t layerCount) {
14424dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    if (layerCount > 9) {
14434dbff11975e737482537e1636051690188f3fbc4Praveen Chavan        return BAD_VALUE;
14444dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    }
14454dbff11975e737482537e1636051690188f3fbc4Praveen Chavan
14464dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    if (layerCount > 0) {
14474dbff11975e737482537e1636051690188f3fbc4Praveen Chavan        mMetaKeys->setInt32(kMetaKey_TemporalLayerCount, layerCount);
14484dbff11975e737482537e1636051690188f3fbc4Praveen Chavan        mMoovExtraSize += sizeof(kMetaKey_TemporalLayerCount) + 4 + 32;
14494dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    }
14504dbff11975e737482537e1636051690188f3fbc4Praveen Chavan
14514dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    return OK;
14524dbff11975e737482537e1636051690188f3fbc4Praveen Chavan}
14534dbff11975e737482537e1636051690188f3fbc4Praveen Chavan
145420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
1455674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(data, 1, size);
145620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
145720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
145878a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const {
145978a1a286f736888ae7af8860b2c424af0d978848James Dong    return mStreamableFile;
146078a1a286f736888ae7af8860b2c424af0d978848James Dong}
146178a1a286f736888ae7af8860b2c424af0d978848James Dong
1462d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() {
1463d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1464d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeLimitBytes == 0) {
1465d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1466d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1467d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1468956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
1469d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1470d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1471d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
1472d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
14731f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
147477e8ae9967a078770416619e99ddb5b010def312James Dong    if (!mStreamableFile) {
147577e8ae9967a078770416619e99ddb5b010def312James Dong        // Add 1024 bytes as error tolerance
147677e8ae9967a078770416619e99ddb5b010def312James Dong        return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes;
147777e8ae9967a078770416619e99ddb5b010def312James Dong    }
1478acd234bba9f048971d66890009eeff9a8db94be3James Dong    // Be conservative in the estimate: do not exceed 95% of
1479acd234bba9f048971d66890009eeff9a8db94be3James Dong    // the target file limit. For small target file size limit, though,
1480acd234bba9f048971d66890009eeff9a8db94be3James Dong    // this will not help.
1481acd234bba9f048971d66890009eeff9a8db94be3James Dong    return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100);
1482d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1483d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1484d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() {
1485d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1486d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationLimitUs == 0) {
1487d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1488d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1489d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1490d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1491d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1492d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
1493d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            return true;
1494d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1495d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1496d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return false;
1497d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1498d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
149925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
150025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
150125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
150225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
150325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
150425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
150525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
150625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
150725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
150825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
150925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
151025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
151125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
1512f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
1513a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGI("setStartTimestampUs: %" PRId64, timeUs);
151443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(timeUs, 0ll);
15153c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
1516065d1aff96818df54456053f1574aec8a234d0deJames Dong    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
1517f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimestampUs = timeUs;
1518a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Earliest track starting time: %" PRId64, mStartTimestampUs);
15193c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    }
15203c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
15213c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
1522f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() {
15233c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
15243c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    return mStartTimestampUs;
15253c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
15263c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
152758ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() {
152858ae9c530247668f8af36e30d228c716c226b3d4James Dong    Mutex::Autolock autolock(mLock);
152958ae9c530247668f8af36e30d228c716c226b3d4James Dong    return mTracks.size();
153058ae9c530247668f8af36e30d228c716c226b3d4James Dong}
153158ae9c530247668f8af36e30d228c716c226b3d4James Dong
153220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
153320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
153420111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
1535b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen        MPEG4Writer *owner, const sp<IMediaSource> &source, size_t trackId)
153620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
153725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
153820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
153920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
1540a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
1541a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mResumed(false),
1542eaae38445a340c4857c1c5569475879a728e63b7James Dong      mStarted(false),
15439db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang      mIsMalformed(false),
1544bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong      mTrackId(trackId),
1545c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong      mTrackDurationUs(0),
1546956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mEstimatedTrackSizeBytes(0),
1547be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong      mSamplesHaveSameSize(true),
1548c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mStszTableEntries(new ListTableEntries<uint32_t, 1>(1000)),
1549c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mStcoTableEntries(new ListTableEntries<uint32_t, 1>(1000)),
1550c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mCo64TableEntries(new ListTableEntries<off64_t, 1>(1000)),
1551c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mStscTableEntries(new ListTableEntries<uint32_t, 3>(1000)),
1552c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mStssTableEntries(new ListTableEntries<uint32_t, 1>(1000)),
1553c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mSttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)),
1554c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mCttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)),
155520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
155625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
1557548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
155813f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mReachedEOS(false),
155913f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mRotation(0) {
156019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    getCodecSpecificDataFromInputFormatIfPossible();
15618f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
15621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    const char *mime;
15631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMeta->findCString(kKeyMIMEType, &mime);
15641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
15659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mIsHevc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC);
15661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAudio = !strncasecmp(mime, "audio/", 6);
156725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mIsVideo = !strncasecmp(mime, "video/", 6);
15681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
15691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
15701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1571b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar    // store temporal layer count
157225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (mIsVideo) {
1573b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar        int32_t count;
1574b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar        if (mMeta->findInt32(kKeyTemporalLayerCount, &count) && count > 1) {
1575b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar            mOwner->setTemporalLayerCount(count);
1576b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar        }
1577b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar    }
1578b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar
1579c059860c73678a202bfa33062723e8f82fb779d9James Dong    setTimeScale();
1580c059860c73678a202bfa33062723e8f82fb779d9James Dong}
1581c059860c73678a202bfa33062723e8f82fb779d9James Dong
15821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() {
15831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1584c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t stcoBoxCount = (mOwner->use32BitFileOffset()
1585c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                            ? mStcoTableEntries->count()
1586c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                            : mCo64TableEntries->count());
1587c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    int64_t stcoBoxSizeBytes = stcoBoxCount * 4;
1588c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4);
15891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
159078a1a286f736888ae7af8860b2c424af0d978848James Dong    mEstimatedTrackSizeBytes = mMdatSizeBytes;  // media data size
159178a1a286f736888ae7af8860b2c424af0d978848James Dong    if (!mOwner->isFileStreamable()) {
159278a1a286f736888ae7af8860b2c424af0d978848James Dong        // Reserved free space is not large enough to hold
159378a1a286f736888ae7af8860b2c424af0d978848James Dong        // all meta data and thus wasted.
1594c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 +  // stsc box size
1595c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mStssTableEntries->count() * 4 +   // stss box size
1596c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mSttsTableEntries->count() * 8 +   // stts box size
1597c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mCttsTableEntries->count() * 8 +   // ctts box size
159878a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stcoBoxSizeBytes +           // stco box size
159978a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stszBoxSizeBytes;            // stsz box size
160078a1a286f736888ae7af8860b2c424af0d978848James Dong    }
16011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
16021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
16031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry(
16041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        size_t chunkId, size_t sampleId) {
16051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1606c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(chunkId));
1607c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(sampleId));
1608c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(1));
16091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
16101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
16111f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) {
1612c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->add(htonl(sampleId));
16131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
16141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
16151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry(
161679761ab096f57c3027fad9556c2bc436672d614eJames Dong        size_t sampleCount, int32_t duration) {
16171f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
16185a217fba010e801c255503602bda4b86ac5a6ac9James Dong    if (duration == 0) {
1619377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGW("0-duration samples found: %zu", sampleCount);
16205a217fba010e801c255503602bda4b86ac5a6ac9James Dong    }
1621c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(sampleCount));
1622c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(duration));
16231f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
16241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1625965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry(
1626965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        size_t sampleCount, int32_t duration) {
1627965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
162825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (!mIsVideo) {
1629965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
1630965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
1631c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(sampleCount));
1632c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(duration));
1633965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
1634965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1635c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) {
1636c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mOwner->use32BitFileOffset()) {
1637c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t value = offset;
1638c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->add(htonl(value));
1639c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
1640c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->add(hton64(offset));
1641c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    }
16421f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
16431f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1644c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() {
16453856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setTimeScale");
1646c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Default time scale
1647c059860c73678a202bfa33062723e8f82fb779d9James Dong    mTimeScale = 90000;
1648c059860c73678a202bfa33062723e8f82fb779d9James Dong
1649c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mIsAudio) {
1650c059860c73678a202bfa33062723e8f82fb779d9James Dong        // Use the sampling rate as the default time scale for audio track.
1651c059860c73678a202bfa33062723e8f82fb779d9James Dong        int32_t sampleRate;
1652c059860c73678a202bfa33062723e8f82fb779d9James Dong        bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
1653c059860c73678a202bfa33062723e8f82fb779d9James Dong        CHECK(success);
1654c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = sampleRate;
1655c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1656c059860c73678a202bfa33062723e8f82fb779d9James Dong
1657c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If someone would like to overwrite the timescale, use user-supplied value.
1658c059860c73678a202bfa33062723e8f82fb779d9James Dong    int32_t timeScale;
1659c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
1660c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = timeScale;
1661c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1662c059860c73678a202bfa33062723e8f82fb779d9James Dong
166343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
166419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber}
166519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
166619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
166719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    const char *mime;
166819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
166919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
16709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    uint32_t type;
16719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const void *data = NULL;
16729aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t size = 0;
167319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
16749aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mMeta->findData(kKeyAVCC, &type, &data, &size);
16759aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
16769aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mMeta->findData(kKeyHVCC, &type, &data, &size);
167719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
167819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
167919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
168019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            ESDS esds(data, size);
16819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            if (esds.getCodecSpecificInfo(&data, &size) != OK) {
16829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                data = NULL;
16839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                size = 0;
168419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            }
168519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
168619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
16879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (data != NULL && copyCodecSpecificData((uint8_t *)data, size) == OK) {
16889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mGotAllCodecSpecificData = true;
16899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
169020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
169120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
169220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
169320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
169420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1695c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStszTableEntries;
1696c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStcoTableEntries;
1697c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCo64TableEntries;
1698c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStscTableEntries;
1699c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mSttsTableEntries;
1700c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStssTableEntries;
1701c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCttsTableEntries;
1702c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
1703c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries = NULL;
1704c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStcoTableEntries = NULL;
1705c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCo64TableEntries = NULL;
1706c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries = NULL;
1707c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries = NULL;
1708c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries = NULL;
1709c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries = NULL;
1710c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
171120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
171220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
171320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
171420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
171520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
171620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
171793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
17183856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("initTrackingProgressStatus");
171993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mPreviousTrackTimeUs = -1;
172093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackingProgressStatus = false;
172193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
172293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    {
172393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeUs;
172493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
1725a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGV("Receive request to track progress status for every %" PRId64 " us", timeUs);
172693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackEveryTimeDurationUs = timeUs;
172793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackingProgressStatus = true;
172893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
172993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
173093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
173193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
17321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static
17331c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) {
17343856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("ThreadWrapper: %p", me);
17351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
17361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    writer->threadFunc();
17371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return NULL;
17381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
17391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17401c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) {
17413856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk: %p", chunk.mTrack);
17421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Mutex::Autolock autolock(mLock);
17431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK_EQ(mDone, false);
17441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
17461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
17471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (chunk.mTrack == it->mTrack) {  // Found owner
17491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            it->mChunks.push_back(chunk);
17501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.signal();
17511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            return;
17521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
17531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
17541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
175543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK(!"Received a chunk for a unknown track");
17561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
17571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1758fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) {
1759a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("writeChunkToFile: %" PRId64 " from %s track",
176025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        chunk->mTimeStampUs, chunk->mTrack->getTrackType());
1761fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1762fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    int32_t isFirstSample = true;
1763fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    while (!chunk->mSamples.empty()) {
1764fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        List<MediaBuffer *>::iterator it = chunk->mSamples.begin();
1765fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
17669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        off64_t offset = (chunk->mTrack->isAvc() || chunk->mTrack->isHevc())
176780f78b773f92048944a850efb7b60629643370cdPraveen Chavan                                ? addMultipleLengthPrefixedSamples_l(*it)
1768fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong                                : addSample_l(*it);
1769fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1770fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (isFirstSample) {
1771fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            chunk->mTrack->addChunkOffset(offset);
1772fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            isFirstSample = false;
17731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
17741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it)->release();
17761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it) = NULL;
1777fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        chunk->mSamples.erase(it);
17781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1779fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    chunk->mSamples.clear();
17801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
17811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1782fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() {
17833856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeAllChunks");
17841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    size_t outstandingChunks = 0;
178570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    Chunk chunk;
178670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    while (findChunkToWrite(&chunk)) {
1787e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong        writeChunkToFile(&chunk);
178870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        ++outstandingChunks;
17891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
179070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
179170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    sendSessionSummary();
179270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
17931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mChunkInfos.clear();
1794377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    ALOGD("%zu chunks are written in the last batch", outstandingChunks);
17951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
17961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1797fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) {
17983856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("findChunkToWrite");
17991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
18011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Track *track = NULL;
18021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
18031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
18041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (!it->mChunks.empty()) {
18051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            List<Chunk>::iterator chunkIt = it->mChunks.begin();
18061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (chunkIt->mTimeStampUs < minTimestampUs) {
18071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                minTimestampUs = chunkIt->mTimeStampUs;
18081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                track = it->mTrack;
18091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            }
18101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
18111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
18121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (track == NULL) {
18143856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Nothing to be written after all");
1815fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        return false;
18161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
18171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mIsFirstChunk) {
18191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsFirstChunk = false;
18201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1821fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
18221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
18231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
18241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it->mTrack == track) {
1825fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            *chunk = *(it->mChunks.begin());
1826fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            it->mChunks.erase(it->mChunks.begin());
1827fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            CHECK_EQ(chunk->mTrack, track);
182870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
182970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t interChunkTimeUs =
183070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                chunk->mTimeStampUs - it->mPrevChunkTimestampUs;
183170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            if (interChunkTimeUs > it->mPrevChunkTimestampUs) {
183270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs = interChunkTimeUs;
183370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            }
183470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
1835fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            return true;
18361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
18371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1838fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1839fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    return false;
18401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
18411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18421c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() {
18433856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("threadFunc");
18441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1845a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0);
1846fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1847fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    Mutex::Autolock autoLock(mLock);
18481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mDone) {
1849fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        Chunk chunk;
1850fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        bool chunkFound = false;
1851fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1852fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) {
18531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.wait(mLock);
18541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
18551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1856de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // In real time recording mode, write without holding the lock in order
1857de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // to reduce the blocking time for media track threads.
1858de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // Otherwise, hold the lock until the existing chunks get written to the
1859de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // file.
1860fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (chunkFound) {
1861de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            if (mIsRealTimeRecording) {
1862de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui                mLock.unlock();
1863de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            }
1864fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            writeChunkToFile(&chunk);
1865de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            if (mIsRealTimeRecording) {
1866de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui                mLock.lock();
1867de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            }
1868fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        }
18691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1870fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1871fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    writeAllChunks();
18721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
18731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18741c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() {
18753856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("startWriterThread");
18761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mDone = false;
18781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsFirstChunk = true;
1879e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    mDriftTimeUs = 0;
18801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<Track *>::iterator it = mTracks.begin();
18811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mTracks.end(); ++it) {
18821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        ChunkInfo info;
18831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        info.mTrack = *it;
188470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mPrevChunkTimestampUs = 0;
188570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mMaxInterChunkDurUs = 0;
18861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.push_back(info);
18871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
18881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_t attr;
18901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_init(&attr);
18911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
18921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_create(&mThread, &attr, ThreadWrapper, this);
18931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_destroy(&attr);
1894411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = true;
18951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
18961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
18971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
189993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) {
1900a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (!mDone && mPaused) {
1901a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mPaused = false;
1902a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mResumed = true;
1903a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
1904a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
190525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
190693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t startTimeUs;
190719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
190819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        startTimeUs = 0;
190919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
191070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    mStartTimeRealUs = startTimeUs;
191119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
191213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t rotationDegrees;
191325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (mIsVideo && params && params->findInt32(kKeyRotation, &rotationDegrees)) {
191413f6284305e4b27395a23db7882d670bdb1bcae1James Dong        mRotation = rotationDegrees;
191513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
191613f6284305e4b27395a23db7882d670bdb1bcae1James Dong
191793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    initTrackingProgressStatus(params);
191893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
1919f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    sp<MetaData> meta = new MetaData;
1920de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) {
1921a472613aec322e25891abf5c77bf3f7e3c244920James Dong        /*
1922a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * This extra delay of accepting incoming audio/video signals
1923a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * helps to align a/v start time at the beginning of a recording
1924a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * session, and it also helps eliminate the "recording" sound for
1925a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * camcorder applications.
1926a472613aec322e25891abf5c77bf3f7e3c244920James Dong         *
192786b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * If client does not set the start time offset, we fall back to
192886b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * use the default initial delay value.
1929a472613aec322e25891abf5c77bf3f7e3c244920James Dong         */
193086b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
193186b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
193286b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
193386b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
193486b7f47aa7482424cf8fd248f1315311919be3b0James Dong        startTimeUs += startTimeOffsetUs;
1935a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Start time offset: %" PRId64 " us", startTimeOffsetUs);
1936a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
1937a472613aec322e25891abf5c77bf3f7e3c244920James Dong
1938f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    meta->setInt64(kKeyTime, startTimeUs);
1939a472613aec322e25891abf5c77bf3f7e3c244920James Dong
1940f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    status_t err = mSource->start(meta.get());
194125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
194225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
194325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
194425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
194520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
194620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
194720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
194820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
194920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
195020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
1951eaae38445a340c4857c1c5569475879a728e63b7James Dong    mStarted = true;
1952c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs = 0;
195325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
1954956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mEstimatedTrackSizeBytes = 0;
19551f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mMdatSizeBytes = 0;
195643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mMaxChunkDurationUs = 0;
1957826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar    mLastDecodingTimeUs = -1;
195820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
195925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
196020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
196125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
196225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
196320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
196420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
196537187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() {
1966a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
196737187916a486504acaf83bea30147eb5fbf46ae5James Dong    return OK;
1968a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
1969a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
197037187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() {
197125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    ALOGD("%s track stopping", getTrackType());
1972eaae38445a340c4857c1c5569475879a728e63b7James Dong    if (!mStarted) {
197329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Stop() called but track is not started");
1974eaae38445a340c4857c1c5569475879a728e63b7James Dong        return ERROR_END_OF_STREAM;
1975eaae38445a340c4857c1c5569475879a728e63b7James Dong    }
1976eaae38445a340c4857c1c5569475879a728e63b7James Dong
197720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
197837187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
197920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
198020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = true;
198120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
198225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    ALOGD("%s track source stopping", getTrackType());
198372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mSource->stop();
198425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    ALOGD("%s track source stopped", getTrackType());
198572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
198620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
198720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
1988377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy));
198937187916a486504acaf83bea30147eb5fbf46ae5James Dong
199025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    ALOGD("%s track stopped", getTrackType());
199137187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
199220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
199320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
199425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
199525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
199625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
199725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
199820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
199920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
200020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
200120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
200237187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = track->threadEntry();
2003377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    return (void *)(uintptr_t)err;
200420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
200520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) {
20073856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("getNalUnitType: %d", byte);
20083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // nal_unit_type: 5-bit unsigned integer
20103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *type = (byte & 0x1F);
20113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
20123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet(
20143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
20153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20163856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseParamSet");
20173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    CHECK(type == kNalUnitTypeSeqParamSet ||
20183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong          type == kNalUnitTypePicParamSet);
20193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
202047d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar    const uint8_t *nextStartCode = findNextNalStartCode(data, length);
20213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *paramSetLen = nextStartCode - data;
20223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (*paramSetLen == 0) {
202329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Param set is malformed, since its length is 0");
20243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return NULL;
20253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
20263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    AVCParamSet paramSet(*paramSetLen, data);
20283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (type == kNalUnitTypeSeqParamSet) {
20293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (*paramSetLen < 4) {
203029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Seq parameter set malformed");
20313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return NULL;
20323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mSeqParamSets.empty()) {
20343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc = data[1];
20353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileCompatible = data[2];
20363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mLevelIdc = data[3];
20373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
20383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (mProfileIdc != data[1] ||
20393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mProfileCompatible != data[2] ||
20403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mLevelIdc != data[3]) {
204107b2fbfb40770f3be0f674596f2e51d257c6d2bdLajos Molnar                // COULD DO: set profile/level to the lowest required to support all SPSs
204229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Inconsistent profile/level found in seq parameter sets");
20433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return NULL;
20443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
20453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mSeqParamSets.push_back(paramSet);
20473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    } else {
20483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mPicParamSets.push_back(paramSet);
20493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
20503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return nextStartCode;
20513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
20523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData(
20543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
20553856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("copyAVCCodecSpecificData");
20563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 2 bytes for each of the parameter set length field
20583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // plus the 7 bytes for the header
20599aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return copyCodecSpecificData(data, size, 4 + 7);
20609aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
20619aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
20629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyHEVCCodecSpecificData(
20639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size) {
20649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ALOGV("copyHEVCCodecSpecificData");
20659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
20669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Min length of HEVC CSD is 23. (ISO/IEC 14496-15:2014 Chapter 8.3.3.1.2)
20679aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return copyCodecSpecificData(data, size, 23);
20689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
20699aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
20709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyCodecSpecificData(
20719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size, size_t minLength) {
20729aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (size < minLength) {
2073377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGE("Codec specific data length too short: %zu", size);
20743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return ERROR_MALFORMED;
20753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
20763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificData = malloc(size);
20789aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
20799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
20809aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
20819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
20829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificDataSize = size;
20833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    memcpy(mCodecSpecificData, data, size);
20843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
20853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
20863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData(
20883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
20893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20903856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseAVCCodecSpecificData");
20913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data starts with a start code.
20923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // SPS and PPS are separated with start codes.
20933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Also, SPS must come before PPS
20943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t type = kNalUnitTypeSeqParamSet;
20953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotSps = false;
20963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotPps = false;
20973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *tmp = data;
20983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = data;
20993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = size;
21003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t paramSetLen = 0;
21013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = 0;
21023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
21033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        getNalUnitType(*(tmp + 4), &type);
21043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (type == kNalUnitTypeSeqParamSet) {
21053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (gotPps) {
210629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
21073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
21083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
21093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
21103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotSps = true;
21113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
21123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
21133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else if (type == kNalUnitTypePicParamSet) {
21143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
211529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
21163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
21173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
21183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotPps) {
21193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotPps = true;
21203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
21213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
21223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
212329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Only SPS and PPS Nal units are expected");
21243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
21253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
21263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nextStartCode == NULL) {
21283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
21293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
21303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Move on to find the next parameter set
21323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft -= nextStartCode - tmp;
21333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        tmp = nextStartCode;
21343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mCodecSpecificDataSize += (2 + paramSetLen);
21353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
21363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
21383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of seq parameter sets
21393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nSeqParamSets = mSeqParamSets.size();
21403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets == 0) {
214129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find sequence parameter set");
21423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
21433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
21443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets > 0x1F) {
2146377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets);
21473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
21483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
21493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
21503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
21523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of pic parameter sets
21533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nPicParamSets = mPicParamSets.size();
21543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets == 0) {
215529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find picture parameter set");
21563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
21573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
21583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets > 0xFF) {
2159377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets);
21603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
21613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
21623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
21631374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME:
21641374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above
21651374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0
21661374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0
21673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
21683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the profiles
21693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // These profiles requires additional parameter set extensions
21703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mProfileIdc == 100 || mProfileIdc == 110 ||
21713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc == 122 || mProfileIdc == 144) {
217229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
21733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return BAD_VALUE;
21743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
21753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
21761374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif
21773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
21783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
2179548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
218003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
218103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
2182548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
218303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
218429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Already have codec specific data");
218503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
218603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
218703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
21883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4) {
2189377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGE("Codec specific data length too short: %zu", size);
219003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
219103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
219203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
21933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data is in the form of AVCCodecSpecificData
21943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (memcmp("\x00\x00\x00\x01", data, 4)) {
21953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return copyAVCCodecSpecificData(data, size);
219603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
219703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
21983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (parseAVCCodecSpecificData(data, size) != OK) {
219903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
220003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
220103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
22023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // ISO 14496-15: AVC file format
22033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize += 7;  // 7 more bytes in the header
220403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
22059aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
22069aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mCodecSpecificDataSize = 0;
22079aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
22089aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
22099aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
221003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
22113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = 1;                     // version
22123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[1] = mProfileIdc;           // profile indication
22133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[2] = mProfileCompatible;    // profile compatibility
22143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[3] = mLevelIdc;
221503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
22163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
2217b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mOwner->useNalLengthFour()) {
2218b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 3;  // length size == 4 bytes
2219b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
2220b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 1;  // length size == 2 bytes
2221b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
222203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
22233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 3-bit '111' followed by 5-bit numSequenceParameterSets
22243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nSequenceParamSets = mSeqParamSets.size();
22253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[5] = 0xe0 | nSequenceParamSets;
22263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 6;
22273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
22283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mSeqParamSets.end(); ++it) {
22293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit sequence parameter set length
22303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t seqParamSetLength = it->mLength;
22313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = seqParamSetLength >> 8;
22323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = seqParamSetLength & 0xff;
22333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // SPS NAL unit (sequence parameter length bytes)
22353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, seqParamSetLength);
22363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + seqParamSetLength);
22373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
22383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 8-bit nPictureParameterSets
22403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nPictureParamSets = mPicParamSets.size();
22413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = nPictureParamSets;
22423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 1;
22433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
22443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mPicParamSets.end(); ++it) {
22453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit picture parameter set length
22463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t picParamSetLength = it->mLength;
22473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = picParamSetLength >> 8;
22483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = picParamSetLength & 0xff;
22493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // PPS Nal unit (picture parameter set length bytes)
22513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, picParamSetLength);
22523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + picParamSetLength);
22533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
225403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
225503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
225603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
225703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
22589aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22599aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::parseHEVCCodecSpecificData(
22609aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size, HevcParameterSets &paramSets) {
22619aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ALOGV("parseHEVCCodecSpecificData");
22639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const uint8_t *tmp = data;
22649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const uint8_t *nextStartCode = data;
22659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t bytesLeft = size;
22669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
226747d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar        nextStartCode = findNextNalStartCode(tmp + 4, bytesLeft - 4);
22689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        status_t err = paramSets.addNalUnit(tmp + 4, (nextStartCode - tmp) - 4);
22699aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (err != OK) {
22709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
22719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
22729aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22739aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        // Move on to find the next parameter set
22749aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        bytesLeft -= nextStartCode - tmp;
22759aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        tmp = nextStartCode;
22769aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
22779aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22789aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t csdSize = 23;
22799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const size_t numNalUnits = paramSets.getNumNalUnits();
22809aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    for (size_t i = 0; i < ARRAY_SIZE(kMandatoryHevcNalUnitTypes); ++i) {
22819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        int type = kMandatoryHevcNalUnitTypes[i];
22829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        size_t numParamSets = paramSets.getNumNalUnitsOfType(type);
22839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (numParamSets == 0) {
22849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            ALOGE("Cound not find NAL unit of type %d", type);
22859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
22869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
22879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
22889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    for (size_t i = 0; i < ARRAY_SIZE(kHevcNalUnitTypes); ++i) {
22899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        int type = kHevcNalUnitTypes[i];
22909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        size_t numParamSets = paramSets.getNumNalUnitsOfType(type);
22919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (numParamSets > 0xffff) {
22929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            ALOGE("Too many seq parameter sets (%zu) found", numParamSets);
22939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
22949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
22959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        csdSize += 3;
22969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        for (size_t j = 0; j < numNalUnits; ++j) {
22979aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            if (paramSets.getType(j) != type) {
22989aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                continue;
22999aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            }
23009aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            csdSize += 2 + paramSets.getSize(j);
23019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
23029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
23039aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificDataSize = csdSize;
23049aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return OK;
23059aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
23069aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
23079aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::makeHEVCCodecSpecificData(
23089aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size) {
23099aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
23109aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData != NULL) {
23119aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Already have codec specific data");
23129aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
23139aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
23149aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
23159aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (size < 4) {
23169aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Codec specific data length too short: %zu", size);
23179aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
23189aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
23199aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
23209aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Data is in the form of HEVCCodecSpecificData
23219aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (memcmp("\x00\x00\x00\x01", data, 4)) {
23229aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return copyHEVCCodecSpecificData(data, size);
23239aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
23249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
23259aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    HevcParameterSets paramSets;
23269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (parseHEVCCodecSpecificData(data, size, paramSets) != OK) {
23273d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim        ALOGE("failed parsing codec specific data");
23289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
23299aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
23309aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
23319aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificData = malloc(mCodecSpecificDataSize);
23329aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
23339aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mCodecSpecificDataSize = 0;
23349aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
23359aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
23369aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
23379aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t err = paramSets.makeHvcc((uint8_t *)mCodecSpecificData,
23383d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim            &mCodecSpecificDataSize, mOwner->useNalLengthFour() ? 4 : 2);
23399aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (err != OK) {
23403d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim        ALOGE("failed constructing HVCC atom");
23419aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return err;
23429aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
23439aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
23449aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return OK;
23459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
23469aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
2347872a481558350634a3fd5cb67939de288af00ecbJames Dong/*
2348872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that
2349872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information
2350872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio
2351872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger
2352872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5,
2353872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined.
2354872a481558350634a3fd5cb67939de288af00ecbJames Dong */
2355872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) {
2356872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t driftTimeUs = 0;
2357872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) {
2358872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t prevDriftTimeUs = mOwner->getDriftTimeUs();
2359872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1;
2360872a481558350634a3fd5cb67939de288af00ecbJames Dong        mOwner->setDriftTimeUs(timeUs);
2361872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2362872a481558350634a3fd5cb67939de288af00ecbJames Dong}
2363872a481558350634a3fd5cb67939de288af00ecbJames Dong
236437187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() {
236530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
236613aec890216948b0c364f8f92792129d0335f506James Dong    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
236743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    const bool hasMultipleTracks = (mOwner->numTracks() > 1);
236813aec890216948b0c364f8f92792129d0335f506James Dong    int64_t chunkTimestampUs = 0;
236913aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nChunks = 0;
23707c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar    int32_t nActualFrames = 0;        // frames containing non-CSD data (non-0 length)
237113aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nZeroLengthFrames = 0;
2372965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastTimestampUs = 0;      // Previous sample time stamp
2373965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationUs = 0;       // Between the previous two samples
2374965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t currDurationTicks = 0;    // Timescale based ticks
2375965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationTicks = 0;    // Timescale based ticks
2376965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int32_t sampleCount = 1;          // Sample count in the current stts table entry
2377000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    uint32_t previousSampleSize = 0;  // Size of the previous sample
2378a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t previousPausedDurationUs = 0;
2379965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t timestampUs = 0;
2380000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t cttsOffsetTimeUs = 0;
2381000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t currCttsOffsetTimeTicks = 0;   // Timescale based ticks
2382000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t lastCttsOffsetTimeTicks = -1;  // Timescale based ticks
238343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    int32_t cttsSampleCount = 0;           // Sample count in the current ctts table entry
2384c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t lastSamplesPerChunk = 0;
2385e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2386a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    if (mIsAudio) {
2387a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
238825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else if (mIsVideo) {
2389a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
239025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else {
239125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        prctl(PR_SET_NAME, (unsigned long)"MetadataTrackEncoding", 0, 0, 0);
2392a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    }
2393de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
2394de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (mOwner->isRealTimeRecording()) {
2395de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
2396de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    }
2397985f838934510983d8a887461e98dca60a6e858fJames Dong
2398d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong    sp<MetaData> meta_data;
239920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
240093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t err = OK;
240120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
240225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    const char *trackName = getTrackType();
240393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    while (!mDone && (err = mSource->read(&buffer)) == OK) {
240420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
240520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
240620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
240713aec890216948b0c364f8f92792129d0335f506James Dong            ++nZeroLengthFrames;
240820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
240920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
241020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2411a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // If the codec specific data has not been received yet, delay pause.
2412a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // After the codec specific data is received, discard what we received
2413a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // when the track is to be paused.
2414a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused && !mResumed) {
2415a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer->release();
2416a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer = NULL;
2417a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            continue;
2418a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2419a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
242030ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
242130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
242203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
242303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
242403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
24257c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // if config format (at track addition) already had CSD, keep that
24267c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // UNLESS we have not received any frames yet.
24277c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // TODO: for now the entire CSD has to come in one frame for encoders, even though
24287c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // they need to be spread out for decoders.
24297c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            if (mGotAllCodecSpecificData && nActualFrames > 0) {
24307c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                ALOGI("ignoring additional CSD for video track after first frame");
24317c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            } else {
24327c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                mMeta = mSource->getFormat(); // get output format after format change
24337c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar
24347c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                if (mIsAvc) {
24357c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    status_t err = makeAVCCodecSpecificData(
24367c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            (const uint8_t *)buffer->data()
24377c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                                + buffer->range_offset(),
24387c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
24397c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    CHECK_EQ((status_t)OK, err);
24407c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                } else if (mIsHevc) {
24417c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    status_t err = makeHEVCCodecSpecificData(
24427c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            (const uint8_t *)buffer->data()
24437c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                                + buffer->range_offset(),
24447c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
24457c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    CHECK_EQ((status_t)OK, err);
24467c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                } else if (mIsMPEG4) {
24477c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    copyCodecSpecificData((const uint8_t *)buffer->data() + buffer->range_offset(),
24487c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
24497c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                }
245030ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
245130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
245230ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
245330ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
245430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
2455548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
245630ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
2457a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2458a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2459e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang        // Per-frame metadata sample's size must be smaller than max allowed.
2460e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang        if (!mIsVideo && !mIsAudio && buffer->range_length() >= kMaxMetadataSize) {
2461e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            ALOGW("Buffer size is %zu. Maximum metadata buffer size is %lld for %s track",
2462e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang                    buffer->range_length(), (long long)kMaxMetadataSize, trackName);
2463e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            buffer->release();
2464e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            mSource->stop();
2465e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            mIsMalformed = true;
2466e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            break;
2467e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang        }
2468e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang
24697c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar        ++nActualFrames;
24707c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar
2471d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // Make a deep copy of the MediaBuffer and Metadata and release
2472d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // the original as soon as we can
2473d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
2474d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
2475d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                buffer->range_length());
2476d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        copy->set_range(0, buffer->range_length());
2477d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data = new MetaData(*buffer->meta_data().get());
2478d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer->release();
2479d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer = NULL;
2480d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
24819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (mIsAvc || mIsHevc) StripStartcode(copy);
2482e136c3bb38e88315bf8797a464ebf2c788296b22James Dong
2483b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        size_t sampleSize = copy->range_length();
24849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (mIsAvc || mIsHevc) {
2485b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            if (mOwner->useNalLengthFour()) {
2486b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 4;
2487b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            } else {
2488b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 2;
2489b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            }
2490b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        }
2491050b28a593350047845a45a14cc5026221ac1620James Dong
2492d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        // Max file size or duration handling
24931f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mMdatSizeBytes += sampleSize;
24941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        updateTrackSizeEstimate();
24951f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
2496d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileSizeLimit()) {
2497316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang            ALOGW("Recorded file size exceeds limit %" PRId64 "bytes",
2498316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang                    mOwner->mMaxFileSizeLimitBytes);
2499d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
2500d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            copy->release();
2501d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            mSource->stop();
2502d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2503d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2504d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileDurationLimit()) {
2505316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang            ALOGW("Recorded file duration exceeds limit %" PRId64 "microseconds",
2506316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang                    mOwner->mMaxFileDurationLimitUs);
2507d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
2508d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            copy->release();
2509d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            mSource->stop();
2510d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2511d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2512d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2513050b28a593350047845a45a14cc5026221ac1620James Dong
2514d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        int32_t isSync = false;
2515d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
2516d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
2517d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
2518d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong////////////////////////////////////////////////////////////////////////////////
2519c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (mStszTableEntries->count() == 0) {
252070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mFirstSampleTimeRealUs = systemTime() / 1000;
2521f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimestampUs = timestampUs;
2522f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mOwner->setStartTimestampUs(mStartTimestampUs);
25238428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs = mStartTimestampUs;
25243c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        }
252548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
2526a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mResumed) {
25278428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
252811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) {
252911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
2530d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang                mSource->stop();
25319db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                mIsMalformed = true;
25329db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                break;
253311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
253411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
25358428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
253611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) {
253711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
2538d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang                mSource->stop();
25399db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                mIsMalformed = true;
25409db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                break;
254111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
254211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
25438428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs += pausedDurationUs - lastDurationUs;
2544a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mResumed = false;
2545a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2546a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2547a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        timestampUs -= previousPausedDurationUs;
254811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
254911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
2550d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            mSource->stop();
25519db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            mIsMalformed = true;
25529db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            break;
255311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        }
255411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
255525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        if (mIsVideo) {
2556965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            /*
2557965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Composition time: timestampUs
2558965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Decoding time: decodingTimeUs
2559000e18370baae60ffd9f25b509501dd8c26deabfJames Dong             * Composition time offset = composition time - decoding time
2560965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             */
2561965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            int64_t decodingTimeUs;
2562965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
2563965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            decodingTimeUs -= previousPausedDurationUs;
2564826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar
2565826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            // ensure non-negative, monotonic decoding time
2566826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            if (mLastDecodingTimeUs < 0) {
2567826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar                decodingTimeUs = std::max((int64_t)0, decodingTimeUs);
2568826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            } else {
2569826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar                // increase decoding time by at least 1 tick
2570826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar                decodingTimeUs = std::max(
2571826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar                        mLastDecodingTimeUs + divUp(1000000, mTimeScale), decodingTimeUs);
2572826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            }
2573826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar
2574826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            mLastDecodingTimeUs = decodingTimeUs;
2575000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            cttsOffsetTimeUs =
2576000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
257711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) {
257811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
2579d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang                mSource->stop();
25809db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                mIsMalformed = true;
25819db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                break;
258211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
258311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2584965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            timestampUs = decodingTimeUs;
2585a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGV("decoding time: %" PRId64 " and ctts offset time: %" PRId64,
2586000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                timestampUs, cttsOffsetTimeUs);
2587000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2588000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts box table if necessary
2589000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            currCttsOffsetTimeTicks =
2590000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL;
259111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) {
259211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
2593d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang                mSource->stop();
25949db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                mIsMalformed = true;
25959db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                break;
259611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
259711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2598c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 0) {
259943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // Force the first ctts table entry to have one single entry
260043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // so that we can do adjustment for the initial track start
260143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // time offset easily in writeCttsBox().
260243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
260343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                addOneCttsTableEntry(1, currCttsOffsetTimeTicks);
260443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                cttsSampleCount = 0;      // No sample in ctts box is pending
260543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            } else {
260643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) {
260743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
260843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
260943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    cttsSampleCount = 1;  // One sample in ctts box is pending
261043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                } else {
261143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    ++cttsSampleCount;
261243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                }
261343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            }
2614000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2615000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts time offset range
2616c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 0) {
2617000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2618000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2619000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            } else {
2620000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) {
2621000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2622000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) {
2623000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2624000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                }
2625000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            }
2626000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2627965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        }
2628872a481558350634a3fd5cb67939de288af00ecbJames Dong
2629de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        if (mOwner->isRealTimeRecording()) {
2630872a481558350634a3fd5cb67939de288af00ecbJames Dong            if (mIsAudio) {
2631872a481558350634a3fd5cb67939de288af00ecbJames Dong                updateDriftTime(meta_data);
2632e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
2633e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
2634872a481558350634a3fd5cb67939de288af00ecbJames Dong
263511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
263611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
2637d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            mSource->stop();
26389db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            mIsMalformed = true;
26399db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            break;
264011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        }
264111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2642a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("%s media time stamp: %" PRId64 " and previous paused duration %" PRId64,
264311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                trackName, timestampUs, previousPausedDurationUs);
2644c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong        if (timestampUs > mTrackDurationUs) {
2645c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong            mTrackDurationUs = timestampUs;
26463b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        }
26473b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber
26485a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // We need to use the time scale based ticks, rather than the
26495a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // timestamp itself to determine whether we have to use a new
26505a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // stts entry, since we may have rounding errors.
26515a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // The calculation is intended to reduce the accumulated
26525a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // rounding errors.
26535a217fba010e801c255503602bda4b86ac5a6ac9James Dong        currDurationTicks =
26545a217fba010e801c255503602bda4b86ac5a6ac9James Dong            ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
26555a217fba010e801c255503602bda4b86ac5a6ac9James Dong                (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
2656c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (currDurationTicks < 0ll) {
2657f85a83af8c6a98b46c394c32b90b09214a68f3e4Hangyu Kuang            ALOGE("do not support out of order frames (timestamp: %lld < last: %lld for %s track",
2658f85a83af8c6a98b46c394c32b90b09214a68f3e4Hangyu Kuang                    (long long)timestampUs, (long long)lastTimestampUs, trackName);
265911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
26600332fadec6e91c37fe39ab92b2c02922370bc853Hangyu Kuang            mSource->stop();
26619db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            mIsMalformed = true;
26629db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            break;
26638c460498c028888c533ab442be12b6d4b669b965James Dong        }
26648c460498c028888c533ab442be12b6d4b669b965James Dong
266585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // if the duration is different for this sample, see if it is close enough to the previous
266685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // duration that we can fudge it and use the same value, to avoid filling the stts table
266785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // with lots of near-identical entries.
266885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // "close enough" here means that the current duration needs to be adjusted by less
266985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // than 0.1 milliseconds
267085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) {
267185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL
267285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                    + (mTimeScale / 2)) / mTimeScale;
267385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            if (deltaUs > -100 && deltaUs < 100) {
267485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                // use previous ticks, and adjust timestamp as if it was actually that number
267585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                // of ticks
267685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                currDurationTicks = lastDurationTicks;
267785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                timestampUs += deltaUs;
267885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            }
267985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        }
2680c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStszTableEntries->add(htonl(sampleSize));
2681c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (mStszTableEntries->count() > 2) {
2682c059860c73678a202bfa33062723e8f82fb779d9James Dong
2683a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // Force the first sample to have its own stts entry so that
2684a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // we can adjust its value later to maintain the A/V sync.
2685c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) {
268679761ab096f57c3027fad9556c2bc436672d614eJames Dong                addOneSttsTableEntry(sampleCount, lastDurationTicks);
2687be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                sampleCount = 1;
2688be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
2689be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                ++sampleCount;
2690be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
2691965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2692be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
2693be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        if (mSamplesHaveSameSize) {
2694c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) {
2695be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSamplesHaveSameSize = false;
2696be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
26978644c14618d30d9e57a69df40ed939986ebf02c4James Dong            previousSampleSize = sampleSize;
2698be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
2699a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("%s timestampUs/lastTimestampUs: %" PRId64 "/%" PRId64,
270011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                trackName, timestampUs, lastTimestampUs);
27018644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastDurationUs = timestampUs - lastTimestampUs;
2702c059860c73678a202bfa33062723e8f82fb779d9James Dong        lastDurationTicks = currDurationTicks;
27038644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastTimestampUs = timestampUs;
270420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2705d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        if (isSync != 0) {
2706c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            addOneStssTableEntry(mStszTableEntries->count());
2707d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        }
2708d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
270993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (mTrackingProgressStatus) {
271093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            if (mPreviousTrackTimeUs <= 0) {
271193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong                mPreviousTrackTimeUs = mStartTimestampUs;
271293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            }
2713faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong            trackProgressStatus(timestampUs);
271493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
271543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        if (!hasMultipleTracks) {
271680f78b773f92048944a850efb7b60629643370cdPraveen Chavan            off64_t offset = (mIsAvc || mIsHevc) ? mOwner->addMultipleLengthPrefixedSamples_l(copy)
271758ae9c530247668f8af36e30d228c716c226b3d4James Dong                                 : mOwner->addSample_l(copy);
2718c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2719c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t count = (mOwner->use32BitFileOffset()
2720c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        ? mStcoTableEntries->count()
2721c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        : mCo64TableEntries->count());
2722c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2723c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (count == 0) {
27241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                addChunkOffset(offset);
272558ae9c530247668f8af36e30d228c716c226b3d4James Dong            }
272658ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy->release();
272758ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy = NULL;
272858ae9c530247668f8af36e30d228c716c226b3d4James Dong            continue;
272958ae9c530247668f8af36e30d228c716c226b3d4James Dong        }
273013aec890216948b0c364f8f92792129d0335f506James Dong
273113aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.push_back(copy);
273213aec890216948b0c364f8f92792129d0335f506James Dong        if (interleaveDurationUs == 0) {
27331f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStscTableEntry(++nChunks, 1);
27341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            bufferChunk(timestampUs);
273513aec890216948b0c364f8f92792129d0335f506James Dong        } else {
273613aec890216948b0c364f8f92792129d0335f506James Dong            if (chunkTimestampUs == 0) {
273713aec890216948b0c364f8f92792129d0335f506James Dong                chunkTimestampUs = timestampUs;
273813aec890216948b0c364f8f92792129d0335f506James Dong            } else {
273943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                int64_t chunkDurationUs = timestampUs - chunkTimestampUs;
274043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                if (chunkDurationUs > interleaveDurationUs) {
274143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    if (chunkDurationUs > mMaxChunkDurationUs) {
274243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                        mMaxChunkDurationUs = chunkDurationUs;
274343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    }
274413aec890216948b0c364f8f92792129d0335f506James Dong                    ++nChunks;
274513aec890216948b0c364f8f92792129d0335f506James Dong                    if (nChunks == 1 ||  // First chunk
2746c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk != mChunkSamples.size()) {
2747c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk = mChunkSamples.size();
2748c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        addOneStscTableEntry(nChunks, lastSamplesPerChunk);
274913aec890216948b0c364f8f92792129d0335f506James Dong                    }
27501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                    bufferChunk(timestampUs);
275113aec890216948b0c364f8f92792129d0335f506James Dong                    chunkTimestampUs = timestampUs;
275213aec890216948b0c364f8f92792129d0335f506James Dong                }
275313aec890216948b0c364f8f92792129d0335f506James Dong            }
275413aec890216948b0c364f8f92792129d0335f506James Dong        }
275513aec890216948b0c364f8f92792129d0335f506James Dong
275620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
275725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
275845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (isTrackMalFormed()) {
2759690f546b0ee548dbfe997df36418e5302ec2d786James Dong        err = ERROR_MALFORMED;
2760f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    }
276145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
2762bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    mOwner->trackProgressStatus(mTrackId, -1, err);
2763be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
276413aec890216948b0c364f8f92792129d0335f506James Dong    // Last chunk
276543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (!hasMultipleTracks) {
2766c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        addOneStscTableEntry(1, mStszTableEntries->count());
276758ae9c530247668f8af36e30d228c716c226b3d4James Dong    } else if (!mChunkSamples.empty()) {
27681f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        addOneStscTableEntry(++nChunks, mChunkSamples.size());
27691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        bufferChunk(timestampUs);
277013aec890216948b0c364f8f92792129d0335f506James Dong    }
277113aec890216948b0c364f8f92792129d0335f506James Dong
2772be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // We don't really know how long the last frame lasts, since
2773be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // there is no frame time after it, just repeat the previous
2774be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // frame's duration.
2775c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() == 1) {
27768f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        lastDurationUs = 0;  // A single sample's duration
277779761ab096f57c3027fad9556c2bc436672d614eJames Dong        lastDurationTicks = 0;
2778be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    } else {
2779be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        ++sampleCount;  // Count for the last sample
2780be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    }
2781a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2782c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() <= 2) {
278379761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(1, lastDurationTicks);
2784a472613aec322e25891abf5c77bf3f7e3c244920James Dong        if (sampleCount - 1 > 0) {
278579761ab096f57c3027fad9556c2bc436672d614eJames Dong            addOneSttsTableEntry(sampleCount - 1, lastDurationTicks);
2786a472613aec322e25891abf5c77bf3f7e3c244920James Dong        }
2787a472613aec322e25891abf5c77bf3f7e3c244920James Dong    } else {
278879761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(sampleCount, lastDurationTicks);
2789a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
2790a472613aec322e25891abf5c77bf3f7e3c244920James Dong
279143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // The last ctts box may not have been written yet, and this
279243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // is to make sure that we write out the last ctts box.
279343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) {
279443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        if (cttsSampleCount > 0) {
279543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
279643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        }
279743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    }
279843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong
2799c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs += lastDurationUs;
280025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
280143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
280243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    sendTrackSummary(hasMultipleTracks);
280343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
2804df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
280511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            count, nZeroLengthFrames, mStszTableEntries->count(), trackName);
2806872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (mIsAudio) {
2807a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Audio track drift time: %" PRId64 " us", mOwner->getDriftTimeUs());
2808872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2809365a963142093a1cd8efdcea76b5f65096a5b115James Dong
281037187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err == ERROR_END_OF_STREAM) {
281137187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
281237187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
281337187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
2814365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
2815365a963142093a1cd8efdcea76b5f65096a5b115James Dong
281645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const {
28179db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang    if (mIsMalformed) {
28189db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang        return true;
28199db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang    }
28209db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang
2821c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() == 0) {                      // no samples written
282229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("The number of recorded samples is 0");
282345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
282445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
282545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
282625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (mIsVideo && mStssTableEntries->count() == 0) {  // no sync frames for video
282729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("There are no sync frames for video track");
282845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
282945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
283045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
283145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (OK != checkCodecSpecificData()) {         // no codec specific data
283245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
283345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
283445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
283545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    return false;
283645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong}
283745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
283843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) {
283907ec01904613a0bac32caaa8444b4690998faed7James Dong
284007ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send track summary only if test mode is enabled.
284107ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
284207ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
284307ec01904613a0bac32caaa8444b4690998faed7James Dong    }
284407ec01904613a0bac32caaa8444b4690998faed7James Dong
284543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int trackNum = (mTrackId << 28);
284643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
284743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
284843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE,
284925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang                    mIsAudio ? 0: 1);
285043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
285143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
285243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS,
285343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mTrackDurationUs / 1000);
285443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
285543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
285643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES,
2857c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    mStszTableEntries->count());
285843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
285986b7f47aa7482424cf8fd248f1315311919be3b0James Dong    {
286086b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // The system delay time excluding the requested initial delay that
286186b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // is used to eliminate the recording sound.
286286b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
286386b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
286486b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
286586b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
286686b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t initialDelayUs =
286786b7f47aa7482424cf8fd248f1315311919be3b0James Dong            mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs;
286886b7f47aa7482424cf8fd248f1315311919be3b0James Dong
286986b7f47aa7482424cf8fd248f1315311919be3b0James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
287070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS,
287170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    (initialDelayUs) / 1000);
287286b7f47aa7482424cf8fd248f1315311919be3b0James Dong    }
287370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
287407ec01904613a0bac32caaa8444b4690998faed7James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
287507ec01904613a0bac32caaa8444b4690998faed7James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES,
287607ec01904613a0bac32caaa8444b4690998faed7James Dong                    mMdatSizeBytes / 1024);
287707ec01904613a0bac32caaa8444b4690998faed7James Dong
287843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (hasMultipleTracks) {
287943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
288043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS,
288143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mMaxChunkDurationUs / 1000);
288270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
288370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
288470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        if (mStartTimestampUs != moovStartTimeUs) {
288570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
288670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
288770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS,
288870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    startTimeOffsetUs / 1000);
288970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        }
289043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    }
289143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong}
289243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
2893faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
2894a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("trackProgressStatus: %" PRId64 " us", timeUs);
2895c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2896215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    if (mTrackEveryTimeDurationUs > 0 &&
2897215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
2898a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("Fire time tracking progress status at %" PRId64 " us", timeUs);
2899bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err);
290093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        mPreviousTrackTimeUs = timeUs;
290193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
290293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
290393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
2904faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus(
2905bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        size_t trackId, int64_t timeUs, status_t err) {
2906faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    Mutex::Autolock lock(mLock);
2907bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t trackNum = (trackId << 28);
2908faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2909faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Error notification
2910faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Do not consider ERROR_END_OF_STREAM an error
2911faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (err != OK && err != ERROR_END_OF_STREAM) {
2912bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
2913bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL,
2914faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2915faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
2916faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2917faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2918faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (timeUs == -1) {
2919faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send completion notification
2920bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2921bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS,
2922faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2923faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    } else {
2924faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send progress status
2925bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2926bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME,
2927faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               timeUs / 1000);
2928faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2929faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong}
2930faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2931d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) {
2932a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("setDriftTimeUs: %" PRId64 " us", driftTimeUs);
2933e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2934d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    mDriftTimeUs = driftTimeUs;
2935e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2936e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2937e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() {
2938a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("getDriftTimeUs: %" PRId64 " us", mDriftTimeUs);
2939e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2940e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    return mDriftTimeUs;
2941e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2942e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2943de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghuibool MPEG4Writer::isRealTimeRecording() const {
2944de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    return mIsRealTimeRecording;
2945de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui}
2946de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
2947b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() {
2948b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    return mUse4ByteNalLength;
2949b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong}
2950b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
29511c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
29523856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk");
29531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
29541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Chunk chunk(this, timestampUs, mChunkSamples);
29551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mOwner->bufferChunk(chunk);
295613aec890216948b0c364f8f92792129d0335f506James Dong    mChunkSamples.clear();
295720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
295820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29593b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
2960c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    return mTrackDurationUs;
296120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
296220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2963d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
2964d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return mEstimatedTrackSizeBytes;
2965d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
2966d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2967690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const {
2968690f546b0ee548dbfe997df36418e5302ec2d786James Dong    const char *mime;
2969690f546b0ee548dbfe997df36418e5302ec2d786James Dong    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
2970690f546b0ee548dbfe997df36418e5302ec2d786James Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
2971690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
29729aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime) ||
29739aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        !strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
2974690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (!mCodecSpecificData ||
2975690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize <= 0) {
297629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Missing codec specific data");
2977690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2978690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2979690f546b0ee548dbfe997df36418e5302ec2d786James Dong    } else {
2980690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (mCodecSpecificData ||
2981690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize > 0) {
298229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Unexepected codec specific data found");
2983690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2984690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2985690f546b0ee548dbfe997df36418e5302ec2d786James Dong    }
2986690f546b0ee548dbfe997df36418e5302ec2d786James Dong    return OK;
2987690f546b0ee548dbfe997df36418e5302ec2d786James Dong}
2988690f546b0ee548dbfe997df36418e5302ec2d786James Dong
298925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangconst char *MPEG4Writer::Track::getTrackType() const {
299025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    return mIsAudio ? "Audio" : (mIsVideo ? "Video" : "Metadata");
299125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang}
29928f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
299325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) {
2994efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
2995b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("trak");
2996b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeTkhdBox(now);
2997b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("mdia");
2998b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeMdhdBox(now);
2999b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeHdlrBox();
3000b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->beginBox("minf");
3001b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                if (mIsAudio) {
3002b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeSmhdBox();
300325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang                } else if (mIsVideo) {
3004b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeVmhdBox();
300525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang                } else {
300625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang                    writeNmhdBox();
3007b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                }
3008b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeDinfBox();
3009b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeStblBox(use32BitOffset);
3010b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->endBox();  // minf
3011b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->endBox();  // mdia
3012b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // trak
3013b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3014b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3015b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) {
3016b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stbl");
3017b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsd");
3018b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);               // version=0, flags=0
3019b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);               // entry count
3020b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
3021b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAudioFourCCBox();
302225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else if (mIsVideo) {
3023b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeVideoFourCCBox();
302425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else {
302525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        writeMetadataFourCCBox();
3026b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3027b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsd
3028b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeSttsBox();
302925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (mIsVideo) {
303025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        writeCttsBox();
3031b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeStssBox();
3032b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3033b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStszBox();
3034b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStscBox();
3035b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStcoBox(use32BitOffset);
3036b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stbl
3037b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3038b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
303925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeMetadataFourCCBox() {
304025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    const char *mime;
304125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    bool success = mMeta->findCString(kKeyMIMEType, &mime);
304225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    CHECK(success);
304325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    const char *fourcc = getFourCCForMime(mime);
304425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (fourcc == NULL) {
304525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        ALOGE("Unknown mime type '%s'.", mime);
304625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        TRESPASS();
304725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    }
304825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->beginBox(fourcc);    // TextMetaDataSampleEntry
304925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->writeCString(mime);  // metadata mime_format
305025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->endBox(); // mett
305125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang}
305225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang
3053b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() {
3054b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
3055b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
3056b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
30578b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    const char *fourcc = getFourCCForMime(mime);
30588b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (fourcc == NULL) {
305929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
306025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        TRESPASS();
3061b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3062b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
30638b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    mOwner->beginBox(fourcc);        // video format
3064b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3065b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3066b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // data ref index
3067b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
3068b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3069b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
3070b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
3071b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
3072b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3073b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t width, height;
3074b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeyWidth, &width);
3075b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = success && mMeta->findInt32(kKeyHeight, &height);
3076b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
3077b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3078b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(width);
3079b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(height);
3080b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // horiz resolution
3081b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // vert resolution
3082b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3083b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // frame count
3084c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo    mOwner->writeInt8(0);            // compressor string length
3085c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo    mOwner->write("                               ", 31);
3086b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x18);        // depth
3087b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(-1);          // predefined
3088b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3089b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
3090b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4vEsdsBox();
3091b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
3092b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeD263Box();
3093b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
3094b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAvccBox();
30959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
30969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        writeHvccBox();
3097b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3098b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3099b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writePaspBox();
310058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    writeColrBox();
3101b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // mp4v, s263 or avc1
3102b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3103b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
310458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnarvoid MPEG4Writer::Track::writeColrBox() {
310558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    ColorAspects aspects;
310658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    memset(&aspects, 0, sizeof(aspects));
310758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    // TRICKY: using | instead of || because we want to execute all findInt32-s
310858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    if (mMeta->findInt32(kKeyColorPrimaries, (int32_t*)&aspects.mPrimaries)
310958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyTransferFunction, (int32_t*)&aspects.mTransfer)
311058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyColorMatrix, (int32_t*)&aspects.mMatrixCoeffs)
311158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyColorRange, (int32_t*)&aspects.mRange)) {
311258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        int32_t primaries, transfer, coeffs;
311358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        bool fullRange;
311458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        ColorUtils::convertCodecColorAspectsToIsoAspects(
311558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar                aspects, &primaries, &transfer, &coeffs, &fullRange);
311658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->beginBox("colr");
311758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeFourcc("nclx");
311858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(primaries);
311958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(transfer);
312058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(coeffs);
3121fffb0c8fbe16ac948619b85e1eea9e65a9daa0c9Pirama Arumuga Nainar        mOwner->writeInt8(int8_t(fullRange ? 0x80 : 0x0));
312258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->endBox(); // colr
312358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    }
312458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar}
312558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
3126b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() {
3127b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
3128b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
3129b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
31308b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    const char *fourcc = getFourCCForMime(mime);
31318b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (fourcc == NULL) {
313229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
313325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        TRESPASS();
3134b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3135b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3136b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(fourcc);        // audio format
3137b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3138b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3139b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x1);         // data ref index
3140b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3141b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3142b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t nChannels;
3143b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
3144b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(nChannels);   // channel count
3145b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(16);          // sample size
3146b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
3147b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3148b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3149b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t samplerate;
3150b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeySampleRate, &samplerate);
3151b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
3152b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(samplerate << 16);
3153b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
3154b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4aEsdsBox();
3155b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
3156b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong               !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
3157b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeDamrBox();
3158b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3159b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3160b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3161b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3162b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() {
3163b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
3164b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
316543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mCodecSpecificDataSize, 0);
3166b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3167b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Make sure all sizes encode to a single byte.
316843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_LT(mCodecSpecificDataSize + 23, 128);
3169b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3170b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);     // version=0, flags=0
3171b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);   // ES_DescrTag
3172b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
3173b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);// ES_ID
3174b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x00);
3175b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3176b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
3177b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
3178b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
3179b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x15);   // streamType AudioStream
3180b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3181b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x03);  // XXX
318246f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt8(0x00);   // buffer size 24-bit (0x300)
318346f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar
318496bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t avgBitrate = 0;
318546f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyBitRate, &avgBitrate);
318696bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t maxBitrate = 0;
318746f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate);
318846f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(maxBitrate);
318946f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(avgBitrate);
3190b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3191b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
3192b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
3193b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3194b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3195b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
3196b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
3197b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
3198b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
3199b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3200b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
3201b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3202b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
3203b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3204b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3205b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() {
3206b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
320743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mCodecSpecificDataSize, 0);
3208bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan
3209bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan    // Make sure all sizes encode to a single byte.
3210bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan    CHECK_LT(23 + mCodecSpecificDataSize, 128);
3211bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan
3212b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
3213b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3214b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);    // version=0, flags=0
3215b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3216b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);  // ES_DescrTag
3217b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
3218b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);  // ES_ID
3219b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x1f);
3220b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3221b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
3222b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
3223b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
3224b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x11);  // streamType VisualStream
3225b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3226b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData[] = {
322746f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar        0x01, 0x77, 0x00, // buffer size 96000 bytes
3228b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3229b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData, sizeof(kData));
3230b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
323196bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t avgBitrate = 0;
323246f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyBitRate, &avgBitrate);
323396bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t maxBitrate = 0;
323446f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate);
323546f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(maxBitrate);
323646f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(avgBitrate);
323746f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar
3238b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
3239b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3240b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
3241b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3242b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3243b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
3244b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
3245b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
3246b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
3247b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3248b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
3249b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3250b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
3251b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3252b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3253efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeTkhdBox(uint32_t now) {
3254b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("tkhd");
3255b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Flags = 7 to indicate that the track is enabled, and
3256b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // part of the presentation
3257b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x07);          // version=0, flags=7
3258b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
3259b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
3260219f195159f93d627af2b243732e3f9020511a46James Dong    mOwner->writeInt32(mTrackId);      // track id starts with 1
3261b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
32628f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t trakDurationUs = getDurationUs();
3263b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mvhdTimeScale = mOwner->getTimeScale();
3264b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t tkhdDuration =
3265b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
3266b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
3267b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3268b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3269b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // layer
3270b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // alternate group
3271b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
3272b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // reserved
3273b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3274b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCompositionMatrix(mRotation);       // matrix
327520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
327625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (!mIsVideo) {
3277b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
3278b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
3279b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
3280b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        int32_t width, height;
3281b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        bool success = mMeta->findInt32(kKeyWidth, &width);
3282b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        success = success && mMeta->findInt32(kKeyHeight, &height);
3283b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(success);
3284b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3285b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
3286b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
3287b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3288b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // tkhd
3289b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3290b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3291b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() {
3292b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("vmhd");
3293b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x01);        // version=0, flags=1
3294b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // graphics mode
3295b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // opcolor
3296b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
3297b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
3298b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3299b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3300b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3301b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() {
3302b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("smhd");
3303b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // version=0, flags=0
3304b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // balance
3305b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3306b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3307b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3308b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
330925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeNmhdBox() {
331025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->beginBox("nmhd");
331125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->writeInt32(0);           // version=0, flags=0
331225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->endBox();
331325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang}
331425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang
3315b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() {
3316b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("hdlr");
3317b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
3318b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // component type: should be mhlr
331925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->writeFourcc(mIsAudio ? "soun" : (mIsVideo ? "vide" : "meta"));  // component subtype
3320b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3321b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3322b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3323b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Removing "r" for the name string just makes the string 4 byte aligned
332425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->writeCString(mIsAudio ? "SoundHandle": (mIsVideo ? "VideoHandle" : "MetadHandle"));
3325b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3326b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3327b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3328efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeMdhdBox(uint32_t now) {
3329b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t trakDurationUs = getDurationUs();
3330b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("mdhd");
3331b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
3332b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
3333b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
3334b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mTimeScale);    // media timescale
3335b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
3336b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mdhdDuration);  // use media timescale
3337b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Language follows the three letter standard ISO-639-2/T
3338b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 'e', 'n', 'g' for "English", for instance.
3339b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Each character is packed as the difference between its ASCII value and 0x60.
3340b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // For "English", these are 00101, 01110, 00111.
3341b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // XXX: Where is the padding bit located: 0x15C7?
3342decc50efede28c5d73137c30d1a95d72dd405555David Yeh    const char *lang = NULL;
3343decc50efede28c5d73137c30d1a95d72dd405555David Yeh    int16_t langCode = 0;
3344decc50efede28c5d73137c30d1a95d72dd405555David Yeh    if (mMeta->findCString(kKeyMediaLanguage, &lang) && lang && strnlen(lang, 3) > 2) {
3345decc50efede28c5d73137c30d1a95d72dd405555David Yeh        langCode = ((lang[0] & 0x1f) << 10) | ((lang[1] & 0x1f) << 5) | (lang[2] & 0x1f);
3346decc50efede28c5d73137c30d1a95d72dd405555David Yeh    }
3347decc50efede28c5d73137c30d1a95d72dd405555David Yeh    mOwner->writeInt16(langCode);      // language code
3348b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // predefined
3349b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3350b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3351b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3352b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() {
3353b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 3gpp2 Spec AMRSampleEntry fields
3354b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("damr");
3355b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString("   ");  // vendor: 4 bytes
3356b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // decoder version
3357b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x83FF);   // mode set: all enabled
3358b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // mode change period
3359b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(1);         // frames per sample
3360b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3361b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3362b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3363b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() {
3364b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // The table index here refers to the sample description index
3365b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // in the sample table entries.
3366b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("url ");
3367b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
3368b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // url
3369b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3370b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3371b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() {
3372b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dref");
3373b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3374b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // entry count (either url or urn)
3375b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeUrlBox();
3376b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dref
3377b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3378b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3379b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() {
3380b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dinf");
3381b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeDrefBox();
3382b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dinf
3383b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3384b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3385b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() {
3386b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
338743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(mCodecSpecificDataSize, 5);
3388b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3389b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Patch avcc's lengthSize field to match the number
3390b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // of bytes we use to indicate the size of a nal unit.
3391b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
3392b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
3393b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("avcC");
3394b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3395b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // avcC
3396b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3397b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
33989aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
33999aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimvoid MPEG4Writer::Track::writeHvccBox() {
34009aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    CHECK(mCodecSpecificData);
34019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    CHECK_GE(mCodecSpecificDataSize, 5);
34029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
34039aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Patch avcc's lengthSize field to match the number
34049aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // of bytes we use to indicate the size of a nal unit.
34059aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
34069aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ptr[21] = (ptr[21] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
34079aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->beginBox("hvcC");
34089aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
34099aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->endBox();  // hvcC
34109aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
34119aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
3412b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() {
3413b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("d263");
3414b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // vendor
3415b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // decoder version
3416b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(10);  // level: 10
3417b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // profile: 0
3418b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // d263
3419b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3420b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3421b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square
3422b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() {
3423b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("pasp");
3424b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // hspacing
3425b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // vspacing
3426b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // pasp
3427b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3428b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3429000e18370baae60ffd9f25b509501dd8c26deabfJames Dongint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const {
3430a472613aec322e25891abf5c77bf3f7e3c244920James Dong    int64_t trackStartTimeOffsetUs = 0;
3431b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
3432b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mStartTimestampUs != moovStartTimeUs) {
343343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_GT(mStartTimestampUs, moovStartTimeUs);
3434b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
3435b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3436000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    return (trackStartTimeOffsetUs *  mTimeScale + 500000LL) / 1000000LL;
3437000e18370baae60ffd9f25b509501dd8c26deabfJames Dong}
3438000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
3439000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() {
3440000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->beginBox("stts");
3441000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3442c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t duration;
3443c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    CHECK(mSttsTableEntries->get(duration, 1));
3444c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    duration = htonl(duration);  // Back to host byte order
3445c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1);
3446c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->write(mOwner);
3447b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stts
3448b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
344920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3450965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() {
3451000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    // There is no B frame at all
3452000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) {
3453000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        return;
3454000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    }
3455000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
3456965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    // Do not write ctts box when there is no need to have it.
3457c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mCttsTableEntries->count() == 0) {
3458965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
3459965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
3460965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3461a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("ctts box has %d entries with range [%" PRId64 ", %" PRId64 "]",
3462c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs);
3463965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3464965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->beginBox("ctts");
3465000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3466c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    uint32_t delta = mMinCttsOffsetTimeUs - getStartTimeOffsetScaledTime();
3467c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    mCttsTableEntries->adjustEntries([delta](size_t /* ix */, uint32_t (&value)[2]) {
3468c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        // entries are <count, ctts> pairs; adjust only ctts
3469c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        uint32_t duration = htonl(value[1]); // back to host byte order
3470c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        value[1] = htonl(duration - delta);
3471c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    });
3472c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->write(mOwner);
3473965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->endBox();  // ctts
3474965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
3475965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3476b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() {
3477b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stss");
3478b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3479c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->write(mOwner);
3480b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stss
3481b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
348225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
3483b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() {
3484b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsz");
3485b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3486c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mOwner->writeInt32(0);
3487c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries->write(mOwner);
3488b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsz
3489b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
349020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3491b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() {
3492b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsc");
3493b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3494c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries->write(mOwner);
3495b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsc
3496b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
349720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3498b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) {
3499b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(use32BitOffset? "stco": "co64");
3500b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3501c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (use32BitOffset) {
3502c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->write(mOwner);
3503c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
3504c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->write(mOwner);
3505b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3506b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stco or co64
350720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
350820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
350907b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() {
351007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("udta");
351107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeGeoDataBox();
351207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
351307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
351407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
3515e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeHdlr() {
3516e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("hdlr");
3517e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Version, Flags
3518e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Predefined
3519e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeFourcc("mdta");
3520e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[0]
3521e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[1]
3522e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[2]
3523e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt8(0);  // Name (empty)
3524e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3525e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3526e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3527e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeKeys() {
3528e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3529e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3530e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("keys");
3531e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0);     // Version, Flags
3532e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(count); // Entry_count
3533e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    for (size_t i = 0; i < count; i++) {
3534e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        AMessage::Type type;
3535e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        const char *key = mMetaKeys->getEntryNameAt(i, &type);
3536e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        size_t n = strlen(key);
3537e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writeInt32(n + 8);
3538e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writeFourcc("mdta");
3539e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        write(key, n); // write without the \0
3540e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3541e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3542e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3543e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3544e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeIlst() {
3545e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3546e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3547e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("ilst");
3548e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    for (size_t i = 0; i < count; i++) {
3549e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        beginBox(i + 1); // key id (1-based)
3550e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        beginBox("data");
3551e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        AMessage::Type type;
3552e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        const char *key = mMetaKeys->getEntryNameAt(i, &type);
3553e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        switch (type) {
35547c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            case AMessage::kTypeString:
35557c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            {
35567c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                AString val;
35577c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                CHECK(mMetaKeys->findString(key, &val));
35587c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(1); // type = UTF8
35597c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0); // default country/language
35607c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                write(val.c_str(), strlen(val.c_str())); // write without \0
35617c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                break;
35627c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            }
35637c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
3564e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            case AMessage::kTypeFloat:
3565e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3566e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                float val;
3567e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                CHECK(mMetaKeys->findFloat(key, &val));
35687c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(23); // type = float32
35697c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3570e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(*reinterpret_cast<int32_t *>(&val));
3571e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3572e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3573e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3574e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            case AMessage::kTypeInt32:
3575e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3576e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                int32_t val;
3577e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                CHECK(mMetaKeys->findInt32(key, &val));
35787c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(67); // type = signed int32
35797c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3580e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(val);
3581e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3582e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3583e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3584e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            default:
3585e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3586e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                ALOGW("Unsupported key type, writing 0 instead");
35877c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(77); // type = unsigned int32
35887c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3589e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(0);
3590e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3591e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3592e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        }
3593e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        endBox(); // data
3594e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        endBox(); // key id
3595e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3596e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox(); // ilst
3597e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3598e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3599e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeMetaBox() {
3600e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3601e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    if (count == 0) {
3602e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        return;
3603e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3604e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3605e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("meta");
3606e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeHdlr();
3607e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeKeys();
3608e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeIlst();
3609e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3610e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3611e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
361207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
361307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
361407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
361507b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() {
361607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("\xA9xyz");
361707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    /*
361807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * For historical reasons, any user data start
361907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * with "\0xA9", must be followed by its assoicated
362007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * language code.
3621432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x0012: text string length
3622432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x15c7: lang (locale) code: en
362307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     */
362407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt32(0x001215c7);
362507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLatitude(mLatitudex10000);
362607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLongitude(mLongitudex10000);
362707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt8(0x2F);
362807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
362907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
363007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
363120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
3632