MPEG4Writer.cpp revision 219f195159f93d627af2b243732e3f9020511a46
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#include <utils/Log.h>
20050b28a593350047845a45a14cc5026221ac1620James Dong
2120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <arpa/inet.h>
2220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <pthread.h>
24a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong#include <sys/prctl.h>
2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong#include <media/stagefright/foundation/ADebug.h>
2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h>
2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h>
2920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
3018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
3103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#include <media/stagefright/MediaErrors.h>
3220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h>
3320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h>
34d599cd4573b5a2d5914c5040e0565ef866749b77James Dong#include <media/mediarecorder.h>
3507ec01904613a0bac32caaa8444b4690998faed7James Dong#include <cutils/properties.h>
36674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong#include <sys/types.h>
37674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong#include <sys/stat.h>
38674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong#include <fcntl.h>
39674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong#include <unistd.h>
4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber#include "include/ESDS.h"
4219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4577e8ae9967a078770416619e99ddb5b010def312James Dongstatic const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024;
461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongstatic const int64_t kMax32BitFileSize = 0x007fffffffLL;
473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypeSeqParamSet = 0x07;
483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypePicParamSet = 0x08;
4970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongstatic const int64_t kInitialDelayTimeUs     = 700000LL;
505b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong
5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track {
5220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
53bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId);
548f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ~Track();
5620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t start(MetaData *params);
5837187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t stop();
5937187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t pause();
6025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool reachedEOS();
6120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
623b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    int64_t getDurationUs() const;
63d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t getEstimatedTrackSizeBytes() const;
64b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeTrackHeader(bool use32BitOffset = true);
651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void bufferChunk(int64_t timestampUs);
661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAvc() const { return mIsAvc; }
671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAudio() const { return mIsAudio; }
681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isMPEG4() const { return mIsMPEG4; }
69c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    void addChunkOffset(off64_t offset);
7070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int32_t getTrackId() const { return mTrackId; }
71dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    status_t dump(int fd, const Vector<String16>& args) const;
7220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
74000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    enum {
75000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        kMaxCttsOffsetTimeUs = 1000000LL,  // 1 second
768c460498c028888c533ab442be12b6d4b669b965James Dong        kSampleArraySize = 1000,
77000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    };
78000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
79c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    // A helper class to handle faster write box with table entries
80c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    template<class TYPE>
81c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    struct ListTableEntries {
82c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        ListTableEntries(uint32_t elementCapacity, uint32_t entryCapacity)
83c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            : mElementCapacity(elementCapacity),
84c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mEntryCapacity(entryCapacity),
85c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mTotalNumTableEntries(0),
86c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mNumValuesInCurrEntry(0),
87c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCurrTableEntriesElement(NULL) {
88c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_GT(mElementCapacity, 0);
89c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_GT(mEntryCapacity, 0);
90c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
91c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
92c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Free the allocated memory.
93c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        ~ListTableEntries() {
94c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (!mTableEntryList.empty()) {
95c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                typename List<TYPE *>::iterator it = mTableEntryList.begin();
96c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                delete[] (*it);
97c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.erase(it);
98c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
99c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
100c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
101c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Replace the value at the given position by the given value.
102c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // There must be an existing value at the given position.
103c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order
104c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
105c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void set(const TYPE& value, uint32_t pos) {
10625f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong            CHECK_LT(pos, mTotalNumTableEntries * mEntryCapacity);
107c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
108c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            typename List<TYPE *>::iterator it = mTableEntryList.begin();
109c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity));
110c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (it != mTableEntryList.end() && iterations > 0) {
111c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++it;
112c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                --iterations;
113c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
114c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK(it != mTableEntryList.end());
115c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_EQ(iterations, 0);
116c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
117c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            (*it)[(pos % (mElementCapacity * mEntryCapacity))] = value;
118c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
119c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
120c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Get the value at the given position by the given value.
121c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value the retrieved value at the position in network byte order.
122c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
123c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @return true if a value is found.
124c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        bool get(TYPE& value, uint32_t pos) const {
12525f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong            if (pos >= mTotalNumTableEntries * mEntryCapacity) {
126c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                return false;
127c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
128c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
129c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            typename List<TYPE *>::iterator it = mTableEntryList.begin();
130c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity));
131c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (it != mTableEntryList.end() && iterations > 0) {
132c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++it;
133c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                --iterations;
134c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
135c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK(it != mTableEntryList.end());
136c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_EQ(iterations, 0);
137c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
138c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            value = (*it)[(pos % (mElementCapacity * mEntryCapacity))];
139c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            return true;
140c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
141c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
142c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Store a single value.
143c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order.
144c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void add(const TYPE& value) {
145c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_LT(mNumValuesInCurrEntry, mElementCapacity);
146c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries % mElementCapacity;
147c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nValues  = mNumValuesInCurrEntry % mEntryCapacity;
148c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (nEntries == 0 && nValues == 0) {
149c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mCurrTableEntriesElement = new TYPE[mEntryCapacity * mElementCapacity];
150c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                CHECK(mCurrTableEntriesElement != NULL);
151c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.push_back(mCurrTableEntriesElement);
152c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
153c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
154c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t pos = nEntries * mEntryCapacity + nValues;
155c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCurrTableEntriesElement[pos] = value;
156c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
157c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            ++mNumValuesInCurrEntry;
158c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if ((mNumValuesInCurrEntry % mEntryCapacity) == 0) {
159c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++mTotalNumTableEntries;
160c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mNumValuesInCurrEntry = 0;
161c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
162c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
163c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
164c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Write out the table entries:
165c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 1. the number of entries goes first
166c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 2. followed by the values in the table enties in order
167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg writer the writer to actual write to the storage
168c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void write(MPEG4Writer *writer) const {
169c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_EQ(mNumValuesInCurrEntry % mEntryCapacity, 0);
170c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries;
171c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            writer->writeInt32(nEntries);
172c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            for (typename List<TYPE *>::iterator it = mTableEntryList.begin();
173c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                it != mTableEntryList.end(); ++it) {
174c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                CHECK_GT(nEntries, 0);
175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                if (nEntries >= mElementCapacity) {
176c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    writer->write(*it, sizeof(TYPE) * mEntryCapacity, mElementCapacity);
177c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    nEntries -= mElementCapacity;
178c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                } else {
179c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    writer->write(*it, sizeof(TYPE) * mEntryCapacity, nEntries);
180c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    break;
181c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                }
182c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
183c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
184c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Return the number of entries in the table.
186c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t count() const { return mTotalNumTableEntries; }
187c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
188c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    private:
189c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mElementCapacity;  // # entries in an element
190c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mEntryCapacity;    // # of values in each entry
191c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mTotalNumTableEntries;
192c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mNumValuesInCurrEntry;  // up to mEntryCapacity
193c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        TYPE             *mCurrTableEntriesElement;
194c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mutable List<TYPE *>     mTableEntryList;
195c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
196c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries);
197c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    };
198c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
199c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
200c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
20120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Writer *mOwner;
20220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mMeta;
203693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<MediaSource> mSource;
20420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    volatile bool mDone;
205a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mPaused;
206a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mResumed;
207eaae38445a340c4857c1c5569475879a728e63b7James Dong    volatile bool mStarted;
2081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAvc;
2091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAudio;
2101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsMPEG4;
211bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t mTrackId;
212c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    int64_t mTrackDurationUs;
21343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int64_t mMaxChunkDurationUs;
214e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
215e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    bool mIsRealTimeRecording;
216d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t mEstimatedTrackSizeBytes;
2171f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t mMdatSizeBytes;
2188f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mTimeScale;
21920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_t mThread;
22120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
222be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
22313aec890216948b0c364f8f92792129d0335f506James Dong    List<MediaBuffer *> mChunkSamples;
2241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
225c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    bool                mSamplesHaveSameSize;
226c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStszTableEntries;
227be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
228c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStcoTableEntries;
229c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<off64_t> *mCo64TableEntries;
230c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStscTableEntries;
231c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStssTableEntries;
232c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mSttsTableEntries;
233c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mCttsTableEntries;
234965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
235000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMinCttsOffsetTimeUs;
236000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMaxCttsOffsetTimeUs;
237965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Sequence parameter set or picture parameter set
2393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    struct AVCParamSet {
2403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        AVCParamSet(uint16_t length, const uint8_t *data)
2413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            : mLength(length), mData(data) {}
2423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
2433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t mLength;
2443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *mData;
2453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    };
2463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mSeqParamSets;
2473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mPicParamSets;
2483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileIdc;
2493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileCompatible;
2503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mLevelIdc;
2513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
25220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *mCodecSpecificData;
25320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t mCodecSpecificDataSize;
254548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    bool mGotAllCodecSpecificData;
25593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    bool mTrackingProgressStatus;
25620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
25725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool mReachedEOS;
2583c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    int64_t mStartTimestampUs;
25970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mStartTimeRealUs;
26070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mFirstSampleTimeRealUs;
26193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mPreviousTrackTimeUs;
26293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mTrackEveryTimeDurationUs;
26325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
264872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Update the audio track's drift information.
265872a481558350634a3fd5cb67939de288af00ecbJames Dong    void updateDriftTime(const sp<MetaData>& meta);
266872a481558350634a3fd5cb67939de288af00ecbJames Dong
267000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int32_t getStartTimeOffsetScaledTime() const;
268000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
26920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static void *ThreadWrapper(void *me);
27037187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t threadEntry();
27120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *parseParamSet(
2733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen);
2743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
275b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size);
276b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size);
277b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size);
278215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong
279215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    // Track authoring progress status
280faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    void trackProgressStatus(int64_t timeUs, status_t err = OK);
28193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    void initTrackingProgressStatus(MetaData *params);
28203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
28319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    void getCodecSpecificDataFromInputFormatIfPossible();
28419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
285c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Determine the track time scale
286c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If it is an audio track, try to use the sampling rate as
287c059860c73678a202bfa33062723e8f82fb779d9James Dong    // the time scale; however, if user chooses the overwrite
288c059860c73678a202bfa33062723e8f82fb779d9James Dong    // value, the user-supplied time scale will be used.
289c059860c73678a202bfa33062723e8f82fb779d9James Dong    void setTimeScale();
290c059860c73678a202bfa33062723e8f82fb779d9James Dong
291690f546b0ee548dbfe997df36418e5302ec2d786James Dong    // Simple validation on the codec specific data
292690f546b0ee548dbfe997df36418e5302ec2d786James Dong    status_t checkCodecSpecificData() const;
29313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t mRotation;
294690f546b0ee548dbfe997df36418e5302ec2d786James Dong
2951f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void updateTrackSizeEstimate();
2961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStscTableEntry(size_t chunkId, size_t sampleId);
2971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStssTableEntry(size_t sampleId);
29879761ab096f57c3027fad9556c2bc436672d614eJames Dong
29979761ab096f57c3027fad9556c2bc436672d614eJames Dong    // Duration is time scale based
30079761ab096f57c3027fad9556c2bc436672d614eJames Dong    void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
301965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
30245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
30345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    bool isTrackMalFormed() const;
30443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    void sendTrackSummary(bool hasMultipleTracks);
3051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
306b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Write the boxes
307b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStcoBox(bool use32BitOffset);
308b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStscBox();
309b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStszBox();
310b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStssBox();
311b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSttsBox();
312965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void writeCttsBox();
313b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeD263Box();
314b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writePaspBox();
315b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAvccBox();
316b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeUrlBox();
317b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDrefBox();
318b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDinfBox();
319b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDamrBox();
320b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMdhdBox(time_t now);
321b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSmhdBox();
322b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVmhdBox();
323b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeHdlrBox();
324b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeTkhdBox(time_t now);
325b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4aEsdsBox();
326b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4vEsdsBox();
327b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAudioFourCCBox();
328b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVideoFourCCBox();
329b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStblBox(bool use32BitOffset);
330b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
33120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track(const Track &);
33220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track &operator=(const Track &);
33320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
33420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename)
336674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    : mFd(-1),
337674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong      mInitCheck(NO_INIT),
338b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong      mUse4ByteNalLength(true),
3391acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
340a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong      mIsFileSizeLimitExplicitlyRequested(false),
341a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
342a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
343411ba422e3635d534928ffd81abf54f4f291c739James Dong      mWriterThreadStarted(false),
34420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOffset(0),
34513aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
3467837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
34707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mInterleaveDurationUs(1000000),
34807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLatitudex10000(0),
34907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLongitudex10000(0),
35086b7f47aa7482424cf8fd248f1315311919be3b0James Dong      mAreGeoTagsAvailable(false),
35186b7f47aa7482424cf8fd248f1315311919be3b0James Dong      mStartTimeOffsetMs(-1) {
352674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong
353af8e8aa1ada2948972555592570ec9ad90cbf372Nick Kralevich    mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
354674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mFd >= 0) {
355674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        mInitCheck = OK;
356674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    }
35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35930ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd)
360674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    : mFd(dup(fd)),
361674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong      mInitCheck(mFd < 0? NO_INIT: OK),
362b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong      mUse4ByteNalLength(true),
3631acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
364a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong      mIsFileSizeLimitExplicitlyRequested(false),
365a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
366a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
367411ba422e3635d534928ffd81abf54f4f291c739James Dong      mWriterThreadStarted(false),
36830ab66297501757d745b9ae10da61adcd891f497Andreas Huber      mOffset(0),
36913aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
3707837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
37107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mInterleaveDurationUs(1000000),
37207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLatitudex10000(0),
37307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLongitudex10000(0),
37486b7f47aa7482424cf8fd248f1315311919be3b0James Dong      mAreGeoTagsAvailable(false),
37586b7f47aa7482424cf8fd248f1315311919be3b0James Dong      mStartTimeOffsetMs(-1) {
37630ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
37730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
37820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
3798bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong    reset();
38020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3811f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    while (!mTracks.empty()) {
3821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        List<Track *>::iterator it = mTracks.begin();
38320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
3841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        (*it) = NULL;
3851f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mTracks.erase(it);
38620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
38720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
38820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
38920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
390dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump(
391dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) {
392dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
393dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
394dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
395dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "   MPEG4Writer %p\n", this);
396dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
397dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     mStarted: %s\n", mStarted? "true": "false");
398dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
399dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
400dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    for (List<Track *>::iterator it = mTracks.begin();
401dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong         it != mTracks.end(); ++it) {
402dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        (*it)->dump(fd, args);
403dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    }
404dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
405dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
406dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
407dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump(
408dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) const {
409dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
410dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
411dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
412dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     %s track\n", mIsAudio? "Audio": "Video");
413dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
414dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "       reached EOS: %s\n",
415dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong            mReachedEOS? "true": "false");
416dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
417c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    snprintf(buffer, SIZE, "       frames encoded : %d\n", mStszTableEntries->count());
41813210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
41913210f3346462a86ce9fe3af72a0c200dba84e27James Dong    snprintf(buffer, SIZE, "       duration encoded : %lld us\n", mTrackDurationUs);
42013210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
421dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
422dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
423dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
424dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
4252dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
426bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    Mutex::Autolock l(mLock);
427bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    if (mStarted) {
42829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Attempt to add source AFTER recording is started");
429bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        return UNKNOWN_ERROR;
430bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    }
431219f195159f93d627af2b243732e3f9020511a46James Dong    Track *track = new Track(this, source, 1 + mTracks.size());
43220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
4332dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
4342dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
43520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
43620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) {
438a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
439a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
44093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        status_t err = (*it)->start(params);
441a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
442a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (err != OK) {
443a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            for (List<Track *>::iterator it2 = mTracks.begin();
444a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                 it2 != it; ++it2) {
445a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                (*it2)->stop();
446a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            }
447a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
448a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            return err;
449a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
450a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
451a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
452a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
453a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
4542dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
4552dec2b5be2056c6d9428897dc672185872d30d17James Dong    // This implementation is highly experimental/heurisitic.
4562dec2b5be2056c6d9428897dc672185872d30d17James Dong    //
4572dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Statistical analysis shows that metadata usually accounts
4582dec2b5be2056c6d9428897dc672185872d30d17James Dong    // for a small portion of the total file size, usually < 0.6%.
4592dec2b5be2056c6d9428897dc672185872d30d17James Dong
46078a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2,
4612dec2b5be2056c6d9428897dc672185872d30d17James Dong    // where 1MB is the common file size limit for MMS application.
46278a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MAX _MOOV_BOX_SIZE value is based on about 3
4632dec2b5be2056c6d9428897dc672185872d30d17James Dong    // minute video recording with a bit rate about 3 Mbps, because
4642dec2b5be2056c6d9428897dc672185872d30d17James Dong    // statistics also show that most of the video captured are going
4652dec2b5be2056c6d9428897dc672185872d30d17James Dong    // to be less than 3 minutes.
4662dec2b5be2056c6d9428897dc672185872d30d17James Dong
4672dec2b5be2056c6d9428897dc672185872d30d17James Dong    // If the estimation is wrong, we will pay the price of wasting
4682dec2b5be2056c6d9428897dc672185872d30d17James Dong    // some reserved space. This should not happen so often statistically.
4692dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int32_t factor = mUse32BitOffset? 1: 2;
47078a1a286f736888ae7af8860b2c424af0d978848James Dong    static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024;  // 3 KB
4712dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
4722dec2b5be2056c6d9428897dc672185872d30d17James Dong    int64_t size = MIN_MOOV_BOX_SIZE;
4732dec2b5be2056c6d9428897dc672185872d30d17James Dong
47478a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file size limit is set
475a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
47678a1a286f736888ae7af8860b2c424af0d978848James Dong        size = mMaxFileSizeLimitBytes * 6 / 1000;
47778a1a286f736888ae7af8860b2c424af0d978848James Dong    }
47878a1a286f736888ae7af8860b2c424af0d978848James Dong
47978a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file duration limit is set
48078a1a286f736888ae7af8860b2c424af0d978848James Dong    if (mMaxFileDurationLimitUs != 0) {
48178a1a286f736888ae7af8860b2c424af0d978848James Dong        if (bitRate > 0) {
48278a1a286f736888ae7af8860b2c424af0d978848James Dong            int64_t size2 =
48378a1a286f736888ae7af8860b2c424af0d978848James Dong                ((mMaxFileDurationLimitUs * bitRate * 6) / 1000 / 8000000);
48478a1a286f736888ae7af8860b2c424af0d978848James Dong            if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
48578a1a286f736888ae7af8860b2c424af0d978848James Dong                // When both file size and duration limits are set,
48678a1a286f736888ae7af8860b2c424af0d978848James Dong                // we use the smaller limit of the two.
48778a1a286f736888ae7af8860b2c424af0d978848James Dong                if (size > size2) {
48878a1a286f736888ae7af8860b2c424af0d978848James Dong                    size = size2;
48978a1a286f736888ae7af8860b2c424af0d978848James Dong                }
49078a1a286f736888ae7af8860b2c424af0d978848James Dong            } else {
49178a1a286f736888ae7af8860b2c424af0d978848James Dong                // Only max file duration limit is set
49278a1a286f736888ae7af8860b2c424af0d978848James Dong                size = size2;
49378a1a286f736888ae7af8860b2c424af0d978848James Dong            }
4942dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
4952dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
49678a1a286f736888ae7af8860b2c424af0d978848James Dong
4972dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size < MIN_MOOV_BOX_SIZE) {
4982dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MIN_MOOV_BOX_SIZE;
4992dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
5002dec2b5be2056c6d9428897dc672185872d30d17James Dong
5012dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Any long duration recording will be probably end up with
5022dec2b5be2056c6d9428897dc672185872d30d17James Dong    // non-streamable mp4 file.
5032dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size > MAX_MOOV_BOX_SIZE) {
5042dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MAX_MOOV_BOX_SIZE;
5052dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
5062dec2b5be2056c6d9428897dc672185872d30d17James Dong
507df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated"
5082dec2b5be2056c6d9428897dc672185872d30d17James Dong         " moov size %lld bytes",
5092dec2b5be2056c6d9428897dc672185872d30d17James Dong         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
5102dec2b5be2056c6d9428897dc672185872d30d17James Dong    return factor * size;
5112dec2b5be2056c6d9428897dc672185872d30d17James Dong}
5122dec2b5be2056c6d9428897dc672185872d30d17James Dong
5132dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) {
514674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
51525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
51620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
51720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
518a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    /*
519a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * Check mMaxFileSizeLimitBytes at the beginning
520a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * since mMaxFileSizeLimitBytes may be implicitly
521a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * changed later for 32-bit file offset even if
522a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * user does not ask to set it explicitly.
523a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     */
524a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0) {
525a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong        mIsFileSizeLimitExplicitlyRequested = true;
526a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    }
527a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong
5282dec2b5be2056c6d9428897dc672185872d30d17James Dong    int32_t use64BitOffset;
5292dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (param &&
5302dec2b5be2056c6d9428897dc672185872d30d17James Dong        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
5312dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64BitOffset) {
5322dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
5332dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
5342dec2b5be2056c6d9428897dc672185872d30d17James Dong
5351f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    if (mUse32BitOffset) {
5361f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // Implicit 32 bit file size limit
5371f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes == 0) {
5381f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
5391f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
5401f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
5411f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // If file size is set to be larger than the 32 bit file
5421f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // size limit, treat it as an error.
5431f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
5445ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block            ALOGW("32-bit file size limit (%lld bytes) too big. "
545d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                 "It is changed to %lld bytes",
546d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                mMaxFileSizeLimitBytes, kMax32BitFileSize);
547d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
5481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
5491f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    }
5501f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
551b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    int32_t use2ByteNalLength;
552b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (param &&
553b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) &&
554b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        use2ByteNalLength) {
555b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mUse4ByteNalLength = false;
5562dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
5572dec2b5be2056c6d9428897dc672185872d30d17James Dong
558065d1aff96818df54456053f1574aec8a234d0deJames Dong    mStartTimestampUs = -1;
55993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
560a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mStarted) {
561a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused) {
562a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mPaused = false;
56393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return startTracks(param);
564a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
565a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
566a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
567a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
5688f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (!param ||
5698f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
5708f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mTimeScale = 1000;
5718f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
57243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
5733856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("movie time scale: %d", mTimeScale);
5748f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
57577e8ae9967a078770416619e99ddb5b010def312James Dong    /*
57677e8ae9967a078770416619e99ddb5b010def312James Dong     * When the requested file size limit is small, the priority
57777e8ae9967a078770416619e99ddb5b010def312James Dong     * is to meet the file size limit requirement, rather than
57877e8ae9967a078770416619e99ddb5b010def312James Dong     * to make the file streamable.
57977e8ae9967a078770416619e99ddb5b010def312James Dong     */
58077e8ae9967a078770416619e99ddb5b010def312James Dong    mStreamableFile =
58177e8ae9967a078770416619e99ddb5b010def312James Dong        (mMaxFileSizeLimitBytes != 0 &&
58277e8ae9967a078770416619e99ddb5b010def312James Dong         mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes);
58377e8ae9967a078770416619e99ddb5b010def312James Dong
58477e8ae9967a078770416619e99ddb5b010def312James Dong    mWriteMoovBoxToMemory = mStreamableFile;
5857837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = NULL;
5867837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
5877837c17063a4c50bc856ba59418516fdab731de7James Dong
588b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeFtypBox(param);
58920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5907837c17063a4c50bc856ba59418516fdab731de7James Dong    mFreeBoxOffset = mOffset;
59120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5927837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mEstimatedMoovBoxSize == 0) {
5932dec2b5be2056c6d9428897dc672185872d30d17James Dong        int32_t bitRate = -1;
5942dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (param) {
5952dec2b5be2056c6d9428897dc672185872d30d17James Dong            param->findInt32(kKeyBitRate, &bitRate);
5962dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
5972dec2b5be2056c6d9428897dc672185872d30d17James Dong        mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
5987837c17063a4c50bc856ba59418516fdab731de7James Dong    }
59943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(mEstimatedMoovBoxSize, 8);
60077e8ae9967a078770416619e99ddb5b010def312James Dong    if (mStreamableFile) {
60177e8ae9967a078770416619e99ddb5b010def312James Dong        // Reserve a 'free' box only for streamable file
60277e8ae9967a078770416619e99ddb5b010def312James Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
60377e8ae9967a078770416619e99ddb5b010def312James Dong        writeInt32(mEstimatedMoovBoxSize);
60477e8ae9967a078770416619e99ddb5b010def312James Dong        write("free", 4);
60577e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
60677e8ae9967a078770416619e99ddb5b010def312James Dong    } else {
60777e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mOffset;
60877e8ae9967a078770416619e99ddb5b010def312James Dong    }
6097837c17063a4c50bc856ba59418516fdab731de7James Dong
6107837c17063a4c50bc856ba59418516fdab731de7James Dong    mOffset = mMdatOffset;
611c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mMdatOffset, SEEK_SET);
6121acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
6131acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("????mdat", 8);
6141acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
6151acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("\x00\x00\x00\x01mdat????????", 16);
6161acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
6171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
6181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    status_t err = startWriterThread();
6191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (err != OK) {
6201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return err;
6211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
6221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
6231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    err = startTracks(param);
624a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (err != OK) {
625a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return err;
62620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
6271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
628a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = true;
62925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
63020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
63120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6321f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const {
6331f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    return mUse32BitOffset;
6341f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
6351f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
63637187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() {
637674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
63837187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
639a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
640a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
64137187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
642a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
643a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
64437187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->pause();
64537187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (status != OK) {
64637187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
64737187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
648a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
64937187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
650a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
651a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
6521c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() {
653b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Stopping writer thread");
654411ba422e3635d534928ffd81abf54f4f291c739James Dong    if (!mWriterThreadStarted) {
655411ba422e3635d534928ffd81abf54f4f291c739James Dong        return;
656411ba422e3635d534928ffd81abf54f4f291c739James Dong    }
6571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
6581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
6591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
6601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
6611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mDone = true;
6621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkReadyCondition.signal();
6631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
6641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
6651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void *dummy;
6661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_join(mThread, &dummy);
667411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = false;
668b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Writer thread stopped");
6691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
6701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
67113f6284305e4b27395a23db7882d670bdb1bcae1James Dong/*
67213f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix:
67313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a  b  u |
67413f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c  d  v |
67513f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x  y  w |
67613f6284305e4b27395a23db7882d670bdb1bcae1James Dong *
67713f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following
67813f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w},
67913f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while
68013f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format.
68113f6284305e4b27395a23db7882d670bdb1bcae1James Dong */
68213f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) {
6833856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeCompositionMatrix");
68413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t a = 0x00010000;
68513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t b = 0;
68613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t c = 0;
68713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t d = 0x00010000;
68813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    switch (degrees) {
68913f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 0:
69013f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
69113f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 90:
69213f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
69313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0x00010000;
69413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0xFFFF0000;
69513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
69613f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
69713f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 180:
69813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0xFFFF0000;
69913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0xFFFF0000;
70013f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
70113f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 270:
70213f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
70313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0xFFFF0000;
70413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0x00010000;
70513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
70613f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
70713f6284305e4b27395a23db7882d670bdb1bcae1James Dong        default:
70813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            CHECK(!"Should never reach this unknown rotation");
70913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
71013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
71113f6284305e4b27395a23db7882d670bdb1bcae1James Dong
71213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(a);           // a
71313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(b);           // b
71413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // u
71513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(c);           // c
71613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(d);           // d
71713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // v
71813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // x
71913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // y
72013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0x40000000);  // w
72113f6284305e4b27395a23db7882d670bdb1bcae1James Dong}
72213f6284305e4b27395a23db7882d670bdb1bcae1James Dong
723411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() {
724411ba422e3635d534928ffd81abf54f4f291c739James Dong    close(mFd);
725411ba422e3635d534928ffd81abf54f4f291c739James Dong    mFd = -1;
726411ba422e3635d534928ffd81abf54f4f291c739James Dong    mInitCheck = NO_INIT;
727411ba422e3635d534928ffd81abf54f4f291c739James Dong    mStarted = false;
728411ba422e3635d534928ffd81abf54f4f291c739James Dong}
72913f6284305e4b27395a23db7882d670bdb1bcae1James Dong
7308bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dongstatus_t MPEG4Writer::reset() {
731674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
73237187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
733411ba422e3635d534928ffd81abf54f4f291c739James Dong    } else {
734411ba422e3635d534928ffd81abf54f4f291c739James Dong        if (!mWriterThreadStarted ||
735411ba422e3635d534928ffd81abf54f4f291c739James Dong            !mStarted) {
736411ba422e3635d534928ffd81abf54f4f291c739James Dong            if (mWriterThreadStarted) {
737411ba422e3635d534928ffd81abf54f4f291c739James Dong                stopWriterThread();
738411ba422e3635d534928ffd81abf54f4f291c739James Dong            }
739411ba422e3635d534928ffd81abf54f4f291c739James Dong            release();
740411ba422e3635d534928ffd81abf54f4f291c739James Dong            return OK;
741411ba422e3635d534928ffd81abf54f4f291c739James Dong        }
74220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
74320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
74437187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
7458f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t maxDurationUs = 0;
74665b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    int64_t minDurationUs = 0x7fffffffffffffffLL;
74720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
74820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
74937187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->stop();
75037187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK) {
75137187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
75237187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
75320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7548f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int64_t durationUs = (*it)->getDurationUs();
7558f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (durationUs > maxDurationUs) {
7568f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            maxDurationUs = durationUs;
75720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
75865b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        if (durationUs < minDurationUs) {
75965b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs = durationUs;
76065b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        }
76165b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    }
76265b3d76025c71d755b0fb3b6ead90255f25417edJames Dong
76365b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    if (mTracks.size() > 1) {
764b8a805261bf0282e992d3608035e47d05a898710Steve Block        ALOGD("Duration from tracks range is [%lld, %lld] us",
76565b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs, maxDurationUs);
76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
76720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    stopWriterThread();
7697837c17063a4c50bc856ba59418516fdab731de7James Dong
77037187916a486504acaf83bea30147eb5fbf46ae5James Dong    // Do not write out movie header on error.
77137187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err != OK) {
772411ba422e3635d534928ffd81abf54f4f291c739James Dong        release();
77337187916a486504acaf83bea30147eb5fbf46ae5James Dong        return err;
77437187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
77537187916a486504acaf83bea30147eb5fbf46ae5James Dong
77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
7771acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
778c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset, SEEK_SET);
7791acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset));
780c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 4);
7811acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
782c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset + 8, SEEK_SET);
7831acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int64_t size = mOffset - mMdatOffset;
7841acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        size = hton64(size);
785c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 8);
7861acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
787c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mOffset, SEEK_SET);
78820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
789c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    const off64_t moovOffset = mOffset;
79077e8ae9967a078770416619e99ddb5b010def312James Dong    mWriteMoovBoxToMemory = mStreamableFile;
7917837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
7927837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
7937837c17063a4c50bc856ba59418516fdab731de7James Dong    CHECK(mMoovBoxBuffer != NULL);
794b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMoovBox(maxDurationUs);
79520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7967837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = false;
7977837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mStreamableFile) {
79843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize);
7997837c17063a4c50bc856ba59418516fdab731de7James Dong
8007837c17063a4c50bc856ba59418516fdab731de7James Dong        // Moov box
801c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
8027837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset = mFreeBoxOffset;
803674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset);
8047837c17063a4c50bc856ba59418516fdab731de7James Dong
8057837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free box
806c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
8077837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
8087837c17063a4c50bc856ba59418516fdab731de7James Dong        write("free", 4);
8097837c17063a4c50bc856ba59418516fdab731de7James Dong
8107837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free temp memory
8117837c17063a4c50bc856ba59418516fdab731de7James Dong        free(mMoovBoxBuffer);
8127837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBuffer = NULL;
8137837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBufferOffset = 0;
8142dec2b5be2056c6d9428897dc672185872d30d17James Dong    } else {
815df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("The mp4 file will not be streamable.");
8167837c17063a4c50bc856ba59418516fdab731de7James Dong    }
8177837c17063a4c50bc856ba59418516fdab731de7James Dong
8180c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
81920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
820411ba422e3635d534928ffd81abf54f4f291c739James Dong    release();
82137187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
82220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
82320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
824b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) {
825b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    time_t now = time(NULL);
826b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("mvhd");
827b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // version=0, flags=0
828b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // creation time
829b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // modification time
830b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTimeScale);    // mvhd timescale
831b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6;
832b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(duration);
833b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0x10000);       // rate: 1.0
834b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0x100);         // volume
835b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0);             // reserved
836b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
837b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
838b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeCompositionMatrix(0); // matrix
839b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
840b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
841b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
842b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
843b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
844b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
845b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTracks.size() + 1);  // nextTrackID
846b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // mvhd
847b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
848b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
849b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) {
850b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("moov");
851b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMvhdBox(durationUs);
85207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (mAreGeoTagsAvailable) {
85307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        writeUdtaBox();
85407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
855b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t id = 1;
856b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    for (List<Track *>::iterator it = mTracks.begin();
857b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        it != mTracks.end(); ++it, ++id) {
858b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (*it)->writeTrackHeader(mUse32BitOffset);
859b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
860b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // moov
861b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
862b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
8632cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) {
864b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("ftyp");
865b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
866b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t fileType;
867b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (param && param->findInt32(kKeyFileType, &fileType) &&
868b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fileType != OUTPUT_FORMAT_MPEG_4) {
869b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("3gp4");
870b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
871b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("isom");
872b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
873b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
874b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);
875b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeFourcc("isom");
876b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeFourcc("3gp4");
877b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();
878b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
879b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
88007ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() {
88107ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5)
88207ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5"
88307ec01904613a0bac32caaa8444b4690998faed7James Dong#endif
88407ec01904613a0bac32caaa8444b4690998faed7James Dong
88507ec01904613a0bac32caaa8444b4690998faed7James Dong    // Test mode is enabled only if rw.media.record.test system
88607ec01904613a0bac32caaa8444b4690998faed7James Dong    // property is enabled.
88707ec01904613a0bac32caaa8444b4690998faed7James Dong    char value[PROPERTY_VALUE_MAX];
88807ec01904613a0bac32caaa8444b4690998faed7James Dong    if (property_get("rw.media.record.test", value, NULL) &&
88907ec01904613a0bac32caaa8444b4690998faed7James Dong        (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) {
89007ec01904613a0bac32caaa8444b4690998faed7James Dong        return true;
89107ec01904613a0bac32caaa8444b4690998faed7James Dong    }
89207ec01904613a0bac32caaa8444b4690998faed7James Dong    return false;
89307ec01904613a0bac32caaa8444b4690998faed7James Dong}
89407ec01904613a0bac32caaa8444b4690998faed7James Dong
89570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() {
89607ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send session summary only if test mode is enabled
89707ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
89807ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
89907ec01904613a0bac32caaa8444b4690998faed7James Dong    }
90007ec01904613a0bac32caaa8444b4690998faed7James Dong
90170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
90270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong         it != mChunkInfos.end(); ++it) {
90370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int trackNum = it->mTrack->getTrackId() << 28;
90470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
90570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS,
90670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs);
90770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    }
90870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong}
90970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
91013aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
91113aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
91213aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
91313aec890216948b0c364f8f92792129d0335f506James Dong}
91413aec890216948b0c364f8f92792129d0335f506James Dong
91513aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() {
91613aec890216948b0c364f8f92792129d0335f506James Dong    mLock.lock();
91713aec890216948b0c364f8f92792129d0335f506James Dong}
91813aec890216948b0c364f8f92792129d0335f506James Dong
91913aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() {
92013aec890216948b0c364f8f92792129d0335f506James Dong    mLock.unlock();
92113aec890216948b0c364f8f92792129d0335f506James Dong}
92220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
923c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
924c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
92520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
926c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    ::write(mFd,
927c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          (const uint8_t *)buffer->data() + buffer->range_offset(),
928c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          buffer->range_length());
92920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
93020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
93120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
93220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
93320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
93420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
93503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
93603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
93703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
93803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
93903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
94003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
94103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
94203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
94303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
94403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
94503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
94603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
94703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
94803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
949c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
950c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
95130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
95230ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
95303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
954b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mUse4ByteNalLength) {
955b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 24;
956c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
957b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 16) & 0xff;
958c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
959b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 8) & 0xff;
960c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
961b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
962c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
963c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong
964c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd,
965c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              (const uint8_t *)buffer->data() + buffer->range_offset(),
966c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              length);
967b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
968b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 4;
969b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
97043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_LT(length, 65536);
97130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
972b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 8;
973c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
974b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
975c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
976c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length);
977b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 2;
978b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
97930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
98030ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
98130ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
98230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
9837837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write(
984674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        const void *ptr, size_t size, size_t nmemb) {
9857837c17063a4c50bc856ba59418516fdab731de7James Dong
9867837c17063a4c50bc856ba59418516fdab731de7James Dong    const size_t bytes = size * nmemb;
9877837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
988674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        // This happens only when we write the moov box at the end of
989674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        // recording, not for each output video/audio frame we receive.
990c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
9911acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        if (moovBoxSize > mEstimatedMoovBoxSize) {
992c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            for (List<off64_t>::iterator it = mBoxes.begin();
9937837c17063a4c50bc856ba59418516fdab731de7James Dong                 it != mBoxes.end(); ++it) {
9947837c17063a4c50bc856ba59418516fdab731de7James Dong                (*it) += mOffset;
9957837c17063a4c50bc856ba59418516fdab731de7James Dong            }
996674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            lseek64(mFd, mOffset, SEEK_SET);
997674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset);
998674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            ::write(mFd, ptr, size * nmemb);
9997837c17063a4c50bc856ba59418516fdab731de7James Dong            mOffset += (bytes + mMoovBoxBufferOffset);
10007837c17063a4c50bc856ba59418516fdab731de7James Dong            free(mMoovBoxBuffer);
10017837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBuffer = NULL;
10027837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset = 0;
10037837c17063a4c50bc856ba59418516fdab731de7James Dong            mWriteMoovBoxToMemory = false;
10047837c17063a4c50bc856ba59418516fdab731de7James Dong            mStreamableFile = false;
10057837c17063a4c50bc856ba59418516fdab731de7James Dong        } else {
10067837c17063a4c50bc856ba59418516fdab731de7James Dong            memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
10077837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset += bytes;
10087837c17063a4c50bc856ba59418516fdab731de7James Dong        }
10097837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1010674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        ::write(mFd, ptr, size * nmemb);
10117837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset += bytes;
10127837c17063a4c50bc856ba59418516fdab731de7James Dong    }
10137837c17063a4c50bc856ba59418516fdab731de7James Dong    return bytes;
10147837c17063a4c50bc856ba59418516fdab731de7James Dong}
10157837c17063a4c50bc856ba59418516fdab731de7James Dong
101620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
10170c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(fourcc), 4);
101820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10197837c17063a4c50bc856ba59418516fdab731de7James Dong    mBoxes.push_back(mWriteMoovBoxToMemory?
10207837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset: mOffset);
102120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
102220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
102320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
102420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
102520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
102620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
10270c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
102820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1029c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = *--mBoxes.end();
103020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
103120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10327837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
10337837c17063a4c50bc856ba59418516fdab731de7James Dong       int32_t x = htonl(mMoovBoxBufferOffset - offset);
10347837c17063a4c50bc856ba59418516fdab731de7James Dong       memcpy(mMoovBoxBuffer + offset, &x, 4);
10357837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1036c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, offset, SEEK_SET);
10377837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mOffset - offset);
10387837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset -= 4;
1039c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
10407837c17063a4c50bc856ba59418516fdab731de7James Dong    }
104120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
104220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
104320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
1044674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 1);
104520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
104620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
104720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
104820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
1049674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 2);
105020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
105120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
105220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
105320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
1054674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 4);
105520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
105620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
105720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
105820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
1059674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 8);
106020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
106120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
106220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
106320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
1064674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, n + 1);
106520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
106620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
106720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
10680c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(s), 4);
1069674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, 4);
107020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
107120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
107207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
107307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format
107407b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) {
107507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
107607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
107707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
107807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
107907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[9];
108007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
108107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
108207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%c%.2d.", sign, wholePart);
108307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
108407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%+.2d.", wholePart);
108507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
108607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
108707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
108807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
108907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
109007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
109107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
109207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[4], 5, "%.4d", fractionalPart);
109307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
109407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
109507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 8);
109607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
109707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
109807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format
109907b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) {
110007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
110107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
110207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
110307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
110407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[10];
110507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
110607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
110707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%c%.3d.", sign, wholePart);
110807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
110907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%+.3d.", wholePart);
111007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
111107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
111207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
111307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
111407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
111507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
111607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
111707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[5], 5, "%.4d", fractionalPart);
111807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
111907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
112007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 9);
112107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
112207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
112307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
112407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
112507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and
112607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000.
112707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and
112807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180]
112907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
113007b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) {
113107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Is latitude or longitude out of range?
113207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (latitudex10000 < -900000 || latitudex10000 > 900000 ||
113307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        longitudex10000 < -1800000 || longitudex10000 > 1800000) {
113407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        return BAD_VALUE;
113507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
113607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
113707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLatitudex10000 = latitudex10000;
113807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLongitudex10000 = longitudex10000;
113907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mAreGeoTagsAvailable = true;
114007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    return OK;
114107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
114207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
114320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
1144674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(data, 1, size);
114520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
114620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
114778a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const {
114878a1a286f736888ae7af8860b2c424af0d978848James Dong    return mStreamableFile;
114978a1a286f736888ae7af8860b2c424af0d978848James Dong}
115078a1a286f736888ae7af8860b2c424af0d978848James Dong
1151d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() {
1152d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1153d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeLimitBytes == 0) {
1154d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1155d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1156d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1157956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
1158d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1159d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1160d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
1161d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
11621f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
116377e8ae9967a078770416619e99ddb5b010def312James Dong    if (!mStreamableFile) {
116477e8ae9967a078770416619e99ddb5b010def312James Dong        // Add 1024 bytes as error tolerance
116577e8ae9967a078770416619e99ddb5b010def312James Dong        return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes;
116677e8ae9967a078770416619e99ddb5b010def312James Dong    }
1167acd234bba9f048971d66890009eeff9a8db94be3James Dong    // Be conservative in the estimate: do not exceed 95% of
1168acd234bba9f048971d66890009eeff9a8db94be3James Dong    // the target file limit. For small target file size limit, though,
1169acd234bba9f048971d66890009eeff9a8db94be3James Dong    // this will not help.
1170acd234bba9f048971d66890009eeff9a8db94be3James Dong    return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100);
1171d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1172d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1173d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() {
1174d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1175d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationLimitUs == 0) {
1176d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1177d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1178d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1179d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1180d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1181d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
1182d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            return true;
1183d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1184d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1185d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return false;
1186d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1187d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
118825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
118925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
119025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
119125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
119225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
119325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
119425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
119525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
119625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
119725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
119825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
119925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
120025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
1201f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
1202df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("setStartTimestampUs: %lld", timeUs);
120343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(timeUs, 0ll);
12043c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
1205065d1aff96818df54456053f1574aec8a234d0deJames Dong    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
1206f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimestampUs = timeUs;
1207df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("Earliest track starting time: %lld", mStartTimestampUs);
12083c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    }
12093c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
12103c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
1211f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() {
12123c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
12133c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    return mStartTimestampUs;
12143c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
12153c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
121658ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() {
121758ae9c530247668f8af36e30d228c716c226b3d4James Dong    Mutex::Autolock autolock(mLock);
121858ae9c530247668f8af36e30d228c716c226b3d4James Dong    return mTracks.size();
121958ae9c530247668f8af36e30d228c716c226b3d4James Dong}
122058ae9c530247668f8af36e30d228c716c226b3d4James Dong
122120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
122220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
122320111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
1224bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId)
122520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
122625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
122720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
122820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
1229a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
1230a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mResumed(false),
1231eaae38445a340c4857c1c5569475879a728e63b7James Dong      mStarted(false),
1232bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong      mTrackId(trackId),
1233c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong      mTrackDurationUs(0),
1234956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mEstimatedTrackSizeBytes(0),
1235be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong      mSamplesHaveSameSize(true),
1236c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStszTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1237c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStcoTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1238c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mCo64TableEntries(new ListTableEntries<off64_t>(1000, 1)),
1239c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStscTableEntries(new ListTableEntries<uint32_t>(1000, 3)),
1240c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStssTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1241c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mSttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)),
1242c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mCttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)),
124320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
124425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
1245548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
124613f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mReachedEOS(false),
124713f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mRotation(0) {
124819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    getCodecSpecificDataFromInputFormatIfPossible();
12498f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
12501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    const char *mime;
12511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMeta->findCString(kKeyMIMEType, &mime);
12521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
12531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAudio = !strncasecmp(mime, "audio/", 6);
12541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
12551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
12561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1257c059860c73678a202bfa33062723e8f82fb779d9James Dong    setTimeScale();
1258c059860c73678a202bfa33062723e8f82fb779d9James Dong}
1259c059860c73678a202bfa33062723e8f82fb779d9James Dong
12601f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() {
12611f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1262c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t stcoBoxCount = (mOwner->use32BitFileOffset()
1263c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                            ? mStcoTableEntries->count()
1264c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                            : mCo64TableEntries->count());
1265c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    int64_t stcoBoxSizeBytes = stcoBoxCount * 4;
1266c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4);
12671f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
126878a1a286f736888ae7af8860b2c424af0d978848James Dong    mEstimatedTrackSizeBytes = mMdatSizeBytes;  // media data size
126978a1a286f736888ae7af8860b2c424af0d978848James Dong    if (!mOwner->isFileStreamable()) {
127078a1a286f736888ae7af8860b2c424af0d978848James Dong        // Reserved free space is not large enough to hold
127178a1a286f736888ae7af8860b2c424af0d978848James Dong        // all meta data and thus wasted.
1272c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 +  // stsc box size
1273c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mStssTableEntries->count() * 4 +   // stss box size
1274c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mSttsTableEntries->count() * 8 +   // stts box size
1275c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mCttsTableEntries->count() * 8 +   // ctts box size
127678a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stcoBoxSizeBytes +           // stco box size
127778a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stszBoxSizeBytes;            // stsz box size
127878a1a286f736888ae7af8860b2c424af0d978848James Dong    }
12791f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
12801f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
12811f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry(
12821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        size_t chunkId, size_t sampleId) {
12831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1284c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(chunkId));
1285c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(sampleId));
1286c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(1));
12871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
12881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
12891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) {
1290c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->add(htonl(sampleId));
12911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
12921f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
12931f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry(
129479761ab096f57c3027fad9556c2bc436672d614eJames Dong        size_t sampleCount, int32_t duration) {
12951f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
12965a217fba010e801c255503602bda4b86ac5a6ac9James Dong    if (duration == 0) {
12975ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("0-duration samples found: %d", sampleCount);
12985a217fba010e801c255503602bda4b86ac5a6ac9James Dong    }
1299c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(sampleCount));
1300c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(duration));
13011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
13021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1303965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry(
1304965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        size_t sampleCount, int32_t duration) {
1305965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1306965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if (mIsAudio) {
1307965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
1308965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
1309c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(sampleCount));
1310c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(duration));
1311965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
1312965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1313c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) {
1314c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mOwner->use32BitFileOffset()) {
1315c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t value = offset;
1316c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->add(htonl(value));
1317c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
1318c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->add(hton64(offset));
1319c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    }
13201f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
13211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1322c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() {
13233856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setTimeScale");
1324c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Default time scale
1325c059860c73678a202bfa33062723e8f82fb779d9James Dong    mTimeScale = 90000;
1326c059860c73678a202bfa33062723e8f82fb779d9James Dong
1327c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mIsAudio) {
1328c059860c73678a202bfa33062723e8f82fb779d9James Dong        // Use the sampling rate as the default time scale for audio track.
1329c059860c73678a202bfa33062723e8f82fb779d9James Dong        int32_t sampleRate;
1330c059860c73678a202bfa33062723e8f82fb779d9James Dong        bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
1331c059860c73678a202bfa33062723e8f82fb779d9James Dong        CHECK(success);
1332c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = sampleRate;
1333c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1334c059860c73678a202bfa33062723e8f82fb779d9James Dong
1335c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If someone would like to overwrite the timescale, use user-supplied value.
1336c059860c73678a202bfa33062723e8f82fb779d9James Dong    int32_t timeScale;
1337c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
1338c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = timeScale;
1339c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1340c059860c73678a202bfa33062723e8f82fb779d9James Dong
134143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
134219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber}
134319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
134419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
134519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    const char *mime;
134619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
134719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
134819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
134919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
135019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
135119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
135219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyAVCC, &type, &data, &size)) {
135319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificData = malloc(size);
135419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificDataSize = size;
135519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            memcpy(mCodecSpecificData, data, size);
135619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mGotAllCodecSpecificData = true;
135719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
135819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
135919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
136019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
136119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
136219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
136319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
136419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            ESDS esds(data, size);
136519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            if (esds.getCodecSpecificInfo(&data, &size) == OK) {
136619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificData = malloc(size);
136719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificDataSize = size;
136819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                memcpy(mCodecSpecificData, data, size);
136919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mGotAllCodecSpecificData = true;
137019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            }
137119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
137219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
137320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
137420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
137520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
137620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
137720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1378c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStszTableEntries;
1379c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStcoTableEntries;
1380c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCo64TableEntries;
1381c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStscTableEntries;
1382c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mSttsTableEntries;
1383c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStssTableEntries;
1384c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCttsTableEntries;
1385c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
1386c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries = NULL;
1387c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStcoTableEntries = NULL;
1388c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCo64TableEntries = NULL;
1389c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries = NULL;
1390c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries = NULL;
1391c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries = NULL;
1392c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries = NULL;
1393c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
139420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
139520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
139620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
139720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
139820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
139920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
140093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
14013856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("initTrackingProgressStatus");
140293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mPreviousTrackTimeUs = -1;
140393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackingProgressStatus = false;
140493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
140593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    {
140693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeUs;
140793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
14083856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("Receive request to track progress status for every %lld us", timeUs);
140993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackEveryTimeDurationUs = timeUs;
141093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackingProgressStatus = true;
141193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
141293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
141393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
141493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
14151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static
14161c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) {
14173856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("ThreadWrapper: %p", me);
14181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
14191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    writer->threadFunc();
14201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return NULL;
14211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
14221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
14231c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) {
14243856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk: %p", chunk.mTrack);
14251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Mutex::Autolock autolock(mLock);
14261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK_EQ(mDone, false);
14271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
14281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
14291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
14301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
14311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (chunk.mTrack == it->mTrack) {  // Found owner
14321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            it->mChunks.push_back(chunk);
14331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.signal();
14341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            return;
14351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
14361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
14371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
143843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK(!"Received a chunk for a unknown track");
14391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
14401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1441fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) {
14423856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeChunkToFile: %lld from %s track",
14435410afcbb0af5d29d9f710a1c2978c500f9792dcPannag Sanketi        chunk->mTimeStampUs, chunk->mTrack->isAudio()? "audio": "video");
1444fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1445fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    int32_t isFirstSample = true;
1446fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    while (!chunk->mSamples.empty()) {
1447fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        List<MediaBuffer *>::iterator it = chunk->mSamples.begin();
1448fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1449fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        off64_t offset = chunk->mTrack->isAvc()
1450fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong                                ? addLengthPrefixedSample_l(*it)
1451fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong                                : addSample_l(*it);
1452fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1453fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (isFirstSample) {
1454fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            chunk->mTrack->addChunkOffset(offset);
1455fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            isFirstSample = false;
14561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
14571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
14581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it)->release();
14591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it) = NULL;
1460fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        chunk->mSamples.erase(it);
14611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1462fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    chunk->mSamples.clear();
14631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
14641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1465fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() {
14663856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeAllChunks");
14671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    size_t outstandingChunks = 0;
146870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    Chunk chunk;
146970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    while (findChunkToWrite(&chunk)) {
1470e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong        writeChunkToFile(&chunk);
147170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        ++outstandingChunks;
14721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
147370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
147470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    sendSessionSummary();
147570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
14761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mChunkInfos.clear();
1477b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("%d chunks are written in the last batch", outstandingChunks);
14781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
14791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1480fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) {
14813856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("findChunkToWrite");
14821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
14831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
14841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Track *track = NULL;
14851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
14861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
14871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (!it->mChunks.empty()) {
14881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            List<Chunk>::iterator chunkIt = it->mChunks.begin();
14891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (chunkIt->mTimeStampUs < minTimestampUs) {
14901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                minTimestampUs = chunkIt->mTimeStampUs;
14911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                track = it->mTrack;
14921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            }
14931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
14941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
14951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
14961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (track == NULL) {
14973856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Nothing to be written after all");
1498fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        return false;
14991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
15001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
15011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mIsFirstChunk) {
15021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsFirstChunk = false;
15031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1504fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
15051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
15061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
15071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it->mTrack == track) {
1508fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            *chunk = *(it->mChunks.begin());
1509fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            it->mChunks.erase(it->mChunks.begin());
1510fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            CHECK_EQ(chunk->mTrack, track);
151170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
151270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t interChunkTimeUs =
151370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                chunk->mTimeStampUs - it->mPrevChunkTimestampUs;
151470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            if (interChunkTimeUs > it->mPrevChunkTimestampUs) {
151570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs = interChunkTimeUs;
151670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            }
151770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
1518fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            return true;
15191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
15201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1521fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1522fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    return false;
15231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
15241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
15251c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() {
15263856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("threadFunc");
15271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1528a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0);
1529fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1530fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    Mutex::Autolock autoLock(mLock);
15311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mDone) {
1532fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        Chunk chunk;
1533fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        bool chunkFound = false;
1534fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1535fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) {
15361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.wait(mLock);
15371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
15381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1539fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        // Actual write without holding the lock in order to
1540fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        // reduce the blocking time for media track threads.
1541fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (chunkFound) {
1542fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            mLock.unlock();
1543fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            writeChunkToFile(&chunk);
1544fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            mLock.lock();
1545fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        }
15461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1547fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1548fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    writeAllChunks();
15491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
15501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
15511c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() {
15523856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("startWriterThread");
15531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
15541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mDone = false;
15551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsFirstChunk = true;
1556e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    mDriftTimeUs = 0;
15571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<Track *>::iterator it = mTracks.begin();
15581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mTracks.end(); ++it) {
15591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        ChunkInfo info;
15601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        info.mTrack = *it;
156170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mPrevChunkTimestampUs = 0;
156270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mMaxInterChunkDurUs = 0;
15631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.push_back(info);
15641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
15651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
15661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_t attr;
15671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_init(&attr);
15681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
15691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_create(&mThread, &attr, ThreadWrapper, this);
15701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_destroy(&attr);
1571411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = true;
15721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
15731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
15741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
15751f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
157693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) {
1577a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (!mDone && mPaused) {
1578a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mPaused = false;
1579a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mResumed = true;
1580a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
1581a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
158225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
158393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t startTimeUs;
158419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
158519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        startTimeUs = 0;
158619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
158770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    mStartTimeRealUs = startTimeUs;
158819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
158913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t rotationDegrees;
159013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) {
159113f6284305e4b27395a23db7882d670bdb1bcae1James Dong        mRotation = rotationDegrees;
159213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
159313f6284305e4b27395a23db7882d670bdb1bcae1James Dong
15945b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong    mIsRealTimeRecording = true;
1595e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    {
1596e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        int32_t isNotRealTime;
1597e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        if (params && params->findInt32(kKeyNotRealTime, &isNotRealTime)) {
1598e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            mIsRealTimeRecording = (isNotRealTime == 0);
1599e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
1600e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    }
1601e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
160293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    initTrackingProgressStatus(params);
160393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
1604f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    sp<MetaData> meta = new MetaData;
1605a472613aec322e25891abf5c77bf3f7e3c244920James Dong    if (mIsRealTimeRecording && mOwner->numTracks() > 1) {
1606a472613aec322e25891abf5c77bf3f7e3c244920James Dong        /*
1607a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * This extra delay of accepting incoming audio/video signals
1608a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * helps to align a/v start time at the beginning of a recording
1609a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * session, and it also helps eliminate the "recording" sound for
1610a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * camcorder applications.
1611a472613aec322e25891abf5c77bf3f7e3c244920James Dong         *
161286b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * If client does not set the start time offset, we fall back to
161386b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * use the default initial delay value.
1614a472613aec322e25891abf5c77bf3f7e3c244920James Dong         */
161586b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
161686b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
161786b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
161886b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
161986b7f47aa7482424cf8fd248f1315311919be3b0James Dong        startTimeUs += startTimeOffsetUs;
1620df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("Start time offset: %lld us", startTimeOffsetUs);
1621a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
1622a472613aec322e25891abf5c77bf3f7e3c244920James Dong
1623f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    meta->setInt64(kKeyTime, startTimeUs);
1624a472613aec322e25891abf5c77bf3f7e3c244920James Dong
1625f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    status_t err = mSource->start(meta.get());
162625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
162725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
162825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
162925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
163020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
163120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
163220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
163320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
163420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
163520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
1636eaae38445a340c4857c1c5569475879a728e63b7James Dong    mStarted = true;
1637c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs = 0;
163825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
1639956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mEstimatedTrackSizeBytes = 0;
16401f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mMdatSizeBytes = 0;
164143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mMaxChunkDurationUs = 0;
164220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
164325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
164420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
164525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
164625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
164720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
164820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
164937187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() {
1650a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
165137187916a486504acaf83bea30147eb5fbf46ae5James Dong    return OK;
1652a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
1653a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
165437187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() {
1655b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Stopping %s track", mIsAudio? "Audio": "Video");
1656eaae38445a340c4857c1c5569475879a728e63b7James Dong    if (!mStarted) {
165729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Stop() called but track is not started");
1658eaae38445a340c4857c1c5569475879a728e63b7James Dong        return ERROR_END_OF_STREAM;
1659eaae38445a340c4857c1c5569475879a728e63b7James Dong    }
1660eaae38445a340c4857c1c5569475879a728e63b7James Dong
166120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
166237187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
166320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
166420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = true;
166520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
166620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
166720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
166820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
166937187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = (status_t) dummy;
167037187916a486504acaf83bea30147eb5fbf46ae5James Dong
1671b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Stopping %s track source", mIsAudio? "Audio": "Video");
167237187916a486504acaf83bea30147eb5fbf46ae5James Dong    {
167337187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = mSource->stop();
167437187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK && status != ERROR_END_OF_STREAM) {
167537187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
167637187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
167737187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
167837187916a486504acaf83bea30147eb5fbf46ae5James Dong
1679b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("%s track stopped", mIsAudio? "Audio": "Video");
168037187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
168120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
168220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
168325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
168425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
168525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
168625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
168720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
168820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
168920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
169020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
169137187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = track->threadEntry();
169237187916a486504acaf83bea30147eb5fbf46ae5James Dong    return (void *) err;
169320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
169420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
16953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) {
16963856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("getNalUnitType: %d", byte);
16973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // nal_unit_type: 5-bit unsigned integer
16993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *type = (byte & 0x1F);
17003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
17013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t *findNextStartCode(
17033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length) {
17043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17053856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("findNextStartCode: %p %d", data, length);
17063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = length;
17083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4  &&
17093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) {
17103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        --bytesLeft;
17113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
17123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (bytesLeft <= 4) {
17133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft = 0; // Last parameter set
17143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
17153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return &data[length - bytesLeft];
17163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
17173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet(
17193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
17203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17213856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseParamSet");
17223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    CHECK(type == kNalUnitTypeSeqParamSet ||
17233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong          type == kNalUnitTypePicParamSet);
17243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = findNextStartCode(data, length);
17263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *paramSetLen = nextStartCode - data;
17273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (*paramSetLen == 0) {
172829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Param set is malformed, since its length is 0");
17293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return NULL;
17303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
17313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    AVCParamSet paramSet(*paramSetLen, data);
17333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (type == kNalUnitTypeSeqParamSet) {
17343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (*paramSetLen < 4) {
173529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Seq parameter set malformed");
17363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return NULL;
17373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
17383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mSeqParamSets.empty()) {
17393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc = data[1];
17403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileCompatible = data[2];
17413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mLevelIdc = data[3];
17423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
17433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (mProfileIdc != data[1] ||
17443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mProfileCompatible != data[2] ||
17453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mLevelIdc != data[3]) {
174629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Inconsistent profile/level found in seq parameter sets");
17473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return NULL;
17483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
17493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
17503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mSeqParamSets.push_back(paramSet);
17513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    } else {
17523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mPicParamSets.push_back(paramSet);
17533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
17543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return nextStartCode;
17553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
17563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData(
17583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
17593856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("copyAVCCodecSpecificData");
17603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 2 bytes for each of the parameter set length field
17623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // plus the 7 bytes for the header
17633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4 + 7) {
176429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Codec specific data length too short: %d", size);
17653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return ERROR_MALFORMED;
17663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
17673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = size;
17693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificData = malloc(size);
17703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    memcpy(mCodecSpecificData, data, size);
17713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
17723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
17733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData(
17753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
17763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17773856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseAVCCodecSpecificData");
17783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data starts with a start code.
17793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // SPS and PPS are separated with start codes.
17803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Also, SPS must come before PPS
17813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t type = kNalUnitTypeSeqParamSet;
17823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotSps = false;
17833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotPps = false;
17843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *tmp = data;
17853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = data;
17863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = size;
17873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t paramSetLen = 0;
17883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = 0;
17893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
17903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        getNalUnitType(*(tmp + 4), &type);
17913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (type == kNalUnitTypeSeqParamSet) {
17923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (gotPps) {
179329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
17943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
17953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
17963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
17973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotSps = true;
17983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
17993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
18003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else if (type == kNalUnitTypePicParamSet) {
18013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
180229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
18033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
18043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
18053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotPps) {
18063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotPps = true;
18073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
18083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
18093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
181029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Only SPS and PPS Nal units are expected");
18113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
18123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
18133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nextStartCode == NULL) {
18153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
18163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
18173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Move on to find the next parameter set
18193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft -= nextStartCode - tmp;
18203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        tmp = nextStartCode;
18213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mCodecSpecificDataSize += (2 + paramSetLen);
18223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
18233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
18253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of seq parameter sets
18263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nSeqParamSets = mSeqParamSets.size();
18273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets == 0) {
182829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find sequence parameter set");
18293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
18303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
18313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets > 0x1F) {
183329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Too many seq parameter sets (%d) found", nSeqParamSets);
18343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
18353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
18363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
18373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
18393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of pic parameter sets
18403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nPicParamSets = mPicParamSets.size();
18413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets == 0) {
184229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find picture parameter set");
18433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
18443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
18453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets > 0xFF) {
184629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Too many pic parameter sets (%d) found", nPicParamSets);
18473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
18483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
18493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
18501374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME:
18511374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above
18521374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0
18531374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0
18543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
18553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the profiles
18563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // These profiles requires additional parameter set extensions
18573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mProfileIdc == 100 || mProfileIdc == 110 ||
18583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc == 122 || mProfileIdc == 144) {
185929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
18603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return BAD_VALUE;
18613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
18623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
18631374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif
18643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
18653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
1866548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
186703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
186803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
1869548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
187003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
187129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Already have codec specific data");
187203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
187303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
187403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
18753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4) {
187629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Codec specific data length too short: %d", size);
187703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
187803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
187903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
18803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data is in the form of AVCCodecSpecificData
18813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (memcmp("\x00\x00\x00\x01", data, 4)) {
18823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return copyAVCCodecSpecificData(data, size);
188303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
188403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
18853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (parseAVCCodecSpecificData(data, size) != OK) {
188603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
188703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
188803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
18893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // ISO 14496-15: AVC file format
18903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize += 7;  // 7 more bytes in the header
189103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
189203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
18933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = 1;                     // version
18943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[1] = mProfileIdc;           // profile indication
18953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[2] = mProfileCompatible;    // profile compatibility
18963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[3] = mLevelIdc;
189703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
18983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
1899b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mOwner->useNalLengthFour()) {
1900b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 3;  // length size == 4 bytes
1901b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
1902b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 1;  // length size == 2 bytes
1903b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
190403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
19053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 3-bit '111' followed by 5-bit numSequenceParameterSets
19063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nSequenceParamSets = mSeqParamSets.size();
19073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[5] = 0xe0 | nSequenceParamSets;
19083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 6;
19093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
19103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mSeqParamSets.end(); ++it) {
19113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit sequence parameter set length
19123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t seqParamSetLength = it->mLength;
19133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = seqParamSetLength >> 8;
19143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = seqParamSetLength & 0xff;
19153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // SPS NAL unit (sequence parameter length bytes)
19173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, seqParamSetLength);
19183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + seqParamSetLength);
19193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
19203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 8-bit nPictureParameterSets
19223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nPictureParamSets = mPicParamSets.size();
19233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = nPictureParamSets;
19243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 1;
19253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
19263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mPicParamSets.end(); ++it) {
19273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit picture parameter set length
19283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t picParamSetLength = it->mLength;
19293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = picParamSetLength >> 8;
19303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = picParamSetLength & 0xff;
19313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // PPS Nal unit (picture parameter set length bytes)
19333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, picParamSetLength);
19343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + picParamSetLength);
19353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
193603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
193703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
193803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
193903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1940872a481558350634a3fd5cb67939de288af00ecbJames Dong/*
1941872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that
1942872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information
1943872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio
1944872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger
1945872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5,
1946872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined.
1947872a481558350634a3fd5cb67939de288af00ecbJames Dong */
1948872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) {
1949872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t driftTimeUs = 0;
1950872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) {
1951872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t prevDriftTimeUs = mOwner->getDriftTimeUs();
1952872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1;
1953872a481558350634a3fd5cb67939de288af00ecbJames Dong        mOwner->setDriftTimeUs(timeUs);
1954872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
1955872a481558350634a3fd5cb67939de288af00ecbJames Dong}
1956872a481558350634a3fd5cb67939de288af00ecbJames Dong
195737187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() {
195830ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
195913aec890216948b0c364f8f92792129d0335f506James Dong    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
196043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    const bool hasMultipleTracks = (mOwner->numTracks() > 1);
196113aec890216948b0c364f8f92792129d0335f506James Dong    int64_t chunkTimestampUs = 0;
196213aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nChunks = 0;
196313aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nZeroLengthFrames = 0;
1964965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastTimestampUs = 0;      // Previous sample time stamp
1965965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationUs = 0;       // Between the previous two samples
1966965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t currDurationTicks = 0;    // Timescale based ticks
1967965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationTicks = 0;    // Timescale based ticks
1968965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int32_t sampleCount = 1;          // Sample count in the current stts table entry
1969000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    uint32_t previousSampleSize = 0;  // Size of the previous sample
1970a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t previousPausedDurationUs = 0;
1971965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t timestampUs = 0;
1972000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t cttsOffsetTimeUs = 0;
1973000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t currCttsOffsetTimeTicks = 0;   // Timescale based ticks
1974000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t lastCttsOffsetTimeTicks = -1;  // Timescale based ticks
197543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    int32_t cttsSampleCount = 0;           // Sample count in the current ctts table entry
1976c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t lastSamplesPerChunk = 0;
1977e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
1978a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    if (mIsAudio) {
1979a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
1980a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    } else {
1981a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
1982a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    }
198386106f8b0641444c97a39e9788eeef55ab2a2ac6Glenn Kasten    androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
1984985f838934510983d8a887461e98dca60a6e858fJames Dong
1985d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong    sp<MetaData> meta_data;
198620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
198793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t err = OK;
198820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
198993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    while (!mDone && (err = mSource->read(&buffer)) == OK) {
199020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
199120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
199220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
199313aec890216948b0c364f8f92792129d0335f506James Dong            ++nZeroLengthFrames;
199420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
199520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
199620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1997a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // If the codec specific data has not been received yet, delay pause.
1998a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // After the codec specific data is received, discard what we received
1999a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // when the track is to be paused.
2000a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused && !mResumed) {
2001a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer->release();
2002a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer = NULL;
2003a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            continue;
2004a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2005a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
200630ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
200730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
200803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
200903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
201003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
2011548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            CHECK(!mGotAllCodecSpecificData);
2012548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
20131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (mIsAvc) {
201403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                status_t err = makeAVCCodecSpecificData(
201503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
201603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
201703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        buffer->range_length());
201843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                CHECK_EQ((status_t)OK, err);
20191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            } else if (mIsMPEG4) {
202003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificDataSize = buffer->range_length();
202103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificData = malloc(mCodecSpecificDataSize);
202203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                memcpy(mCodecSpecificData,
202303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
202403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
202503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                       buffer->range_length());
202630ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
202730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
202830ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
202930ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
203030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
2031548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
203230ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
2033a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2034a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2035d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // Make a deep copy of the MediaBuffer and Metadata and release
2036d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // the original as soon as we can
2037d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
2038d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
2039d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                buffer->range_length());
2040d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        copy->set_range(0, buffer->range_length());
2041d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data = new MetaData(*buffer->meta_data().get());
2042d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer->release();
2043d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer = NULL;
2044d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
20451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (mIsAvc) StripStartcode(copy);
2046e136c3bb38e88315bf8797a464ebf2c788296b22James Dong
2047b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        size_t sampleSize = copy->range_length();
2048b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        if (mIsAvc) {
2049b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            if (mOwner->useNalLengthFour()) {
2050b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 4;
2051b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            } else {
2052b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 2;
2053b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            }
2054b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        }
2055050b28a593350047845a45a14cc5026221ac1620James Dong
2056d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        // Max file size or duration handling
20571f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mMdatSizeBytes += sampleSize;
20581f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        updateTrackSizeEstimate();
20591f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
2060d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileSizeLimit()) {
2061d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
2062d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2063d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2064d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileDurationLimit()) {
2065d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
2066d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2067d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2068d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2069050b28a593350047845a45a14cc5026221ac1620James Dong
2070d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        int32_t isSync = false;
2071d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
2072d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
2073d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
2074d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong////////////////////////////////////////////////////////////////////////////////
2075c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (mStszTableEntries->count() == 0) {
207670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mFirstSampleTimeRealUs = systemTime() / 1000;
2077f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimestampUs = timestampUs;
2078f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mOwner->setStartTimestampUs(mStartTimestampUs);
20798428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs = mStartTimestampUs;
20803c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        }
208148c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
2082a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mResumed) {
20838428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
208443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            CHECK_GE(durExcludingEarlierPausesUs, 0ll);
20858428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
208643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            CHECK_GE(pausedDurationUs, lastDurationUs);
20878428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs += pausedDurationUs - lastDurationUs;
2088a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mResumed = false;
2089a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2090a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2091a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        timestampUs -= previousPausedDurationUs;
209243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_GE(timestampUs, 0ll);
2093000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        if (!mIsAudio) {
2094965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            /*
2095965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Composition time: timestampUs
2096965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Decoding time: decodingTimeUs
2097000e18370baae60ffd9f25b509501dd8c26deabfJames Dong             * Composition time offset = composition time - decoding time
2098965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             */
2099965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            int64_t decodingTimeUs;
2100965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
2101965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            decodingTimeUs -= previousPausedDurationUs;
2102000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            cttsOffsetTimeUs =
2103000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
210443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            CHECK_GE(cttsOffsetTimeUs, 0ll);
2105965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            timestampUs = decodingTimeUs;
2106000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            ALOGV("decoding time: %lld and ctts offset time: %lld",
2107000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                timestampUs, cttsOffsetTimeUs);
2108000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2109000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts box table if necessary
2110000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            currCttsOffsetTimeTicks =
2111000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL;
211243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            CHECK_LE(currCttsOffsetTimeTicks, 0x0FFFFFFFFLL);
2113c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 0) {
211443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // Force the first ctts table entry to have one single entry
211543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // so that we can do adjustment for the initial track start
211643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // time offset easily in writeCttsBox().
211743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
211843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                addOneCttsTableEntry(1, currCttsOffsetTimeTicks);
211943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                cttsSampleCount = 0;      // No sample in ctts box is pending
212043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            } else {
212143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) {
212243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
212343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
212443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    cttsSampleCount = 1;  // One sample in ctts box is pending
212543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                } else {
212643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    ++cttsSampleCount;
212743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                }
212843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            }
2129000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2130000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts time offset range
2131c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 0) {
2132000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2133000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2134000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            } else {
2135000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) {
2136000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2137000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) {
2138000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2139000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                }
2140000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            }
2141000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2142965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        }
2143872a481558350634a3fd5cb67939de288af00ecbJames Dong
2144872a481558350634a3fd5cb67939de288af00ecbJames Dong        if (mIsRealTimeRecording) {
2145872a481558350634a3fd5cb67939de288af00ecbJames Dong            if (mIsAudio) {
2146872a481558350634a3fd5cb67939de288af00ecbJames Dong                updateDriftTime(meta_data);
2147e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
2148e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
2149872a481558350634a3fd5cb67939de288af00ecbJames Dong
215043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_GE(timestampUs, 0ll);
21513856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("%s media time stamp: %lld and previous paused duration %lld",
21528428af5381e835cc783b7ecb0d71cb60961c99c2James Dong                mIsAudio? "Audio": "Video", timestampUs, previousPausedDurationUs);
2153c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong        if (timestampUs > mTrackDurationUs) {
2154c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong            mTrackDurationUs = timestampUs;
21553b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        }
21563b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber
21575a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // We need to use the time scale based ticks, rather than the
21585a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // timestamp itself to determine whether we have to use a new
21595a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // stts entry, since we may have rounding errors.
21605a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // The calculation is intended to reduce the accumulated
21615a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // rounding errors.
21625a217fba010e801c255503602bda4b86ac5a6ac9James Dong        currDurationTicks =
21635a217fba010e801c255503602bda4b86ac5a6ac9James Dong            ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
21645a217fba010e801c255503602bda4b86ac5a6ac9James Dong                (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
2165c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (currDurationTicks < 0ll) {
2166c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            ALOGE("timestampUs %lld < lastTimestampUs %lld for %s track",
2167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                timestampUs, lastTimestampUs, mIsAudio? "Audio": "Video");
2168c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            return UNKNOWN_ERROR;
21698c460498c028888c533ab442be12b6d4b669b965James Dong        }
21708c460498c028888c533ab442be12b6d4b669b965James Dong
2171c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStszTableEntries->add(htonl(sampleSize));
2172c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (mStszTableEntries->count() > 2) {
2173c059860c73678a202bfa33062723e8f82fb779d9James Dong
2174a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // Force the first sample to have its own stts entry so that
2175a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // we can adjust its value later to maintain the A/V sync.
2176c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) {
217779761ab096f57c3027fad9556c2bc436672d614eJames Dong                addOneSttsTableEntry(sampleCount, lastDurationTicks);
2178be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                sampleCount = 1;
2179be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
2180be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                ++sampleCount;
2181be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
2182965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2183be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
2184be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        if (mSamplesHaveSameSize) {
2185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) {
2186be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSamplesHaveSameSize = false;
2187be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
21888644c14618d30d9e57a69df40ed939986ebf02c4James Dong            previousSampleSize = sampleSize;
2189be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
21903856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("%s timestampUs/lastTimestampUs: %lld/%lld",
2191a472613aec322e25891abf5c77bf3f7e3c244920James Dong                mIsAudio? "Audio": "Video", timestampUs, lastTimestampUs);
21928644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastDurationUs = timestampUs - lastTimestampUs;
2193c059860c73678a202bfa33062723e8f82fb779d9James Dong        lastDurationTicks = currDurationTicks;
21948644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastTimestampUs = timestampUs;
219520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2196d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        if (isSync != 0) {
2197c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            addOneStssTableEntry(mStszTableEntries->count());
2198d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        }
2199d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
220093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (mTrackingProgressStatus) {
220193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            if (mPreviousTrackTimeUs <= 0) {
220293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong                mPreviousTrackTimeUs = mStartTimestampUs;
220393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            }
2204faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong            trackProgressStatus(timestampUs);
220593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
220643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        if (!hasMultipleTracks) {
2207c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy)
220858ae9c530247668f8af36e30d228c716c226b3d4James Dong                                 : mOwner->addSample_l(copy);
2209c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2210c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t count = (mOwner->use32BitFileOffset()
2211c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        ? mStcoTableEntries->count()
2212c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        : mCo64TableEntries->count());
2213c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2214c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (count == 0) {
22151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                addChunkOffset(offset);
221658ae9c530247668f8af36e30d228c716c226b3d4James Dong            }
221758ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy->release();
221858ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy = NULL;
221958ae9c530247668f8af36e30d228c716c226b3d4James Dong            continue;
222058ae9c530247668f8af36e30d228c716c226b3d4James Dong        }
222113aec890216948b0c364f8f92792129d0335f506James Dong
222213aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.push_back(copy);
222313aec890216948b0c364f8f92792129d0335f506James Dong        if (interleaveDurationUs == 0) {
22241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStscTableEntry(++nChunks, 1);
22251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            bufferChunk(timestampUs);
222613aec890216948b0c364f8f92792129d0335f506James Dong        } else {
222713aec890216948b0c364f8f92792129d0335f506James Dong            if (chunkTimestampUs == 0) {
222813aec890216948b0c364f8f92792129d0335f506James Dong                chunkTimestampUs = timestampUs;
222913aec890216948b0c364f8f92792129d0335f506James Dong            } else {
223043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                int64_t chunkDurationUs = timestampUs - chunkTimestampUs;
223143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                if (chunkDurationUs > interleaveDurationUs) {
223243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    if (chunkDurationUs > mMaxChunkDurationUs) {
223343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                        mMaxChunkDurationUs = chunkDurationUs;
223443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    }
223513aec890216948b0c364f8f92792129d0335f506James Dong                    ++nChunks;
223613aec890216948b0c364f8f92792129d0335f506James Dong                    if (nChunks == 1 ||  // First chunk
2237c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk != mChunkSamples.size()) {
2238c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk = mChunkSamples.size();
2239c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        addOneStscTableEntry(nChunks, lastSamplesPerChunk);
224013aec890216948b0c364f8f92792129d0335f506James Dong                    }
22411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                    bufferChunk(timestampUs);
224213aec890216948b0c364f8f92792129d0335f506James Dong                    chunkTimestampUs = timestampUs;
224313aec890216948b0c364f8f92792129d0335f506James Dong                }
224413aec890216948b0c364f8f92792129d0335f506James Dong            }
224513aec890216948b0c364f8f92792129d0335f506James Dong        }
224613aec890216948b0c364f8f92792129d0335f506James Dong
224720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
224825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
224945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (isTrackMalFormed()) {
2250690f546b0ee548dbfe997df36418e5302ec2d786James Dong        err = ERROR_MALFORMED;
2251f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    }
225245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
2253bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    mOwner->trackProgressStatus(mTrackId, -1, err);
2254be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
225513aec890216948b0c364f8f92792129d0335f506James Dong    // Last chunk
225643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (!hasMultipleTracks) {
2257c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        addOneStscTableEntry(1, mStszTableEntries->count());
225858ae9c530247668f8af36e30d228c716c226b3d4James Dong    } else if (!mChunkSamples.empty()) {
22591f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        addOneStscTableEntry(++nChunks, mChunkSamples.size());
22601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        bufferChunk(timestampUs);
226113aec890216948b0c364f8f92792129d0335f506James Dong    }
226213aec890216948b0c364f8f92792129d0335f506James Dong
2263be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // We don't really know how long the last frame lasts, since
2264be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // there is no frame time after it, just repeat the previous
2265be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // frame's duration.
2266c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() == 1) {
22678f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        lastDurationUs = 0;  // A single sample's duration
226879761ab096f57c3027fad9556c2bc436672d614eJames Dong        lastDurationTicks = 0;
2269be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    } else {
2270be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        ++sampleCount;  // Count for the last sample
2271be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    }
2272a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2273c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() <= 2) {
227479761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(1, lastDurationTicks);
2275a472613aec322e25891abf5c77bf3f7e3c244920James Dong        if (sampleCount - 1 > 0) {
227679761ab096f57c3027fad9556c2bc436672d614eJames Dong            addOneSttsTableEntry(sampleCount - 1, lastDurationTicks);
2277a472613aec322e25891abf5c77bf3f7e3c244920James Dong        }
2278a472613aec322e25891abf5c77bf3f7e3c244920James Dong    } else {
227979761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(sampleCount, lastDurationTicks);
2280a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
2281a472613aec322e25891abf5c77bf3f7e3c244920James Dong
228243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // The last ctts box may not have been written yet, and this
228343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // is to make sure that we write out the last ctts box.
228443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) {
228543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        if (cttsSampleCount > 0) {
228643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
228743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        }
228843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    }
228943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong
2290c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs += lastDurationUs;
229125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
229243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
229343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    sendTrackSummary(hasMultipleTracks);
229443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
2295df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
2296c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            count, nZeroLengthFrames, mStszTableEntries->count(), mIsAudio? "audio": "video");
2297872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (mIsAudio) {
2298df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("Audio track drift time: %lld us", mOwner->getDriftTimeUs());
2299872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2300365a963142093a1cd8efdcea76b5f65096a5b115James Dong
230137187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err == ERROR_END_OF_STREAM) {
230237187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
230337187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
230437187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
2305365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
2306365a963142093a1cd8efdcea76b5f65096a5b115James Dong
230745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const {
2308c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() == 0) {                      // no samples written
230929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("The number of recorded samples is 0");
231045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
231145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
231245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
2313c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (!mIsAudio && mStssTableEntries->count() == 0) {  // no sync frames for video
231429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("There are no sync frames for video track");
231545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
231645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
231745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
231845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (OK != checkCodecSpecificData()) {         // no codec specific data
231945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
232045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
232145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
232245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    return false;
232345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong}
232445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
232543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) {
232607ec01904613a0bac32caaa8444b4690998faed7James Dong
232707ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send track summary only if test mode is enabled.
232807ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
232907ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
233007ec01904613a0bac32caaa8444b4690998faed7James Dong    }
233107ec01904613a0bac32caaa8444b4690998faed7James Dong
233243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int trackNum = (mTrackId << 28);
233343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
233443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
233543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE,
233643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mIsAudio? 0: 1);
233743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
233843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
233943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS,
234043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mTrackDurationUs / 1000);
234143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
234243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
234343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES,
2344c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    mStszTableEntries->count());
234543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
234686b7f47aa7482424cf8fd248f1315311919be3b0James Dong    {
234786b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // The system delay time excluding the requested initial delay that
234886b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // is used to eliminate the recording sound.
234986b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
235086b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
235186b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
235286b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
235386b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t initialDelayUs =
235486b7f47aa7482424cf8fd248f1315311919be3b0James Dong            mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs;
235586b7f47aa7482424cf8fd248f1315311919be3b0James Dong
235686b7f47aa7482424cf8fd248f1315311919be3b0James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
235770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS,
235870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    (initialDelayUs) / 1000);
235986b7f47aa7482424cf8fd248f1315311919be3b0James Dong    }
236070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
236107ec01904613a0bac32caaa8444b4690998faed7James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
236207ec01904613a0bac32caaa8444b4690998faed7James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES,
236307ec01904613a0bac32caaa8444b4690998faed7James Dong                    mMdatSizeBytes / 1024);
236407ec01904613a0bac32caaa8444b4690998faed7James Dong
236543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (hasMultipleTracks) {
236643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
236743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS,
236843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mMaxChunkDurationUs / 1000);
236970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
237070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
237170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        if (mStartTimestampUs != moovStartTimeUs) {
237270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
237370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
237470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS,
237570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    startTimeOffsetUs / 1000);
237670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        }
237743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    }
237843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong}
237943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
2380faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
23813856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("trackProgressStatus: %lld us", timeUs);
2382c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2383215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    if (mTrackEveryTimeDurationUs > 0 &&
2384215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
23853856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Fire time tracking progress status at %lld us", timeUs);
2386bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err);
238793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        mPreviousTrackTimeUs = timeUs;
238893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
238993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
239093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
2391faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus(
2392bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        size_t trackId, int64_t timeUs, status_t err) {
2393faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    Mutex::Autolock lock(mLock);
2394bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t trackNum = (trackId << 28);
2395faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2396faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Error notification
2397faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Do not consider ERROR_END_OF_STREAM an error
2398faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (err != OK && err != ERROR_END_OF_STREAM) {
2399bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
2400bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL,
2401faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2402faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
2403faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2404faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2405faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (timeUs == -1) {
2406faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send completion notification
2407bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2408bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS,
2409faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2410faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    } else {
2411faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send progress status
2412bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2413bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME,
2414faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               timeUs / 1000);
2415faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2416faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong}
2417faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2418d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) {
24193856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setDriftTimeUs: %lld us", driftTimeUs);
2420e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2421d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    mDriftTimeUs = driftTimeUs;
2422e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2423e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2424e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() {
24253856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("getDriftTimeUs: %lld us", mDriftTimeUs);
2426e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2427e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    return mDriftTimeUs;
2428e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2429e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2430b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() {
2431b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    return mUse4ByteNalLength;
2432b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong}
2433b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
24341c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
24353856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk");
24361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
24371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Chunk chunk(this, timestampUs, mChunkSamples);
24381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mOwner->bufferChunk(chunk);
243913aec890216948b0c364f8f92792129d0335f506James Dong    mChunkSamples.clear();
244020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
244120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24423b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
2443c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    return mTrackDurationUs;
244420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
244520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2446d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
2447d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return mEstimatedTrackSizeBytes;
2448d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
2449d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2450690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const {
2451690f546b0ee548dbfe997df36418e5302ec2d786James Dong    const char *mime;
2452690f546b0ee548dbfe997df36418e5302ec2d786James Dong    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
2453690f546b0ee548dbfe997df36418e5302ec2d786James Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
2454690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
2455690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2456690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (!mCodecSpecificData ||
2457690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize <= 0) {
245829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Missing codec specific data");
2459690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2460690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2461690f546b0ee548dbfe997df36418e5302ec2d786James Dong    } else {
2462690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (mCodecSpecificData ||
2463690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize > 0) {
246429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Unexepected codec specific data found");
2465690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2466690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2467690f546b0ee548dbfe997df36418e5302ec2d786James Dong    }
2468690f546b0ee548dbfe997df36418e5302ec2d786James Dong    return OK;
2469690f546b0ee548dbfe997df36418e5302ec2d786James Dong}
2470690f546b0ee548dbfe997df36418e5302ec2d786James Dong
2471b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) {
247220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24733856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("%s track time scale: %d",
24741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsAudio? "Audio": "Video", mTimeScale);
24758f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
247620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
2477b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("trak");
2478b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeTkhdBox(now);
2479b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("mdia");
2480b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeMdhdBox(now);
2481b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeHdlrBox();
2482b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->beginBox("minf");
2483b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                if (mIsAudio) {
2484b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeSmhdBox();
2485b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                } else {
2486b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeVmhdBox();
2487b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                }
2488b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeDinfBox();
2489b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeStblBox(use32BitOffset);
2490b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->endBox();  // minf
2491b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->endBox();  // mdia
2492b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // trak
2493b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2494b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2495b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) {
2496b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stbl");
2497b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsd");
2498b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);               // version=0, flags=0
2499b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);               // entry count
2500b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
2501b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAudioFourCCBox();
2502b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
2503b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeVideoFourCCBox();
2504b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2505b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsd
2506b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeSttsBox();
2507965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    writeCttsBox();
2508b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!mIsAudio) {
2509b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeStssBox();
2510b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2511b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStszBox();
2512b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStscBox();
2513b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStcoBox(use32BitOffset);
2514b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stbl
2515b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2516b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2517b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() {
2518b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
2519b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
2520b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2521b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
2522b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("mp4v");
2523b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
2524b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("s263");
2525b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2526b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("avc1");
2527b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
252829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
2529b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(!"should not be here, unknown mime type.");
2530b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2531b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2532b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2533b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2534b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // data ref index
2535b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
2536b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2537b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2538b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2539b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2540b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2541b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t width, height;
2542b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeyWidth, &width);
2543b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = success && mMeta->findInt32(kKeyHeight, &height);
2544b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2545b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2546b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(width);
2547b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(height);
2548b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // horiz resolution
2549b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // vert resolution
2550b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2551b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // frame count
2552b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write("                                ", 32);
2553b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x18);        // depth
2554b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(-1);          // predefined
2555b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
255643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_LT(23 + mCodecSpecificDataSize, 128);
2557b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2558b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
2559b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4vEsdsBox();
2560b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
2561b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeD263Box();
2562b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2563b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAvccBox();
2564b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2565b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2566b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writePaspBox();
2567b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // mp4v, s263 or avc1
2568b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2569b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2570b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() {
2571b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
2572b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
2573b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2574b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *fourcc = NULL;
2575b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
2576b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fourcc = "samr";
2577b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
2578b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fourcc = "sawb";
2579b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
2580b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fourcc = "mp4a";
2581b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
258229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
2583b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(!"should not be here, unknown mime type.");
2584b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2585b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2586b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(fourcc);        // audio format
2587b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2588b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2589b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x1);         // data ref index
2590b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2591b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2592b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t nChannels;
2593b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
2594b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(nChannels);   // channel count
2595b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(16);          // sample size
2596b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
2597b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2598b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2599b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t samplerate;
2600b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeySampleRate, &samplerate);
2601b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2602b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(samplerate << 16);
2603b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
2604b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4aEsdsBox();
2605b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
2606b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong               !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
2607b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeDamrBox();
2608b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2609b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2610b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2611b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2612b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() {
2613b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
2614b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
261543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mCodecSpecificDataSize, 0);
2616b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2617b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Make sure all sizes encode to a single byte.
261843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_LT(mCodecSpecificDataSize + 23, 128);
2619b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2620b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);     // version=0, flags=0
2621b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);   // ES_DescrTag
2622b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
2623b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);// ES_ID
2624b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x00);
2625b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2626b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
2627b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
2628b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
2629b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x15);   // streamType AudioStream
2630b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2631b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x03);  // XXX
2632b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x00);   // buffer size 24-bit
2633b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(96000); // max bit rate
2634b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(96000); // avg bit rate
2635b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2636b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
2637b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
2638b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2639b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2640b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
2641b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
2642b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
2643b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
2644b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
2645b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
2646b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2647b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
2648b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2649b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2650b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() {
2651b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
265243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mCodecSpecificDataSize, 0);
2653b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
2654b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2655b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);    // version=0, flags=0
2656b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2657b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);  // ES_DescrTag
2658b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
2659b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);  // ES_ID
2660b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x1f);
2661b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2662b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
2663b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
2664b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
2665b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x11);  // streamType VisualStream
2666b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2667b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData[] = {
2668b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01, 0x77, 0x00,
2669b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x00, 0x03, 0xe8, 0x00,
2670b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x00, 0x03, 0xe8, 0x00
2671b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
2672b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData, sizeof(kData));
2673b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2674b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
2675b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2676b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
2677b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2678b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2679b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
2680b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
2681b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
2682b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
2683b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
2684b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
2685b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2686b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
2687b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2688b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2689b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTkhdBox(time_t now) {
2690b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("tkhd");
2691b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Flags = 7 to indicate that the track is enabled, and
2692b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // part of the presentation
2693b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x07);          // version=0, flags=7
2694b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
2695b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
2696219f195159f93d627af2b243732e3f9020511a46James Dong    mOwner->writeInt32(mTrackId);      // track id starts with 1
2697b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
26988f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t trakDurationUs = getDurationUs();
2699b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mvhdTimeScale = mOwner->getTimeScale();
2700b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t tkhdDuration =
2701b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
2702b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
2703b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2704b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2705b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // layer
2706b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // alternate group
2707b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
2708b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // reserved
2709b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2710b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCompositionMatrix(mRotation);       // matrix
271120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2712b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
2713b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
2714b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
2715b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
2716b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        int32_t width, height;
2717b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        bool success = mMeta->findInt32(kKeyWidth, &width);
2718b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        success = success && mMeta->findInt32(kKeyHeight, &height);
2719b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(success);
2720b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2721b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
2722b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
2723b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2724b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // tkhd
2725b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2726b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2727b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() {
2728b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("vmhd");
2729b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x01);        // version=0, flags=1
2730b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // graphics mode
2731b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // opcolor
2732b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
2733b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
2734b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2735b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2736b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2737b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() {
2738b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("smhd");
2739b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // version=0, flags=0
2740b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // balance
2741b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2742b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2743b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2744b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2745b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() {
2746b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("hdlr");
2747b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
2748b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // component type: should be mhlr
2749b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeFourcc(mIsAudio ? "soun" : "vide");  // component subtype
2750b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2751b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2752b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2753b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Removing "r" for the name string just makes the string 4 byte aligned
2754b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle");  // name
2755b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2756b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2757b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2758b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMdhdBox(time_t now) {
2759b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t trakDurationUs = getDurationUs();
2760b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("mdhd");
2761b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
2762b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
2763b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
2764b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mTimeScale);    // media timescale
2765b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
2766b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mdhdDuration);  // use media timescale
2767b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Language follows the three letter standard ISO-639-2/T
2768b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 'e', 'n', 'g' for "English", for instance.
2769b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Each character is packed as the difference between its ASCII value and 0x60.
2770b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // For "English", these are 00101, 01110, 00111.
2771b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // XXX: Where is the padding bit located: 0x15C7?
2772b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // language code
2773b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // predefined
2774b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2775b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2776b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2777b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() {
2778b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 3gpp2 Spec AMRSampleEntry fields
2779b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("damr");
2780b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString("   ");  // vendor: 4 bytes
2781b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // decoder version
2782b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x83FF);   // mode set: all enabled
2783b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // mode change period
2784b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(1);         // frames per sample
2785b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2786b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2787b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2788b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() {
2789b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // The table index here refers to the sample description index
2790b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // in the sample table entries.
2791b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("url ");
2792b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
2793b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // url
2794b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2795b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2796b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() {
2797b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dref");
2798b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2799b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // entry count (either url or urn)
2800b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeUrlBox();
2801b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dref
2802b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2803b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2804b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() {
2805b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dinf");
2806b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeDrefBox();
2807b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dinf
2808b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2809b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2810b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() {
2811b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
281243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(mCodecSpecificDataSize, 5);
2813b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2814b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Patch avcc's lengthSize field to match the number
2815b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // of bytes we use to indicate the size of a nal unit.
2816b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
2817b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
2818b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("avcC");
2819b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2820b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // avcC
2821b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2822b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2823b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() {
2824b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("d263");
2825b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // vendor
2826b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // decoder version
2827b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(10);  // level: 10
2828b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // profile: 0
2829b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // d263
2830b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2831b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2832b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square
2833b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() {
2834b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("pasp");
2835b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // hspacing
2836b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // vspacing
2837b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // pasp
2838b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2839b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2840000e18370baae60ffd9f25b509501dd8c26deabfJames Dongint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const {
2841a472613aec322e25891abf5c77bf3f7e3c244920James Dong    int64_t trackStartTimeOffsetUs = 0;
2842b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
2843b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mStartTimestampUs != moovStartTimeUs) {
284443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_GT(mStartTimestampUs, moovStartTimeUs);
2845b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
2846b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2847000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    return (trackStartTimeOffsetUs *  mTimeScale + 500000LL) / 1000000LL;
2848000e18370baae60ffd9f25b509501dd8c26deabfJames Dong}
2849000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2850000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() {
2851000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->beginBox("stts");
2852000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2853c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t duration;
2854c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    CHECK(mSttsTableEntries->get(duration, 1));
2855c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    duration = htonl(duration);  // Back to host byte order
2856c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1);
2857c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->write(mOwner);
2858b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stts
2859b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
286020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2861965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() {
2862965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if (mIsAudio) {  // ctts is not for audio
2863965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
2864965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
2865965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2866000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    // There is no B frame at all
2867000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) {
2868000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        return;
2869000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    }
2870000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2871965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    // Do not write ctts box when there is no need to have it.
2872c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mCttsTableEntries->count() == 0) {
2873965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
2874965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
2875965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2876c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ALOGV("ctts box has %d entries with range [%lld, %lld]",
2877c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs);
2878965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2879965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->beginBox("ctts");
2880000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2881c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t duration;
2882c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    CHECK(mCttsTableEntries->get(duration, 1));
2883c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    duration = htonl(duration);  // Back host byte order
2884c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime() - mMinCttsOffsetTimeUs), 1);
2885c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->write(mOwner);
2886965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->endBox();  // ctts
2887965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
2888965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2889b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() {
2890b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stss");
2891b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2892c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->write(mOwner);
2893b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stss
2894b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
289525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
2896b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() {
2897b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsz");
2898b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2899c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mOwner->writeInt32(0);
2900c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries->write(mOwner);
2901b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsz
2902b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
290320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2904b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() {
2905b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsc");
2906b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2907c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries->write(mOwner);
2908b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsc
2909b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
291020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2911b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) {
2912b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(use32BitOffset? "stco": "co64");
2913b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2914c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (use32BitOffset) {
2915c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->write(mOwner);
2916c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
2917c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->write(mOwner);
2918b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2919b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stco or co64
292020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
292120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
292207b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() {
292307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("udta");
292407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeGeoDataBox();
292507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
292607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
292707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
292807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
292907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
293007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
293107b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() {
293207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("\xA9xyz");
293307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    /*
293407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * For historical reasons, any user data start
293507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * with "\0xA9", must be followed by its assoicated
293607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * language code.
2937432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x0012: text string length
2938432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x15c7: lang (locale) code: en
293907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     */
294007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt32(0x001215c7);
294107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLatitude(mLatitudex10000);
294207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLongitude(mLongitudex10000);
294307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt8(0x2F);
294407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
294507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
294607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
294720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
2948