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();
320efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeMdhdBox(uint32_t now);
321b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSmhdBox();
322b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVmhdBox();
323b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeHdlrBox();
324efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeTkhdBox(uint32_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
824efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonuint32_t MPEG4Writer::getMpeg4Time() {
825b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    time_t now = time(NULL);
826efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // MP4 file uses time counting seconds since midnight, Jan. 1, 1904
827efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // while time function returns Unix epoch values which starts
828efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // at 1970-01-01. Lets add the number of seconds between them
829efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t mpeg4Time = now + (66 * 365 + 17) * (24 * 60 * 60);
830efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    return mpeg4Time;
831efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson}
832efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson
833efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) {
834efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
835b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("mvhd");
836b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // version=0, flags=0
837b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // creation time
838b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // modification time
839b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTimeScale);    // mvhd timescale
840b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6;
841b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(duration);
842b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0x10000);       // rate: 1.0
843b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0x100);         // volume
844b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0);             // reserved
845b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
846b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
847b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeCompositionMatrix(0); // matrix
848b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
849b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
850b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
851b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
852b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
853b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
854b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTracks.size() + 1);  // nextTrackID
855b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // mvhd
856b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
857b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
858b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) {
859b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("moov");
860b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMvhdBox(durationUs);
86107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (mAreGeoTagsAvailable) {
86207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        writeUdtaBox();
86307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
864b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t id = 1;
865b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    for (List<Track *>::iterator it = mTracks.begin();
866b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        it != mTracks.end(); ++it, ++id) {
867b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (*it)->writeTrackHeader(mUse32BitOffset);
868b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
869b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // moov
870b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
871b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
8722cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) {
873b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("ftyp");
874b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
875b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t fileType;
876b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (param && param->findInt32(kKeyFileType, &fileType) &&
877b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fileType != OUTPUT_FORMAT_MPEG_4) {
878b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("3gp4");
879b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
880b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("isom");
881b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
882b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
883b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);
884b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeFourcc("isom");
885b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeFourcc("3gp4");
886b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();
887b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
888b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
88907ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() {
89007ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5)
89107ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5"
89207ec01904613a0bac32caaa8444b4690998faed7James Dong#endif
89307ec01904613a0bac32caaa8444b4690998faed7James Dong
89407ec01904613a0bac32caaa8444b4690998faed7James Dong    // Test mode is enabled only if rw.media.record.test system
89507ec01904613a0bac32caaa8444b4690998faed7James Dong    // property is enabled.
89607ec01904613a0bac32caaa8444b4690998faed7James Dong    char value[PROPERTY_VALUE_MAX];
89707ec01904613a0bac32caaa8444b4690998faed7James Dong    if (property_get("rw.media.record.test", value, NULL) &&
89807ec01904613a0bac32caaa8444b4690998faed7James Dong        (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) {
89907ec01904613a0bac32caaa8444b4690998faed7James Dong        return true;
90007ec01904613a0bac32caaa8444b4690998faed7James Dong    }
90107ec01904613a0bac32caaa8444b4690998faed7James Dong    return false;
90207ec01904613a0bac32caaa8444b4690998faed7James Dong}
90307ec01904613a0bac32caaa8444b4690998faed7James Dong
90470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() {
90507ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send session summary only if test mode is enabled
90607ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
90707ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
90807ec01904613a0bac32caaa8444b4690998faed7James Dong    }
90907ec01904613a0bac32caaa8444b4690998faed7James Dong
91070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
91170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong         it != mChunkInfos.end(); ++it) {
91270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int trackNum = it->mTrack->getTrackId() << 28;
91370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
91470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS,
91570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs);
91670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    }
91770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong}
91870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
91913aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
92013aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
92113aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
92213aec890216948b0c364f8f92792129d0335f506James Dong}
92313aec890216948b0c364f8f92792129d0335f506James Dong
92413aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() {
92513aec890216948b0c364f8f92792129d0335f506James Dong    mLock.lock();
92613aec890216948b0c364f8f92792129d0335f506James Dong}
92713aec890216948b0c364f8f92792129d0335f506James Dong
92813aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() {
92913aec890216948b0c364f8f92792129d0335f506James Dong    mLock.unlock();
93013aec890216948b0c364f8f92792129d0335f506James Dong}
93120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
932c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
933c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
93420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
935c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    ::write(mFd,
936c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          (const uint8_t *)buffer->data() + buffer->range_offset(),
937c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          buffer->range_length());
93820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
93920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
94020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
94120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
94220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
94320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
94403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
94503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
94603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
94703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
94803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
94903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
95003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
95103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
95203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
95303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
95403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
95503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
95603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
95703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
958c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
959c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
96030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
96130ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
96203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
963b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mUse4ByteNalLength) {
964b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 24;
965c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
966b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 16) & 0xff;
967c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
968b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 8) & 0xff;
969c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
970b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
971c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
972c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong
973c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd,
974c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              (const uint8_t *)buffer->data() + buffer->range_offset(),
975c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              length);
976b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
977b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 4;
978b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
97943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_LT(length, 65536);
98030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
981b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 8;
982c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
983b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
984c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
985c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length);
986b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 2;
987b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
98830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
98930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
99030ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
99130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
9927837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write(
993674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        const void *ptr, size_t size, size_t nmemb) {
9947837c17063a4c50bc856ba59418516fdab731de7James Dong
9957837c17063a4c50bc856ba59418516fdab731de7James Dong    const size_t bytes = size * nmemb;
9967837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
997674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        // This happens only when we write the moov box at the end of
998674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        // recording, not for each output video/audio frame we receive.
999c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
10001acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        if (moovBoxSize > mEstimatedMoovBoxSize) {
1001c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            for (List<off64_t>::iterator it = mBoxes.begin();
10027837c17063a4c50bc856ba59418516fdab731de7James Dong                 it != mBoxes.end(); ++it) {
10037837c17063a4c50bc856ba59418516fdab731de7James Dong                (*it) += mOffset;
10047837c17063a4c50bc856ba59418516fdab731de7James Dong            }
1005674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            lseek64(mFd, mOffset, SEEK_SET);
1006674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset);
1007674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            ::write(mFd, ptr, size * nmemb);
10087837c17063a4c50bc856ba59418516fdab731de7James Dong            mOffset += (bytes + mMoovBoxBufferOffset);
10097837c17063a4c50bc856ba59418516fdab731de7James Dong            free(mMoovBoxBuffer);
10107837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBuffer = NULL;
10117837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset = 0;
10127837c17063a4c50bc856ba59418516fdab731de7James Dong            mWriteMoovBoxToMemory = false;
10137837c17063a4c50bc856ba59418516fdab731de7James Dong            mStreamableFile = false;
10147837c17063a4c50bc856ba59418516fdab731de7James Dong        } else {
10157837c17063a4c50bc856ba59418516fdab731de7James Dong            memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
10167837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset += bytes;
10177837c17063a4c50bc856ba59418516fdab731de7James Dong        }
10187837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1019674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        ::write(mFd, ptr, size * nmemb);
10207837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset += bytes;
10217837c17063a4c50bc856ba59418516fdab731de7James Dong    }
10227837c17063a4c50bc856ba59418516fdab731de7James Dong    return bytes;
10237837c17063a4c50bc856ba59418516fdab731de7James Dong}
10247837c17063a4c50bc856ba59418516fdab731de7James Dong
102520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
10260c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(fourcc), 4);
102720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10287837c17063a4c50bc856ba59418516fdab731de7James Dong    mBoxes.push_back(mWriteMoovBoxToMemory?
10297837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset: mOffset);
103020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
103120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
103220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
103320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
103420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
103520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
10360c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
103720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1038c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = *--mBoxes.end();
103920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
104020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10417837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
10427837c17063a4c50bc856ba59418516fdab731de7James Dong       int32_t x = htonl(mMoovBoxBufferOffset - offset);
10437837c17063a4c50bc856ba59418516fdab731de7James Dong       memcpy(mMoovBoxBuffer + offset, &x, 4);
10447837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1045c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, offset, SEEK_SET);
10467837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mOffset - offset);
10477837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset -= 4;
1048c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
10497837c17063a4c50bc856ba59418516fdab731de7James Dong    }
105020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
105120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
105220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
1053674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 1);
105420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
105520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
105620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
105720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
1058674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 2);
105920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
106020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
106120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
106220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
1063674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 4);
106420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
106520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
106620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
106720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
1068674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 8);
106920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
107020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
107120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
107220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
1073674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, n + 1);
107420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
107520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
107620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
10770c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(s), 4);
1078674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, 4);
107920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
108020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
108107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
108207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format
108307b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) {
108407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
108507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
108607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
108707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
108807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[9];
108907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
109007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
109107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%c%.2d.", sign, wholePart);
109207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
109307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%+.2d.", wholePart);
109407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
109507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
109607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
109707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
109807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
109907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
110007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
110107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[4], 5, "%.4d", fractionalPart);
110207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
110307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
110407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 8);
110507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
110607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
110707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format
110807b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) {
110907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
111007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
111107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
111207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
111307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[10];
111407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
111507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
111607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%c%.3d.", sign, wholePart);
111707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
111807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%+.3d.", wholePart);
111907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
112007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
112107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
112207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
112307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
112407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
112507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
112607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[5], 5, "%.4d", fractionalPart);
112707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
112807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
112907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 9);
113007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
113107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
113207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
113307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
113407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and
113507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000.
113607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and
113707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180]
113807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
113907b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) {
114007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Is latitude or longitude out of range?
114107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (latitudex10000 < -900000 || latitudex10000 > 900000 ||
114207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        longitudex10000 < -1800000 || longitudex10000 > 1800000) {
114307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        return BAD_VALUE;
114407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
114507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
114607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLatitudex10000 = latitudex10000;
114707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLongitudex10000 = longitudex10000;
114807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mAreGeoTagsAvailable = true;
114907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    return OK;
115007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
115107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
115220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
1153674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(data, 1, size);
115420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
115520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
115678a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const {
115778a1a286f736888ae7af8860b2c424af0d978848James Dong    return mStreamableFile;
115878a1a286f736888ae7af8860b2c424af0d978848James Dong}
115978a1a286f736888ae7af8860b2c424af0d978848James Dong
1160d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() {
1161d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1162d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeLimitBytes == 0) {
1163d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1164d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1165d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1166956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
1167d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1168d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1169d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
1170d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
11711f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
117277e8ae9967a078770416619e99ddb5b010def312James Dong    if (!mStreamableFile) {
117377e8ae9967a078770416619e99ddb5b010def312James Dong        // Add 1024 bytes as error tolerance
117477e8ae9967a078770416619e99ddb5b010def312James Dong        return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes;
117577e8ae9967a078770416619e99ddb5b010def312James Dong    }
1176acd234bba9f048971d66890009eeff9a8db94be3James Dong    // Be conservative in the estimate: do not exceed 95% of
1177acd234bba9f048971d66890009eeff9a8db94be3James Dong    // the target file limit. For small target file size limit, though,
1178acd234bba9f048971d66890009eeff9a8db94be3James Dong    // this will not help.
1179acd234bba9f048971d66890009eeff9a8db94be3James Dong    return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100);
1180d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1181d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1182d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() {
1183d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1184d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationLimitUs == 0) {
1185d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1186d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1187d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1188d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1189d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1190d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
1191d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            return true;
1192d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1193d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1194d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return false;
1195d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1196d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
119725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
119825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
119925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
120025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
120125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
120225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
120325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
120425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
120525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
120625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
120725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
120825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
120925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
1210f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
1211df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("setStartTimestampUs: %lld", timeUs);
121243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(timeUs, 0ll);
12133c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
1214065d1aff96818df54456053f1574aec8a234d0deJames Dong    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
1215f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimestampUs = timeUs;
1216df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("Earliest track starting time: %lld", mStartTimestampUs);
12173c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    }
12183c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
12193c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
1220f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() {
12213c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
12223c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    return mStartTimestampUs;
12233c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
12243c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
122558ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() {
122658ae9c530247668f8af36e30d228c716c226b3d4James Dong    Mutex::Autolock autolock(mLock);
122758ae9c530247668f8af36e30d228c716c226b3d4James Dong    return mTracks.size();
122858ae9c530247668f8af36e30d228c716c226b3d4James Dong}
122958ae9c530247668f8af36e30d228c716c226b3d4James Dong
123020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
123120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
123220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
1233bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId)
123420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
123525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
123620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
123720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
1238a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
1239a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mResumed(false),
1240eaae38445a340c4857c1c5569475879a728e63b7James Dong      mStarted(false),
1241bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong      mTrackId(trackId),
1242c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong      mTrackDurationUs(0),
1243956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mEstimatedTrackSizeBytes(0),
1244be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong      mSamplesHaveSameSize(true),
1245c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStszTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1246c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStcoTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1247c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mCo64TableEntries(new ListTableEntries<off64_t>(1000, 1)),
1248c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStscTableEntries(new ListTableEntries<uint32_t>(1000, 3)),
1249c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStssTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1250c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mSttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)),
1251c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mCttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)),
125220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
125325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
1254548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
125513f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mReachedEOS(false),
125613f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mRotation(0) {
125719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    getCodecSpecificDataFromInputFormatIfPossible();
12588f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
12591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    const char *mime;
12601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMeta->findCString(kKeyMIMEType, &mime);
12611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
12621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAudio = !strncasecmp(mime, "audio/", 6);
12631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
12641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
12651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1266c059860c73678a202bfa33062723e8f82fb779d9James Dong    setTimeScale();
1267c059860c73678a202bfa33062723e8f82fb779d9James Dong}
1268c059860c73678a202bfa33062723e8f82fb779d9James Dong
12691f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() {
12701f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1271c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t stcoBoxCount = (mOwner->use32BitFileOffset()
1272c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                            ? mStcoTableEntries->count()
1273c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                            : mCo64TableEntries->count());
1274c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    int64_t stcoBoxSizeBytes = stcoBoxCount * 4;
1275c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4);
12761f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
127778a1a286f736888ae7af8860b2c424af0d978848James Dong    mEstimatedTrackSizeBytes = mMdatSizeBytes;  // media data size
127878a1a286f736888ae7af8860b2c424af0d978848James Dong    if (!mOwner->isFileStreamable()) {
127978a1a286f736888ae7af8860b2c424af0d978848James Dong        // Reserved free space is not large enough to hold
128078a1a286f736888ae7af8860b2c424af0d978848James Dong        // all meta data and thus wasted.
1281c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 +  // stsc box size
1282c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mStssTableEntries->count() * 4 +   // stss box size
1283c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mSttsTableEntries->count() * 8 +   // stts box size
1284c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mCttsTableEntries->count() * 8 +   // ctts box size
128578a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stcoBoxSizeBytes +           // stco box size
128678a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stszBoxSizeBytes;            // stsz box size
128778a1a286f736888ae7af8860b2c424af0d978848James Dong    }
12881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
12891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
12901f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry(
12911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        size_t chunkId, size_t sampleId) {
12921f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1293c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(chunkId));
1294c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(sampleId));
1295c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(1));
12961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
12971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
12981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) {
1299c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->add(htonl(sampleId));
13001f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
13011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
13021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry(
130379761ab096f57c3027fad9556c2bc436672d614eJames Dong        size_t sampleCount, int32_t duration) {
13041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
13055a217fba010e801c255503602bda4b86ac5a6ac9James Dong    if (duration == 0) {
13065ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("0-duration samples found: %d", sampleCount);
13075a217fba010e801c255503602bda4b86ac5a6ac9James Dong    }
1308c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(sampleCount));
1309c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(duration));
13101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
13111f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1312965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry(
1313965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        size_t sampleCount, int32_t duration) {
1314965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1315965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if (mIsAudio) {
1316965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
1317965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
1318c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(sampleCount));
1319c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(duration));
1320965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
1321965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1322c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) {
1323c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mOwner->use32BitFileOffset()) {
1324c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t value = offset;
1325c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->add(htonl(value));
1326c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
1327c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->add(hton64(offset));
1328c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    }
13291f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
13301f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1331c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() {
13323856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setTimeScale");
1333c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Default time scale
1334c059860c73678a202bfa33062723e8f82fb779d9James Dong    mTimeScale = 90000;
1335c059860c73678a202bfa33062723e8f82fb779d9James Dong
1336c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mIsAudio) {
1337c059860c73678a202bfa33062723e8f82fb779d9James Dong        // Use the sampling rate as the default time scale for audio track.
1338c059860c73678a202bfa33062723e8f82fb779d9James Dong        int32_t sampleRate;
1339c059860c73678a202bfa33062723e8f82fb779d9James Dong        bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
1340c059860c73678a202bfa33062723e8f82fb779d9James Dong        CHECK(success);
1341c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = sampleRate;
1342c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1343c059860c73678a202bfa33062723e8f82fb779d9James Dong
1344c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If someone would like to overwrite the timescale, use user-supplied value.
1345c059860c73678a202bfa33062723e8f82fb779d9James Dong    int32_t timeScale;
1346c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
1347c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = timeScale;
1348c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1349c059860c73678a202bfa33062723e8f82fb779d9James Dong
135043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
135119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber}
135219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
135319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
135419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    const char *mime;
135519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
135619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
135719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
135819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
135919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
136019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
136119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyAVCC, &type, &data, &size)) {
136219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificData = malloc(size);
136319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificDataSize = size;
136419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            memcpy(mCodecSpecificData, data, size);
136519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mGotAllCodecSpecificData = true;
136619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
136719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
136819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
136919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
137019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
137119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
137219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
137319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            ESDS esds(data, size);
137419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            if (esds.getCodecSpecificInfo(&data, &size) == OK) {
137519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificData = malloc(size);
137619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificDataSize = size;
137719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                memcpy(mCodecSpecificData, data, size);
137819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mGotAllCodecSpecificData = true;
137919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            }
138019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
138119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
138220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
138320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
138420111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
138520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
138620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1387c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStszTableEntries;
1388c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStcoTableEntries;
1389c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCo64TableEntries;
1390c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStscTableEntries;
1391c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mSttsTableEntries;
1392c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStssTableEntries;
1393c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCttsTableEntries;
1394c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
1395c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries = NULL;
1396c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStcoTableEntries = NULL;
1397c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCo64TableEntries = NULL;
1398c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries = NULL;
1399c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries = NULL;
1400c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries = NULL;
1401c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries = NULL;
1402c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
140320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
140420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
140520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
140620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
140720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
140820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
140993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
14103856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("initTrackingProgressStatus");
141193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mPreviousTrackTimeUs = -1;
141293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackingProgressStatus = false;
141393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
141493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    {
141593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeUs;
141693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
14173856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("Receive request to track progress status for every %lld us", timeUs);
141893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackEveryTimeDurationUs = timeUs;
141993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackingProgressStatus = true;
142093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
142193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
142293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
142393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
14241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static
14251c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) {
14263856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("ThreadWrapper: %p", me);
14271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
14281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    writer->threadFunc();
14291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return NULL;
14301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
14311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
14321c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) {
14333856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk: %p", chunk.mTrack);
14341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Mutex::Autolock autolock(mLock);
14351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK_EQ(mDone, false);
14361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
14371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
14381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
14391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
14401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (chunk.mTrack == it->mTrack) {  // Found owner
14411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            it->mChunks.push_back(chunk);
14421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.signal();
14431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            return;
14441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
14451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
14461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
144743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK(!"Received a chunk for a unknown track");
14481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
14491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1450fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) {
14513856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeChunkToFile: %lld from %s track",
14525410afcbb0af5d29d9f710a1c2978c500f9792dcPannag Sanketi        chunk->mTimeStampUs, chunk->mTrack->isAudio()? "audio": "video");
1453fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1454fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    int32_t isFirstSample = true;
1455fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    while (!chunk->mSamples.empty()) {
1456fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        List<MediaBuffer *>::iterator it = chunk->mSamples.begin();
1457fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1458fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        off64_t offset = chunk->mTrack->isAvc()
1459fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong                                ? addLengthPrefixedSample_l(*it)
1460fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong                                : addSample_l(*it);
1461fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1462fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (isFirstSample) {
1463fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            chunk->mTrack->addChunkOffset(offset);
1464fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            isFirstSample = false;
14651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
14661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
14671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it)->release();
14681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it) = NULL;
1469fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        chunk->mSamples.erase(it);
14701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1471fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    chunk->mSamples.clear();
14721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
14731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1474fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() {
14753856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeAllChunks");
14761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    size_t outstandingChunks = 0;
147770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    Chunk chunk;
147870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    while (findChunkToWrite(&chunk)) {
1479e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong        writeChunkToFile(&chunk);
148070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        ++outstandingChunks;
14811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
148270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
148370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    sendSessionSummary();
148470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
14851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mChunkInfos.clear();
1486b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("%d chunks are written in the last batch", outstandingChunks);
14871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
14881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1489fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) {
14903856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("findChunkToWrite");
14911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
14921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
14931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Track *track = NULL;
14941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
14951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
14961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (!it->mChunks.empty()) {
14971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            List<Chunk>::iterator chunkIt = it->mChunks.begin();
14981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (chunkIt->mTimeStampUs < minTimestampUs) {
14991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                minTimestampUs = chunkIt->mTimeStampUs;
15001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                track = it->mTrack;
15011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            }
15021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
15031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
15041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
15051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (track == NULL) {
15063856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Nothing to be written after all");
1507fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        return false;
15081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
15091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
15101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mIsFirstChunk) {
15111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsFirstChunk = false;
15121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1513fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
15141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
15151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
15161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it->mTrack == track) {
1517fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            *chunk = *(it->mChunks.begin());
1518fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            it->mChunks.erase(it->mChunks.begin());
1519fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            CHECK_EQ(chunk->mTrack, track);
152070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
152170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t interChunkTimeUs =
152270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                chunk->mTimeStampUs - it->mPrevChunkTimestampUs;
152370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            if (interChunkTimeUs > it->mPrevChunkTimestampUs) {
152470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs = interChunkTimeUs;
152570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            }
152670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
1527fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            return true;
15281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
15291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1530fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1531fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    return false;
15321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
15331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
15341c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() {
15353856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("threadFunc");
15361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1537a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0);
1538fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1539fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    Mutex::Autolock autoLock(mLock);
15401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mDone) {
1541fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        Chunk chunk;
1542fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        bool chunkFound = false;
1543fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1544fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) {
15451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.wait(mLock);
15461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
15471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1548fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        // Actual write without holding the lock in order to
1549fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        // reduce the blocking time for media track threads.
1550fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (chunkFound) {
1551fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            mLock.unlock();
1552fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            writeChunkToFile(&chunk);
1553fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            mLock.lock();
1554fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        }
15551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1556fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1557fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    writeAllChunks();
15581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
15591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
15601c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() {
15613856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("startWriterThread");
15621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
15631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mDone = false;
15641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsFirstChunk = true;
1565e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    mDriftTimeUs = 0;
15661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<Track *>::iterator it = mTracks.begin();
15671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mTracks.end(); ++it) {
15681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        ChunkInfo info;
15691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        info.mTrack = *it;
157070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mPrevChunkTimestampUs = 0;
157170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mMaxInterChunkDurUs = 0;
15721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.push_back(info);
15731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
15741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
15751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_t attr;
15761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_init(&attr);
15771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
15781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_create(&mThread, &attr, ThreadWrapper, this);
15791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_destroy(&attr);
1580411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = true;
15811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
15821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
15831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
15841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
158593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) {
1586a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (!mDone && mPaused) {
1587a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mPaused = false;
1588a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mResumed = true;
1589a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
1590a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
159125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
159293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t startTimeUs;
159319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
159419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        startTimeUs = 0;
159519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
159670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    mStartTimeRealUs = startTimeUs;
159719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
159813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t rotationDegrees;
159913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) {
160013f6284305e4b27395a23db7882d670bdb1bcae1James Dong        mRotation = rotationDegrees;
160113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
160213f6284305e4b27395a23db7882d670bdb1bcae1James Dong
16035b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong    mIsRealTimeRecording = true;
1604e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    {
1605e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        int32_t isNotRealTime;
1606e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        if (params && params->findInt32(kKeyNotRealTime, &isNotRealTime)) {
1607e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            mIsRealTimeRecording = (isNotRealTime == 0);
1608e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
1609e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    }
1610e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
161193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    initTrackingProgressStatus(params);
161293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
1613f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    sp<MetaData> meta = new MetaData;
1614a472613aec322e25891abf5c77bf3f7e3c244920James Dong    if (mIsRealTimeRecording && mOwner->numTracks() > 1) {
1615a472613aec322e25891abf5c77bf3f7e3c244920James Dong        /*
1616a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * This extra delay of accepting incoming audio/video signals
1617a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * helps to align a/v start time at the beginning of a recording
1618a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * session, and it also helps eliminate the "recording" sound for
1619a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * camcorder applications.
1620a472613aec322e25891abf5c77bf3f7e3c244920James Dong         *
162186b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * If client does not set the start time offset, we fall back to
162286b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * use the default initial delay value.
1623a472613aec322e25891abf5c77bf3f7e3c244920James Dong         */
162486b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
162586b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
162686b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
162786b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
162886b7f47aa7482424cf8fd248f1315311919be3b0James Dong        startTimeUs += startTimeOffsetUs;
1629df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("Start time offset: %lld us", startTimeOffsetUs);
1630a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
1631a472613aec322e25891abf5c77bf3f7e3c244920James Dong
1632f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    meta->setInt64(kKeyTime, startTimeUs);
1633a472613aec322e25891abf5c77bf3f7e3c244920James Dong
1634f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    status_t err = mSource->start(meta.get());
163525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
163625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
163725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
163825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
163920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
164020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
164120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
164220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
164320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
164420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
1645eaae38445a340c4857c1c5569475879a728e63b7James Dong    mStarted = true;
1646c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs = 0;
164725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
1648956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mEstimatedTrackSizeBytes = 0;
16491f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mMdatSizeBytes = 0;
165043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mMaxChunkDurationUs = 0;
165120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
165225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
165320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
165425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
165525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
165620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
165720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
165837187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() {
1659a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
166037187916a486504acaf83bea30147eb5fbf46ae5James Dong    return OK;
1661a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
1662a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
166337187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() {
1664b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Stopping %s track", mIsAudio? "Audio": "Video");
1665eaae38445a340c4857c1c5569475879a728e63b7James Dong    if (!mStarted) {
166629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Stop() called but track is not started");
1667eaae38445a340c4857c1c5569475879a728e63b7James Dong        return ERROR_END_OF_STREAM;
1668eaae38445a340c4857c1c5569475879a728e63b7James Dong    }
1669eaae38445a340c4857c1c5569475879a728e63b7James Dong
167020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
167137187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
167220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
167320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = true;
167420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
167520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
167620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
167720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
167837187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = (status_t) dummy;
167937187916a486504acaf83bea30147eb5fbf46ae5James Dong
1680b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Stopping %s track source", mIsAudio? "Audio": "Video");
168137187916a486504acaf83bea30147eb5fbf46ae5James Dong    {
168237187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = mSource->stop();
168337187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK && status != ERROR_END_OF_STREAM) {
168437187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
168537187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
168637187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
168737187916a486504acaf83bea30147eb5fbf46ae5James Dong
1688b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("%s track stopped", mIsAudio? "Audio": "Video");
168937187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
169020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
169120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
169225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
169325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
169425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
169525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
169620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
169720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
169820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
169920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
170037187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = track->threadEntry();
170137187916a486504acaf83bea30147eb5fbf46ae5James Dong    return (void *) err;
170220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
170320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) {
17053856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("getNalUnitType: %d", byte);
17063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // nal_unit_type: 5-bit unsigned integer
17083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *type = (byte & 0x1F);
17093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
17103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t *findNextStartCode(
17123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length) {
17133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17143856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("findNextStartCode: %p %d", data, length);
17153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = length;
17173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4  &&
17183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) {
17193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        --bytesLeft;
17203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
17213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (bytesLeft <= 4) {
17223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft = 0; // Last parameter set
17233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
17243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return &data[length - bytesLeft];
17253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
17263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet(
17283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
17293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17303856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseParamSet");
17313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    CHECK(type == kNalUnitTypeSeqParamSet ||
17323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong          type == kNalUnitTypePicParamSet);
17333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = findNextStartCode(data, length);
17353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *paramSetLen = nextStartCode - data;
17363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (*paramSetLen == 0) {
173729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Param set is malformed, since its length is 0");
17383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return NULL;
17393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
17403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    AVCParamSet paramSet(*paramSetLen, data);
17423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (type == kNalUnitTypeSeqParamSet) {
17433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (*paramSetLen < 4) {
174429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Seq parameter set malformed");
17453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return NULL;
17463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
17473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mSeqParamSets.empty()) {
17483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc = data[1];
17493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileCompatible = data[2];
17503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mLevelIdc = data[3];
17513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
17523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (mProfileIdc != data[1] ||
17533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mProfileCompatible != data[2] ||
17543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mLevelIdc != data[3]) {
175529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Inconsistent profile/level found in seq parameter sets");
17563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return NULL;
17573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
17583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
17593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mSeqParamSets.push_back(paramSet);
17603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    } else {
17613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mPicParamSets.push_back(paramSet);
17623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
17633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return nextStartCode;
17643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
17653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData(
17673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
17683856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("copyAVCCodecSpecificData");
17693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 2 bytes for each of the parameter set length field
17713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // plus the 7 bytes for the header
17723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4 + 7) {
177329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Codec specific data length too short: %d", size);
17743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return ERROR_MALFORMED;
17753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
17763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = size;
17783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificData = malloc(size);
17793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    memcpy(mCodecSpecificData, data, size);
17803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
17813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
17823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData(
17843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
17853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17863856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseAVCCodecSpecificData");
17873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data starts with a start code.
17883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // SPS and PPS are separated with start codes.
17893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Also, SPS must come before PPS
17903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t type = kNalUnitTypeSeqParamSet;
17913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotSps = false;
17923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotPps = false;
17933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *tmp = data;
17943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = data;
17953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = size;
17963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t paramSetLen = 0;
17973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = 0;
17983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
17993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        getNalUnitType(*(tmp + 4), &type);
18003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (type == kNalUnitTypeSeqParamSet) {
18013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (gotPps) {
180229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
18033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
18043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
18053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
18063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotSps = true;
18073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
18083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
18093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else if (type == kNalUnitTypePicParamSet) {
18103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
181129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
18123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
18133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
18143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotPps) {
18153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotPps = true;
18163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
18173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
18183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
181929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Only SPS and PPS Nal units are expected");
18203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
18213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
18223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nextStartCode == NULL) {
18243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
18253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
18263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Move on to find the next parameter set
18283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft -= nextStartCode - tmp;
18293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        tmp = nextStartCode;
18303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mCodecSpecificDataSize += (2 + paramSetLen);
18313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
18323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
18343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of seq parameter sets
18353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nSeqParamSets = mSeqParamSets.size();
18363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets == 0) {
183729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find sequence parameter set");
18383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
18393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
18403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets > 0x1F) {
184229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Too many seq parameter sets (%d) found", nSeqParamSets);
18433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
18443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
18453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
18463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
18483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of pic parameter sets
18493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nPicParamSets = mPicParamSets.size();
18503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets == 0) {
185129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find picture parameter set");
18523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
18533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
18543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets > 0xFF) {
185529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Too many pic parameter sets (%d) found", nPicParamSets);
18563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
18573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
18583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
18591374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME:
18601374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above
18611374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0
18621374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0
18633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
18643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the profiles
18653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // These profiles requires additional parameter set extensions
18663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mProfileIdc == 100 || mProfileIdc == 110 ||
18673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc == 122 || mProfileIdc == 144) {
186829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
18693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return BAD_VALUE;
18703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
18713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
18721374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif
18733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
18743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
1875548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
187603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
187703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
1878548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
187903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
188029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Already have codec specific data");
188103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
188203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
188303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
18843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4) {
188529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Codec specific data length too short: %d", size);
188603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
188703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
188803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
18893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data is in the form of AVCCodecSpecificData
18903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (memcmp("\x00\x00\x00\x01", data, 4)) {
18913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return copyAVCCodecSpecificData(data, size);
189203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
189303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
18943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (parseAVCCodecSpecificData(data, size) != OK) {
189503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
189603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
189703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
18983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // ISO 14496-15: AVC file format
18993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize += 7;  // 7 more bytes in the header
190003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
190103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
19023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = 1;                     // version
19033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[1] = mProfileIdc;           // profile indication
19043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[2] = mProfileCompatible;    // profile compatibility
19053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[3] = mLevelIdc;
190603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
19073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
1908b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mOwner->useNalLengthFour()) {
1909b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 3;  // length size == 4 bytes
1910b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
1911b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 1;  // length size == 2 bytes
1912b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
191303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
19143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 3-bit '111' followed by 5-bit numSequenceParameterSets
19153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nSequenceParamSets = mSeqParamSets.size();
19163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[5] = 0xe0 | nSequenceParamSets;
19173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 6;
19183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
19193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mSeqParamSets.end(); ++it) {
19203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit sequence parameter set length
19213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t seqParamSetLength = it->mLength;
19223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = seqParamSetLength >> 8;
19233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = seqParamSetLength & 0xff;
19243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // SPS NAL unit (sequence parameter length bytes)
19263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, seqParamSetLength);
19273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + seqParamSetLength);
19283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
19293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 8-bit nPictureParameterSets
19313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nPictureParamSets = mPicParamSets.size();
19323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = nPictureParamSets;
19333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 1;
19343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
19353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mPicParamSets.end(); ++it) {
19363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit picture parameter set length
19373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t picParamSetLength = it->mLength;
19383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = picParamSetLength >> 8;
19393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = picParamSetLength & 0xff;
19403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // PPS Nal unit (picture parameter set length bytes)
19423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, picParamSetLength);
19433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + picParamSetLength);
19443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
194503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
194603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
194703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
194803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1949872a481558350634a3fd5cb67939de288af00ecbJames Dong/*
1950872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that
1951872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information
1952872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio
1953872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger
1954872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5,
1955872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined.
1956872a481558350634a3fd5cb67939de288af00ecbJames Dong */
1957872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) {
1958872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t driftTimeUs = 0;
1959872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) {
1960872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t prevDriftTimeUs = mOwner->getDriftTimeUs();
1961872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1;
1962872a481558350634a3fd5cb67939de288af00ecbJames Dong        mOwner->setDriftTimeUs(timeUs);
1963872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
1964872a481558350634a3fd5cb67939de288af00ecbJames Dong}
1965872a481558350634a3fd5cb67939de288af00ecbJames Dong
196637187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() {
196730ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
196813aec890216948b0c364f8f92792129d0335f506James Dong    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
196943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    const bool hasMultipleTracks = (mOwner->numTracks() > 1);
197013aec890216948b0c364f8f92792129d0335f506James Dong    int64_t chunkTimestampUs = 0;
197113aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nChunks = 0;
197213aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nZeroLengthFrames = 0;
1973965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastTimestampUs = 0;      // Previous sample time stamp
1974965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationUs = 0;       // Between the previous two samples
1975965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t currDurationTicks = 0;    // Timescale based ticks
1976965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationTicks = 0;    // Timescale based ticks
1977965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int32_t sampleCount = 1;          // Sample count in the current stts table entry
1978000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    uint32_t previousSampleSize = 0;  // Size of the previous sample
1979a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t previousPausedDurationUs = 0;
1980965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t timestampUs = 0;
1981000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t cttsOffsetTimeUs = 0;
1982000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t currCttsOffsetTimeTicks = 0;   // Timescale based ticks
1983000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t lastCttsOffsetTimeTicks = -1;  // Timescale based ticks
198443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    int32_t cttsSampleCount = 0;           // Sample count in the current ctts table entry
1985c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t lastSamplesPerChunk = 0;
1986e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
1987a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    if (mIsAudio) {
1988a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
1989a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    } else {
1990a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
1991a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    }
199286106f8b0641444c97a39e9788eeef55ab2a2ac6Glenn Kasten    androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
1993985f838934510983d8a887461e98dca60a6e858fJames Dong
1994d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong    sp<MetaData> meta_data;
199520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
199693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t err = OK;
199720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
199893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    while (!mDone && (err = mSource->read(&buffer)) == OK) {
199920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
200020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
200120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
200213aec890216948b0c364f8f92792129d0335f506James Dong            ++nZeroLengthFrames;
200320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
200420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
200520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2006a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // If the codec specific data has not been received yet, delay pause.
2007a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // After the codec specific data is received, discard what we received
2008a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // when the track is to be paused.
2009a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused && !mResumed) {
2010a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer->release();
2011a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer = NULL;
2012a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            continue;
2013a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2014a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
201530ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
201630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
201703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
201803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
201903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
2020548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            CHECK(!mGotAllCodecSpecificData);
2021548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
20221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (mIsAvc) {
202303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                status_t err = makeAVCCodecSpecificData(
202403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
202503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
202603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        buffer->range_length());
202743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                CHECK_EQ((status_t)OK, err);
20281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            } else if (mIsMPEG4) {
202903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificDataSize = buffer->range_length();
203003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificData = malloc(mCodecSpecificDataSize);
203103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                memcpy(mCodecSpecificData,
203203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
203303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
203403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                       buffer->range_length());
203530ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
203630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
203730ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
203830ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
203930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
2040548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
204130ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
2042a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2043a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2044d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // Make a deep copy of the MediaBuffer and Metadata and release
2045d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // the original as soon as we can
2046d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
2047d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
2048d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                buffer->range_length());
2049d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        copy->set_range(0, buffer->range_length());
2050d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data = new MetaData(*buffer->meta_data().get());
2051d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer->release();
2052d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer = NULL;
2053d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
20541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (mIsAvc) StripStartcode(copy);
2055e136c3bb38e88315bf8797a464ebf2c788296b22James Dong
2056b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        size_t sampleSize = copy->range_length();
2057b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        if (mIsAvc) {
2058b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            if (mOwner->useNalLengthFour()) {
2059b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 4;
2060b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            } else {
2061b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 2;
2062b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            }
2063b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        }
2064050b28a593350047845a45a14cc5026221ac1620James Dong
2065d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        // Max file size or duration handling
20661f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mMdatSizeBytes += sampleSize;
20671f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        updateTrackSizeEstimate();
20681f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
2069d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileSizeLimit()) {
2070d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
2071d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2072d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2073d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileDurationLimit()) {
2074d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
2075d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2076d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2077d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2078050b28a593350047845a45a14cc5026221ac1620James Dong
2079d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        int32_t isSync = false;
2080d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
2081d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
2082d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
2083d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong////////////////////////////////////////////////////////////////////////////////
2084c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (mStszTableEntries->count() == 0) {
208570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mFirstSampleTimeRealUs = systemTime() / 1000;
2086f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimestampUs = timestampUs;
2087f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mOwner->setStartTimestampUs(mStartTimestampUs);
20888428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs = mStartTimestampUs;
20893c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        }
209048c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
2091a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mResumed) {
20928428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
209343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            CHECK_GE(durExcludingEarlierPausesUs, 0ll);
20948428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
209543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            CHECK_GE(pausedDurationUs, lastDurationUs);
20968428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs += pausedDurationUs - lastDurationUs;
2097a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mResumed = false;
2098a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2099a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2100a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        timestampUs -= previousPausedDurationUs;
210143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_GE(timestampUs, 0ll);
2102000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        if (!mIsAudio) {
2103965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            /*
2104965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Composition time: timestampUs
2105965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Decoding time: decodingTimeUs
2106000e18370baae60ffd9f25b509501dd8c26deabfJames Dong             * Composition time offset = composition time - decoding time
2107965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             */
2108965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            int64_t decodingTimeUs;
2109965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
2110965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            decodingTimeUs -= previousPausedDurationUs;
2111000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            cttsOffsetTimeUs =
2112000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
211343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            CHECK_GE(cttsOffsetTimeUs, 0ll);
2114965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            timestampUs = decodingTimeUs;
2115000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            ALOGV("decoding time: %lld and ctts offset time: %lld",
2116000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                timestampUs, cttsOffsetTimeUs);
2117000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2118000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts box table if necessary
2119000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            currCttsOffsetTimeTicks =
2120000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL;
212143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            CHECK_LE(currCttsOffsetTimeTicks, 0x0FFFFFFFFLL);
2122c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 0) {
212343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // Force the first ctts table entry to have one single entry
212443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // so that we can do adjustment for the initial track start
212543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // time offset easily in writeCttsBox().
212643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
212743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                addOneCttsTableEntry(1, currCttsOffsetTimeTicks);
212843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                cttsSampleCount = 0;      // No sample in ctts box is pending
212943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            } else {
213043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) {
213143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
213243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
213343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    cttsSampleCount = 1;  // One sample in ctts box is pending
213443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                } else {
213543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    ++cttsSampleCount;
213643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                }
213743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            }
2138000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2139000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts time offset range
2140c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 0) {
2141000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2142000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2143000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            } else {
2144000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) {
2145000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2146000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) {
2147000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2148000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                }
2149000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            }
2150000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2151965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        }
2152872a481558350634a3fd5cb67939de288af00ecbJames Dong
2153872a481558350634a3fd5cb67939de288af00ecbJames Dong        if (mIsRealTimeRecording) {
2154872a481558350634a3fd5cb67939de288af00ecbJames Dong            if (mIsAudio) {
2155872a481558350634a3fd5cb67939de288af00ecbJames Dong                updateDriftTime(meta_data);
2156e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
2157e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
2158872a481558350634a3fd5cb67939de288af00ecbJames Dong
215943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_GE(timestampUs, 0ll);
21603856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("%s media time stamp: %lld and previous paused duration %lld",
21618428af5381e835cc783b7ecb0d71cb60961c99c2James Dong                mIsAudio? "Audio": "Video", timestampUs, previousPausedDurationUs);
2162c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong        if (timestampUs > mTrackDurationUs) {
2163c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong            mTrackDurationUs = timestampUs;
21643b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        }
21653b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber
21665a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // We need to use the time scale based ticks, rather than the
21675a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // timestamp itself to determine whether we have to use a new
21685a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // stts entry, since we may have rounding errors.
21695a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // The calculation is intended to reduce the accumulated
21705a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // rounding errors.
21715a217fba010e801c255503602bda4b86ac5a6ac9James Dong        currDurationTicks =
21725a217fba010e801c255503602bda4b86ac5a6ac9James Dong            ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
21735a217fba010e801c255503602bda4b86ac5a6ac9James Dong                (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
2174c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (currDurationTicks < 0ll) {
2175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            ALOGE("timestampUs %lld < lastTimestampUs %lld for %s track",
2176c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                timestampUs, lastTimestampUs, mIsAudio? "Audio": "Video");
2177c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            return UNKNOWN_ERROR;
21788c460498c028888c533ab442be12b6d4b669b965James Dong        }
21798c460498c028888c533ab442be12b6d4b669b965James Dong
2180c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStszTableEntries->add(htonl(sampleSize));
2181c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (mStszTableEntries->count() > 2) {
2182c059860c73678a202bfa33062723e8f82fb779d9James Dong
2183a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // Force the first sample to have its own stts entry so that
2184a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // we can adjust its value later to maintain the A/V sync.
2185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) {
218679761ab096f57c3027fad9556c2bc436672d614eJames Dong                addOneSttsTableEntry(sampleCount, lastDurationTicks);
2187be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                sampleCount = 1;
2188be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
2189be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                ++sampleCount;
2190be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
2191965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2192be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
2193be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        if (mSamplesHaveSameSize) {
2194c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) {
2195be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSamplesHaveSameSize = false;
2196be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
21978644c14618d30d9e57a69df40ed939986ebf02c4James Dong            previousSampleSize = sampleSize;
2198be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
21993856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("%s timestampUs/lastTimestampUs: %lld/%lld",
2200a472613aec322e25891abf5c77bf3f7e3c244920James Dong                mIsAudio? "Audio": "Video", timestampUs, lastTimestampUs);
22018644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastDurationUs = timestampUs - lastTimestampUs;
2202c059860c73678a202bfa33062723e8f82fb779d9James Dong        lastDurationTicks = currDurationTicks;
22038644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastTimestampUs = timestampUs;
220420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2205d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        if (isSync != 0) {
2206c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            addOneStssTableEntry(mStszTableEntries->count());
2207d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        }
2208d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
220993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (mTrackingProgressStatus) {
221093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            if (mPreviousTrackTimeUs <= 0) {
221193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong                mPreviousTrackTimeUs = mStartTimestampUs;
221293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            }
2213faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong            trackProgressStatus(timestampUs);
221493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
221543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        if (!hasMultipleTracks) {
2216c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy)
221758ae9c530247668f8af36e30d228c716c226b3d4James Dong                                 : mOwner->addSample_l(copy);
2218c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2219c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t count = (mOwner->use32BitFileOffset()
2220c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        ? mStcoTableEntries->count()
2221c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        : mCo64TableEntries->count());
2222c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2223c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (count == 0) {
22241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                addChunkOffset(offset);
222558ae9c530247668f8af36e30d228c716c226b3d4James Dong            }
222658ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy->release();
222758ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy = NULL;
222858ae9c530247668f8af36e30d228c716c226b3d4James Dong            continue;
222958ae9c530247668f8af36e30d228c716c226b3d4James Dong        }
223013aec890216948b0c364f8f92792129d0335f506James Dong
223113aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.push_back(copy);
223213aec890216948b0c364f8f92792129d0335f506James Dong        if (interleaveDurationUs == 0) {
22331f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStscTableEntry(++nChunks, 1);
22341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            bufferChunk(timestampUs);
223513aec890216948b0c364f8f92792129d0335f506James Dong        } else {
223613aec890216948b0c364f8f92792129d0335f506James Dong            if (chunkTimestampUs == 0) {
223713aec890216948b0c364f8f92792129d0335f506James Dong                chunkTimestampUs = timestampUs;
223813aec890216948b0c364f8f92792129d0335f506James Dong            } else {
223943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                int64_t chunkDurationUs = timestampUs - chunkTimestampUs;
224043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                if (chunkDurationUs > interleaveDurationUs) {
224143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    if (chunkDurationUs > mMaxChunkDurationUs) {
224243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                        mMaxChunkDurationUs = chunkDurationUs;
224343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    }
224413aec890216948b0c364f8f92792129d0335f506James Dong                    ++nChunks;
224513aec890216948b0c364f8f92792129d0335f506James Dong                    if (nChunks == 1 ||  // First chunk
2246c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk != mChunkSamples.size()) {
2247c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk = mChunkSamples.size();
2248c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        addOneStscTableEntry(nChunks, lastSamplesPerChunk);
224913aec890216948b0c364f8f92792129d0335f506James Dong                    }
22501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                    bufferChunk(timestampUs);
225113aec890216948b0c364f8f92792129d0335f506James Dong                    chunkTimestampUs = timestampUs;
225213aec890216948b0c364f8f92792129d0335f506James Dong                }
225313aec890216948b0c364f8f92792129d0335f506James Dong            }
225413aec890216948b0c364f8f92792129d0335f506James Dong        }
225513aec890216948b0c364f8f92792129d0335f506James Dong
225620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
225725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
225845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (isTrackMalFormed()) {
2259690f546b0ee548dbfe997df36418e5302ec2d786James Dong        err = ERROR_MALFORMED;
2260f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    }
226145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
2262bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    mOwner->trackProgressStatus(mTrackId, -1, err);
2263be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
226413aec890216948b0c364f8f92792129d0335f506James Dong    // Last chunk
226543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (!hasMultipleTracks) {
2266c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        addOneStscTableEntry(1, mStszTableEntries->count());
226758ae9c530247668f8af36e30d228c716c226b3d4James Dong    } else if (!mChunkSamples.empty()) {
22681f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        addOneStscTableEntry(++nChunks, mChunkSamples.size());
22691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        bufferChunk(timestampUs);
227013aec890216948b0c364f8f92792129d0335f506James Dong    }
227113aec890216948b0c364f8f92792129d0335f506James Dong
2272be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // We don't really know how long the last frame lasts, since
2273be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // there is no frame time after it, just repeat the previous
2274be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // frame's duration.
2275c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() == 1) {
22768f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        lastDurationUs = 0;  // A single sample's duration
227779761ab096f57c3027fad9556c2bc436672d614eJames Dong        lastDurationTicks = 0;
2278be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    } else {
2279be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        ++sampleCount;  // Count for the last sample
2280be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    }
2281a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2282c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() <= 2) {
228379761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(1, lastDurationTicks);
2284a472613aec322e25891abf5c77bf3f7e3c244920James Dong        if (sampleCount - 1 > 0) {
228579761ab096f57c3027fad9556c2bc436672d614eJames Dong            addOneSttsTableEntry(sampleCount - 1, lastDurationTicks);
2286a472613aec322e25891abf5c77bf3f7e3c244920James Dong        }
2287a472613aec322e25891abf5c77bf3f7e3c244920James Dong    } else {
228879761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(sampleCount, lastDurationTicks);
2289a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
2290a472613aec322e25891abf5c77bf3f7e3c244920James Dong
229143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // The last ctts box may not have been written yet, and this
229243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // is to make sure that we write out the last ctts box.
229343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) {
229443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        if (cttsSampleCount > 0) {
229543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
229643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        }
229743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    }
229843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong
2299c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs += lastDurationUs;
230025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
230143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
230243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    sendTrackSummary(hasMultipleTracks);
230343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
2304df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
2305c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            count, nZeroLengthFrames, mStszTableEntries->count(), mIsAudio? "audio": "video");
2306872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (mIsAudio) {
2307df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("Audio track drift time: %lld us", mOwner->getDriftTimeUs());
2308872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2309365a963142093a1cd8efdcea76b5f65096a5b115James Dong
231037187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err == ERROR_END_OF_STREAM) {
231137187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
231237187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
231337187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
2314365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
2315365a963142093a1cd8efdcea76b5f65096a5b115James Dong
231645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const {
2317c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() == 0) {                      // no samples written
231829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("The number of recorded samples is 0");
231945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
232045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
232145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
2322c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (!mIsAudio && mStssTableEntries->count() == 0) {  // no sync frames for video
232329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("There are no sync frames for video track");
232445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
232545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
232645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
232745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (OK != checkCodecSpecificData()) {         // no codec specific data
232845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
232945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
233045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
233145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    return false;
233245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong}
233345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
233443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) {
233507ec01904613a0bac32caaa8444b4690998faed7James Dong
233607ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send track summary only if test mode is enabled.
233707ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
233807ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
233907ec01904613a0bac32caaa8444b4690998faed7James Dong    }
234007ec01904613a0bac32caaa8444b4690998faed7James Dong
234143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int trackNum = (mTrackId << 28);
234243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
234343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
234443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE,
234543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mIsAudio? 0: 1);
234643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
234743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
234843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS,
234943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mTrackDurationUs / 1000);
235043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
235143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
235243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES,
2353c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    mStszTableEntries->count());
235443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
235586b7f47aa7482424cf8fd248f1315311919be3b0James Dong    {
235686b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // The system delay time excluding the requested initial delay that
235786b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // is used to eliminate the recording sound.
235886b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
235986b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
236086b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
236186b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
236286b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t initialDelayUs =
236386b7f47aa7482424cf8fd248f1315311919be3b0James Dong            mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs;
236486b7f47aa7482424cf8fd248f1315311919be3b0James Dong
236586b7f47aa7482424cf8fd248f1315311919be3b0James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
236670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS,
236770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    (initialDelayUs) / 1000);
236886b7f47aa7482424cf8fd248f1315311919be3b0James Dong    }
236970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
237007ec01904613a0bac32caaa8444b4690998faed7James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
237107ec01904613a0bac32caaa8444b4690998faed7James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES,
237207ec01904613a0bac32caaa8444b4690998faed7James Dong                    mMdatSizeBytes / 1024);
237307ec01904613a0bac32caaa8444b4690998faed7James Dong
237443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (hasMultipleTracks) {
237543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
237643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS,
237743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mMaxChunkDurationUs / 1000);
237870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
237970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
238070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        if (mStartTimestampUs != moovStartTimeUs) {
238170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
238270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
238370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS,
238470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    startTimeOffsetUs / 1000);
238570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        }
238643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    }
238743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong}
238843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
2389faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
23903856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("trackProgressStatus: %lld us", timeUs);
2391c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2392215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    if (mTrackEveryTimeDurationUs > 0 &&
2393215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
23943856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Fire time tracking progress status at %lld us", timeUs);
2395bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err);
239693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        mPreviousTrackTimeUs = timeUs;
239793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
239893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
239993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
2400faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus(
2401bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        size_t trackId, int64_t timeUs, status_t err) {
2402faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    Mutex::Autolock lock(mLock);
2403bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t trackNum = (trackId << 28);
2404faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2405faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Error notification
2406faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Do not consider ERROR_END_OF_STREAM an error
2407faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (err != OK && err != ERROR_END_OF_STREAM) {
2408bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
2409bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL,
2410faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2411faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
2412faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2413faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2414faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (timeUs == -1) {
2415faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send completion notification
2416bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2417bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS,
2418faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2419faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    } else {
2420faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send progress status
2421bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2422bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME,
2423faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               timeUs / 1000);
2424faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2425faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong}
2426faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2427d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) {
24283856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setDriftTimeUs: %lld us", driftTimeUs);
2429e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2430d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    mDriftTimeUs = driftTimeUs;
2431e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2432e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2433e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() {
24343856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("getDriftTimeUs: %lld us", mDriftTimeUs);
2435e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2436e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    return mDriftTimeUs;
2437e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2438e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2439b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() {
2440b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    return mUse4ByteNalLength;
2441b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong}
2442b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
24431c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
24443856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk");
24451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
24461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Chunk chunk(this, timestampUs, mChunkSamples);
24471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mOwner->bufferChunk(chunk);
244813aec890216948b0c364f8f92792129d0335f506James Dong    mChunkSamples.clear();
244920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
245020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24513b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
2452c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    return mTrackDurationUs;
245320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
245420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2455d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
2456d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return mEstimatedTrackSizeBytes;
2457d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
2458d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2459690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const {
2460690f546b0ee548dbfe997df36418e5302ec2d786James Dong    const char *mime;
2461690f546b0ee548dbfe997df36418e5302ec2d786James Dong    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
2462690f546b0ee548dbfe997df36418e5302ec2d786James Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
2463690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
2464690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2465690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (!mCodecSpecificData ||
2466690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize <= 0) {
246729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Missing codec specific data");
2468690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2469690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2470690f546b0ee548dbfe997df36418e5302ec2d786James Dong    } else {
2471690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (mCodecSpecificData ||
2472690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize > 0) {
247329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Unexepected codec specific data found");
2474690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2475690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2476690f546b0ee548dbfe997df36418e5302ec2d786James Dong    }
2477690f546b0ee548dbfe997df36418e5302ec2d786James Dong    return OK;
2478690f546b0ee548dbfe997df36418e5302ec2d786James Dong}
2479690f546b0ee548dbfe997df36418e5302ec2d786James Dong
2480b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) {
248120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24823856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("%s track time scale: %d",
24831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsAudio? "Audio": "Video", mTimeScale);
24848f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
2485efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
2486b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("trak");
2487b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeTkhdBox(now);
2488b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("mdia");
2489b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeMdhdBox(now);
2490b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeHdlrBox();
2491b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->beginBox("minf");
2492b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                if (mIsAudio) {
2493b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeSmhdBox();
2494b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                } else {
2495b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeVmhdBox();
2496b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                }
2497b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeDinfBox();
2498b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeStblBox(use32BitOffset);
2499b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->endBox();  // minf
2500b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->endBox();  // mdia
2501b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // trak
2502b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2503b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2504b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) {
2505b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stbl");
2506b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsd");
2507b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);               // version=0, flags=0
2508b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);               // entry count
2509b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
2510b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAudioFourCCBox();
2511b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
2512b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeVideoFourCCBox();
2513b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2514b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsd
2515b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeSttsBox();
2516965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    writeCttsBox();
2517b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!mIsAudio) {
2518b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeStssBox();
2519b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2520b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStszBox();
2521b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStscBox();
2522b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStcoBox(use32BitOffset);
2523b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stbl
2524b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2525b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2526b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() {
2527b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
2528b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
2529b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2530b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
2531b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("mp4v");
2532b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
2533b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("s263");
2534b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2535b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("avc1");
2536b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
253729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
2538b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(!"should not be here, unknown mime type.");
2539b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2540b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2541b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2542b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2543b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // data ref index
2544b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
2545b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2546b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2547b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2548b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2549b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2550b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t width, height;
2551b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeyWidth, &width);
2552b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = success && mMeta->findInt32(kKeyHeight, &height);
2553b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2554b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2555b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(width);
2556b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(height);
2557b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // horiz resolution
2558b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // vert resolution
2559b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2560b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // frame count
2561b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write("                                ", 32);
2562b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x18);        // depth
2563b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(-1);          // predefined
2564b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
256543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_LT(23 + mCodecSpecificDataSize, 128);
2566b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2567b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
2568b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4vEsdsBox();
2569b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
2570b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeD263Box();
2571b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2572b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAvccBox();
2573b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2574b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2575b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writePaspBox();
2576b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // mp4v, s263 or avc1
2577b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2578b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2579b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() {
2580b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
2581b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
2582b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2583b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *fourcc = NULL;
2584b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
2585b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fourcc = "samr";
2586b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
2587b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fourcc = "sawb";
2588b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
2589b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fourcc = "mp4a";
2590b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
259129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
2592b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(!"should not be here, unknown mime type.");
2593b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2594b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2595b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(fourcc);        // audio format
2596b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2597b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2598b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x1);         // data ref index
2599b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2600b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2601b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t nChannels;
2602b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
2603b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(nChannels);   // channel count
2604b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(16);          // sample size
2605b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
2606b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2607b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2608b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t samplerate;
2609b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeySampleRate, &samplerate);
2610b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2611b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(samplerate << 16);
2612b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
2613b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4aEsdsBox();
2614b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
2615b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong               !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
2616b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeDamrBox();
2617b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2618b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2619b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2620b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2621b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() {
2622b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
2623b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
262443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mCodecSpecificDataSize, 0);
2625b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2626b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Make sure all sizes encode to a single byte.
262743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_LT(mCodecSpecificDataSize + 23, 128);
2628b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2629b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);     // version=0, flags=0
2630b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);   // ES_DescrTag
2631b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
2632b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);// ES_ID
2633b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x00);
2634b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2635b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
2636b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
2637b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
2638b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x15);   // streamType AudioStream
2639b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2640b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x03);  // XXX
2641b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x00);   // buffer size 24-bit
2642b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(96000); // max bit rate
2643b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(96000); // avg bit rate
2644b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2645b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
2646b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
2647b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2648b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2649b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
2650b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
2651b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
2652b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
2653b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
2654b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
2655b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2656b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
2657b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2658b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2659b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() {
2660b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
266143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mCodecSpecificDataSize, 0);
2662b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
2663b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2664b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);    // version=0, flags=0
2665b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2666b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);  // ES_DescrTag
2667b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
2668b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);  // ES_ID
2669b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x1f);
2670b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2671b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
2672b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
2673b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
2674b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x11);  // streamType VisualStream
2675b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2676b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData[] = {
2677b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01, 0x77, 0x00,
2678b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x00, 0x03, 0xe8, 0x00,
2679b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x00, 0x03, 0xe8, 0x00
2680b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
2681b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData, sizeof(kData));
2682b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2683b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
2684b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2685b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
2686b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2687b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2688b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
2689b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
2690b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
2691b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
2692b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
2693b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
2694b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2695b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
2696b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2697b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2698efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeTkhdBox(uint32_t now) {
2699b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("tkhd");
2700b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Flags = 7 to indicate that the track is enabled, and
2701b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // part of the presentation
2702b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x07);          // version=0, flags=7
2703b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
2704b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
2705219f195159f93d627af2b243732e3f9020511a46James Dong    mOwner->writeInt32(mTrackId);      // track id starts with 1
2706b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
27078f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t trakDurationUs = getDurationUs();
2708b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mvhdTimeScale = mOwner->getTimeScale();
2709b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t tkhdDuration =
2710b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
2711b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
2712b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2713b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2714b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // layer
2715b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // alternate group
2716b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
2717b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // reserved
2718b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2719b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCompositionMatrix(mRotation);       // matrix
272020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2721b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
2722b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
2723b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
2724b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
2725b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        int32_t width, height;
2726b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        bool success = mMeta->findInt32(kKeyWidth, &width);
2727b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        success = success && mMeta->findInt32(kKeyHeight, &height);
2728b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(success);
2729b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2730b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
2731b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
2732b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2733b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // tkhd
2734b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2735b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2736b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() {
2737b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("vmhd");
2738b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x01);        // version=0, flags=1
2739b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // graphics mode
2740b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // opcolor
2741b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
2742b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
2743b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2744b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2745b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2746b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() {
2747b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("smhd");
2748b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // version=0, flags=0
2749b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // balance
2750b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2751b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2752b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2753b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2754b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() {
2755b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("hdlr");
2756b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
2757b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // component type: should be mhlr
2758b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeFourcc(mIsAudio ? "soun" : "vide");  // component subtype
2759b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2760b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2761b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2762b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Removing "r" for the name string just makes the string 4 byte aligned
2763b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle");  // name
2764b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2765b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2766b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2767efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeMdhdBox(uint32_t now) {
2768b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t trakDurationUs = getDurationUs();
2769b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("mdhd");
2770b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
2771b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
2772b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
2773b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mTimeScale);    // media timescale
2774b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
2775b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mdhdDuration);  // use media timescale
2776b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Language follows the three letter standard ISO-639-2/T
2777b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 'e', 'n', 'g' for "English", for instance.
2778b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Each character is packed as the difference between its ASCII value and 0x60.
2779b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // For "English", these are 00101, 01110, 00111.
2780b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // XXX: Where is the padding bit located: 0x15C7?
2781b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // language code
2782b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // predefined
2783b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2784b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2785b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2786b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() {
2787b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 3gpp2 Spec AMRSampleEntry fields
2788b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("damr");
2789b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString("   ");  // vendor: 4 bytes
2790b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // decoder version
2791b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x83FF);   // mode set: all enabled
2792b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // mode change period
2793b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(1);         // frames per sample
2794b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2795b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2796b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2797b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() {
2798b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // The table index here refers to the sample description index
2799b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // in the sample table entries.
2800b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("url ");
2801b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
2802b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // url
2803b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2804b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2805b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() {
2806b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dref");
2807b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2808b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // entry count (either url or urn)
2809b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeUrlBox();
2810b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dref
2811b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2812b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2813b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() {
2814b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dinf");
2815b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeDrefBox();
2816b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dinf
2817b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2818b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2819b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() {
2820b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
282143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(mCodecSpecificDataSize, 5);
2822b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2823b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Patch avcc's lengthSize field to match the number
2824b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // of bytes we use to indicate the size of a nal unit.
2825b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
2826b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
2827b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("avcC");
2828b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2829b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // avcC
2830b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2831b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2832b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() {
2833b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("d263");
2834b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // vendor
2835b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // decoder version
2836b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(10);  // level: 10
2837b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // profile: 0
2838b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // d263
2839b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2840b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2841b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square
2842b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() {
2843b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("pasp");
2844b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // hspacing
2845b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // vspacing
2846b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // pasp
2847b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2848b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2849000e18370baae60ffd9f25b509501dd8c26deabfJames Dongint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const {
2850a472613aec322e25891abf5c77bf3f7e3c244920James Dong    int64_t trackStartTimeOffsetUs = 0;
2851b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
2852b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mStartTimestampUs != moovStartTimeUs) {
285343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_GT(mStartTimestampUs, moovStartTimeUs);
2854b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
2855b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2856000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    return (trackStartTimeOffsetUs *  mTimeScale + 500000LL) / 1000000LL;
2857000e18370baae60ffd9f25b509501dd8c26deabfJames Dong}
2858000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2859000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() {
2860000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->beginBox("stts");
2861000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2862c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t duration;
2863c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    CHECK(mSttsTableEntries->get(duration, 1));
2864c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    duration = htonl(duration);  // Back to host byte order
2865c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1);
2866c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->write(mOwner);
2867b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stts
2868b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
286920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2870965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() {
2871965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if (mIsAudio) {  // ctts is not for audio
2872965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
2873965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
2874965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2875000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    // There is no B frame at all
2876000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) {
2877000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        return;
2878000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    }
2879000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2880965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    // Do not write ctts box when there is no need to have it.
2881c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mCttsTableEntries->count() == 0) {
2882965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
2883965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
2884965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2885c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ALOGV("ctts box has %d entries with range [%lld, %lld]",
2886c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs);
2887965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2888965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->beginBox("ctts");
2889000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2890c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t duration;
2891c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    CHECK(mCttsTableEntries->get(duration, 1));
2892c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    duration = htonl(duration);  // Back host byte order
2893c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime() - mMinCttsOffsetTimeUs), 1);
2894c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->write(mOwner);
2895965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->endBox();  // ctts
2896965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
2897965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2898b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() {
2899b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stss");
2900b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2901c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->write(mOwner);
2902b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stss
2903b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
290425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
2905b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() {
2906b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsz");
2907b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2908c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mOwner->writeInt32(0);
2909c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries->write(mOwner);
2910b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsz
2911b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
291220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2913b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() {
2914b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsc");
2915b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2916c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries->write(mOwner);
2917b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsc
2918b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
291920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2920b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) {
2921b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(use32BitOffset? "stco": "co64");
2922b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2923c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (use32BitOffset) {
2924c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->write(mOwner);
2925c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
2926c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->write(mOwner);
2927b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2928b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stco or co64
292920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
293020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
293107b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() {
293207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("udta");
293307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeGeoDataBox();
293407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
293507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
293607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
293707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
293807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
293907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
294007b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() {
294107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("\xA9xyz");
294207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    /*
294307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * For historical reasons, any user data start
294407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * with "\0xA9", must be followed by its assoicated
294507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * language code.
2946432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x0012: text string length
2947432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x15c7: lang (locale) code: en
294807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     */
294907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt32(0x001215c7);
295007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLatitude(mLatitudex10000);
295107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLongitude(mLongitudex10000);
295207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt8(0x2F);
295307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
295407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
295507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
295620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
2957