MPEG4Writer.cpp revision d24affe100fb9ebcdabef47068e7a0f728a3a44e
120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber/*
220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Copyright (C) 2009 The Android Open Source Project
320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * you may not use this file except in compliance with the License.
620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * You may obtain a copy of the License at
720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
1020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Unless required by applicable law or agreed to in writing, software
1120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * See the License for the specific language governing permissions and
1420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * limitations under the License.
1520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber */
1620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17050b28a593350047845a45a14cc5026221ac1620James Dong//#define LOG_NDEBUG 0
18050b28a593350047845a45a14cc5026221ac1620James Dong#define LOG_TAG "MPEG4Writer"
19050b28a593350047845a45a14cc5026221ac1620James Dong
20826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar#include <algorithm>
21826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar
2220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <arpa/inet.h>
23a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <fcntl.h>
24a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <inttypes.h>
2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <pthread.h>
26a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong#include <sys/prctl.h>
27a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <sys/stat.h>
28a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <sys/types.h>
29a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <unistd.h>
30a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn
31a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <utils/Log.h>
3220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar#include <functional>
34c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar
3543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong#include <media/stagefright/foundation/ADebug.h>
36e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang#include <media/stagefright/foundation/AMessage.h>
37826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar#include <media/stagefright/foundation/AUtils.h>
3858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar#include <media/stagefright/foundation/ColorUtils.h>
3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h>
4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h>
4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
4218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
4303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#include <media/stagefright/MediaErrors.h>
4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h>
4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h>
46d599cd4573b5a2d5914c5040e0565ef866749b77James Dong#include <media/mediarecorder.h>
4707ec01904613a0bac32caaa8444b4690998faed7James Dong#include <cutils/properties.h>
4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber#include "include/ESDS.h"
509aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim#include "include/HevcUtils.h"
5180f78b773f92048944a850efb7b60629643370cdPraveen Chavan#include "include/avc_utils.h"
52dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn
53dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#ifndef __predict_false
54dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#define __predict_false(exp) __builtin_expect((exp) != 0, 0)
55dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#endif
56dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn
5711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih#define WARN_UNLESS(condition, message, ...) \
58dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn( (__predict_false(condition)) ? false : ({ \
5911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih    ALOGW("Condition %s failed "  message, #condition, ##__VA_ARGS__); \
6011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih    true; \
6111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih}))
6211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
6320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6577e8ae9967a078770416619e99ddb5b010def312James Dongstatic const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024;
661f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachadstatic const int64_t kMax32BitFileSize = 0x00ffffffffLL; // 2^32-1 : max FAT32
671f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad                                                         // filesystem file size
681f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad                                                         // used by most SD cards
693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypeSeqParamSet = 0x07;
703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypePicParamSet = 0x08;
7170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongstatic const int64_t kInitialDelayTimeUs     = 700000LL;
725b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong
737c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Version[]    = "com.android.version";
743b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnar#ifdef SHOW_MODEL_BUILD
753b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnarstatic const char kMetaKey_Model[]      = "com.android.model";
767c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Build[]      = "com.android.build";
773b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnar#endif
787c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_CaptureFps[] = "com.android.capture.fps";
794dbff11975e737482537e1636051690188f3fbc4Praveen Chavanstatic const char kMetaKey_TemporalLayerCount[] = "com.android.video.temporal_layers_count";
807c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatic const uint8_t kMandatoryHevcNalUnitTypes[3] = {
829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeVps,
839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeSps,
849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypePps,
859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim};
869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatic const uint8_t kHevcNalUnitTypes[5] = {
879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeVps,
889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeSps,
899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypePps,
909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypePrefixSei,
919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeSuffixSei,
929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim};
937c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang/* uncomment to include model and build in meta */
947c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang//#define SHOW_MODEL_BUILD 1
957c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
9620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track {
9720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
98b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen    Track(MPEG4Writer *owner, const sp<IMediaSource> &source, size_t trackId);
998f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
10020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ~Track();
10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t start(MetaData *params);
10337187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t stop();
10437187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t pause();
10525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool reachedEOS();
10620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1073b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    int64_t getDurationUs() const;
108d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t getEstimatedTrackSizeBytes() const;
109b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeTrackHeader(bool use32BitOffset = true);
1101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void bufferChunk(int64_t timestampUs);
1111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAvc() const { return mIsAvc; }
1129aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    bool isHevc() const { return mIsHevc; }
1131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAudio() const { return mIsAudio; }
1141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isMPEG4() const { return mIsMPEG4; }
115c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    void addChunkOffset(off64_t offset);
11670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int32_t getTrackId() const { return mTrackId; }
117dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    status_t dump(int fd, const Vector<String16>& args) const;
1188b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    static const char *getFourCCForMime(const char *mime);
11920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
121000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    enum {
122000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        kMaxCttsOffsetTimeUs = 1000000LL,  // 1 second
1238c460498c028888c533ab442be12b6d4b669b965James Dong        kSampleArraySize = 1000,
124000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    };
125000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
126c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    // A helper class to handle faster write box with table entries
127c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    template<class TYPE, unsigned ENTRY_SIZE>
128c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    // ENTRY_SIZE: # of values in each entry
129c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    struct ListTableEntries {
130c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        static_assert(ENTRY_SIZE > 0, "ENTRY_SIZE must be positive");
131c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        ListTableEntries(uint32_t elementCapacity)
132c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            : mElementCapacity(elementCapacity),
133c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mTotalNumTableEntries(0),
134c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mNumValuesInCurrEntry(0),
135c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCurrTableEntriesElement(NULL) {
136c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_GT(mElementCapacity, 0);
1372177f21c1ae5bf5cb8c1113a1adbe1fd7db34206Wei Jia            // Ensure no integer overflow on allocation in add().
138c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            CHECK_LT(ENTRY_SIZE, UINT32_MAX / mElementCapacity);
139c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
140c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
141c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Free the allocated memory.
142c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        ~ListTableEntries() {
143c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (!mTableEntryList.empty()) {
144c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                typename List<TYPE *>::iterator it = mTableEntryList.begin();
145c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                delete[] (*it);
146c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.erase(it);
147c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
148c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
149c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
150c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Replace the value at the given position by the given value.
151c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // There must be an existing value at the given position.
152c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order
153c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
154c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void set(const TYPE& value, uint32_t pos) {
155c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            CHECK_LT(pos, mTotalNumTableEntries * ENTRY_SIZE);
156c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
157c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            typename List<TYPE *>::iterator it = mTableEntryList.begin();
158c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            uint32_t iterations = (pos / (mElementCapacity * ENTRY_SIZE));
159c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (it != mTableEntryList.end() && iterations > 0) {
160c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++it;
161c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                --iterations;
162c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
163c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK(it != mTableEntryList.end());
164c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_EQ(iterations, 0);
165c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
166c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            (*it)[(pos % (mElementCapacity * ENTRY_SIZE))] = value;
167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
168c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
169c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Get the value at the given position by the given value.
170c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value the retrieved value at the position in network byte order.
171c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
172c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @return true if a value is found.
173c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        bool get(TYPE& value, uint32_t pos) const {
174c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            if (pos >= mTotalNumTableEntries * ENTRY_SIZE) {
175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                return false;
176c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
177c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
178c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            typename List<TYPE *>::iterator it = mTableEntryList.begin();
179c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            uint32_t iterations = (pos / (mElementCapacity * ENTRY_SIZE));
180c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (it != mTableEntryList.end() && iterations > 0) {
181c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++it;
182c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                --iterations;
183c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
184c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK(it != mTableEntryList.end());
185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_EQ(iterations, 0);
186c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
187c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            value = (*it)[(pos % (mElementCapacity * ENTRY_SIZE))];
188c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            return true;
189c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
190c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
191c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        // adjusts all values by |adjust(value)|
192c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        void adjustEntries(
193c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                std::function<void(size_t /* ix */, TYPE(& /* entry */)[ENTRY_SIZE])> update) {
194c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            size_t nEntries = mTotalNumTableEntries + mNumValuesInCurrEntry / ENTRY_SIZE;
195c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            size_t ix = 0;
196c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            for (TYPE *entryArray : mTableEntryList) {
197c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                size_t num = std::min(nEntries, (size_t)mElementCapacity);
198c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                for (size_t i = 0; i < num; ++i) {
199c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                    update(ix++, (TYPE(&)[ENTRY_SIZE])(*entryArray));
200c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                    entryArray += ENTRY_SIZE;
201c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                }
202c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                nEntries -= num;
203c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            }
204c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        }
205c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar
206c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Store a single value.
207c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order.
208c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void add(const TYPE& value) {
209c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_LT(mNumValuesInCurrEntry, mElementCapacity);
210c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries % mElementCapacity;
211c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            uint32_t nValues  = mNumValuesInCurrEntry % ENTRY_SIZE;
212c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (nEntries == 0 && nValues == 0) {
213c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                mCurrTableEntriesElement = new TYPE[ENTRY_SIZE * mElementCapacity];
214c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                CHECK(mCurrTableEntriesElement != NULL);
215c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.push_back(mCurrTableEntriesElement);
216c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
217c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
218c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            uint32_t pos = nEntries * ENTRY_SIZE + nValues;
219c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCurrTableEntriesElement[pos] = value;
220c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
221c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            ++mNumValuesInCurrEntry;
222c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            if ((mNumValuesInCurrEntry % ENTRY_SIZE) == 0) {
223c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++mTotalNumTableEntries;
224c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mNumValuesInCurrEntry = 0;
225c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
226c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
227c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
228c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Write out the table entries:
229c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 1. the number of entries goes first
230c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 2. followed by the values in the table enties in order
231c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg writer the writer to actual write to the storage
232c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void write(MPEG4Writer *writer) const {
233c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            CHECK_EQ(mNumValuesInCurrEntry % ENTRY_SIZE, 0);
234c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries;
235c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            writer->writeInt32(nEntries);
236c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            for (typename List<TYPE *>::iterator it = mTableEntryList.begin();
237c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                it != mTableEntryList.end(); ++it) {
238c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                CHECK_GT(nEntries, 0);
239c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                if (nEntries >= mElementCapacity) {
240c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                    writer->write(*it, sizeof(TYPE) * ENTRY_SIZE, mElementCapacity);
241c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    nEntries -= mElementCapacity;
242c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                } else {
243c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                    writer->write(*it, sizeof(TYPE) * ENTRY_SIZE, nEntries);
244c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    break;
245c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                }
246c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
247c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
248c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
249c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Return the number of entries in the table.
250c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t count() const { return mTotalNumTableEntries; }
251c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
252c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    private:
253c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mElementCapacity;  // # entries in an element
254c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mTotalNumTableEntries;
255c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        uint32_t         mNumValuesInCurrEntry;  // up to ENTRY_SIZE
256c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        TYPE             *mCurrTableEntriesElement;
257c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mutable List<TYPE *>     mTableEntryList;
258c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
259c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries);
260c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    };
261c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
262c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
263c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
26420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Writer *mOwner;
26520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mMeta;
266b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen    sp<IMediaSource> mSource;
26720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    volatile bool mDone;
268a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mPaused;
269a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mResumed;
270eaae38445a340c4857c1c5569475879a728e63b7James Dong    volatile bool mStarted;
2711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAvc;
2729aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    bool mIsHevc;
2731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAudio;
2741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsMPEG4;
2759db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang    bool mIsMalformed;
276bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t mTrackId;
277c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    int64_t mTrackDurationUs;
27843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int64_t mMaxChunkDurationUs;
279826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar    int64_t mLastDecodingTimeUs;
280e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
281d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t mEstimatedTrackSizeBytes;
2821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t mMdatSizeBytes;
2838f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mTimeScale;
28420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_t mThread;
28620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
287be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
28813aec890216948b0c364f8f92792129d0335f506James Dong    List<MediaBuffer *> mChunkSamples;
2891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
290c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    bool                mSamplesHaveSameSize;
291c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 1> *mStszTableEntries;
292be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
293c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 1> *mStcoTableEntries;
294c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<off64_t, 1> *mCo64TableEntries;
295c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 3> *mStscTableEntries;
296c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 1> *mStssTableEntries;
297c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 2> *mSttsTableEntries;
298c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 2> *mCttsTableEntries;
299965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
300000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMinCttsOffsetTimeUs;
301000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMaxCttsOffsetTimeUs;
302965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Sequence parameter set or picture parameter set
3043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    struct AVCParamSet {
3053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        AVCParamSet(uint16_t length, const uint8_t *data)
3063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            : mLength(length), mData(data) {}
3073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
3083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t mLength;
3093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *mData;
3103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    };
3113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mSeqParamSets;
3123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mPicParamSets;
3133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileIdc;
3143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileCompatible;
3153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mLevelIdc;
3163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
31720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *mCodecSpecificData;
31820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t mCodecSpecificDataSize;
319548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    bool mGotAllCodecSpecificData;
32093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    bool mTrackingProgressStatus;
32120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool mReachedEOS;
3233c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    int64_t mStartTimestampUs;
32470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mStartTimeRealUs;
32570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mFirstSampleTimeRealUs;
32693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mPreviousTrackTimeUs;
32793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mTrackEveryTimeDurationUs;
32825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
329872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Update the audio track's drift information.
330872a481558350634a3fd5cb67939de288af00ecbJames Dong    void updateDriftTime(const sp<MetaData>& meta);
331872a481558350634a3fd5cb67939de288af00ecbJames Dong
332000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int32_t getStartTimeOffsetScaledTime() const;
333000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
33420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static void *ThreadWrapper(void *me);
33537187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t threadEntry();
33620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *parseParamSet(
3383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen);
3393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
3409aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t copyCodecSpecificData(const uint8_t *data, size_t size, size_t minLength = 0);
3419aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
342b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size);
343b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size);
344b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size);
345215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong
3469aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t makeHEVCCodecSpecificData(const uint8_t *data, size_t size);
3479aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t copyHEVCCodecSpecificData(const uint8_t *data, size_t size);
3489aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t parseHEVCCodecSpecificData(
3499aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            const uint8_t *data, size_t size, HevcParameterSets &paramSets);
3509aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
351215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    // Track authoring progress status
352faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    void trackProgressStatus(int64_t timeUs, status_t err = OK);
35393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    void initTrackingProgressStatus(MetaData *params);
35403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
35519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    void getCodecSpecificDataFromInputFormatIfPossible();
35619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
357c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Determine the track time scale
358c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If it is an audio track, try to use the sampling rate as
359c059860c73678a202bfa33062723e8f82fb779d9James Dong    // the time scale; however, if user chooses the overwrite
360c059860c73678a202bfa33062723e8f82fb779d9James Dong    // value, the user-supplied time scale will be used.
361c059860c73678a202bfa33062723e8f82fb779d9James Dong    void setTimeScale();
362c059860c73678a202bfa33062723e8f82fb779d9James Dong
363690f546b0ee548dbfe997df36418e5302ec2d786James Dong    // Simple validation on the codec specific data
364690f546b0ee548dbfe997df36418e5302ec2d786James Dong    status_t checkCodecSpecificData() const;
36513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t mRotation;
366690f546b0ee548dbfe997df36418e5302ec2d786James Dong
3671f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void updateTrackSizeEstimate();
3681f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStscTableEntry(size_t chunkId, size_t sampleId);
3691f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStssTableEntry(size_t sampleId);
37079761ab096f57c3027fad9556c2bc436672d614eJames Dong
37179761ab096f57c3027fad9556c2bc436672d614eJames Dong    // Duration is time scale based
37279761ab096f57c3027fad9556c2bc436672d614eJames Dong    void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
373965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
37445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
37545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    bool isTrackMalFormed() const;
37643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    void sendTrackSummary(bool hasMultipleTracks);
3771f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
378b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Write the boxes
379b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStcoBox(bool use32BitOffset);
380b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStscBox();
381b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStszBox();
382b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStssBox();
383b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSttsBox();
384965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void writeCttsBox();
385b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeD263Box();
386b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writePaspBox();
387b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAvccBox();
3889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    void writeHvccBox();
389b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeUrlBox();
390b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDrefBox();
391b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDinfBox();
392b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDamrBox();
393efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeMdhdBox(uint32_t now);
394b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSmhdBox();
395b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVmhdBox();
396b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeHdlrBox();
397efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeTkhdBox(uint32_t now);
39858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    void writeColrBox();
399b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4aEsdsBox();
400b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4vEsdsBox();
401b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAudioFourCCBox();
402b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVideoFourCCBox();
403b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStblBox(bool use32BitOffset);
404b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
40520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track(const Track &);
40620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track &operator=(const Track &);
40720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
40820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
40930ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd)
410674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    : mFd(dup(fd)),
411674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong      mInitCheck(mFd < 0? NO_INIT: OK),
412de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui      mIsRealTimeRecording(true),
413b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong      mUse4ByteNalLength(true),
4141acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
415a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong      mIsFileSizeLimitExplicitlyRequested(false),
416a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
417a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
418411ba422e3635d534928ffd81abf54f4f291c739James Dong      mWriterThreadStarted(false),
41930ab66297501757d745b9ae10da61adcd891f497Andreas Huber      mOffset(0),
42013aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
421e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mMoovBoxBuffer(NULL),
422e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mMoovBoxBufferOffset(0),
423e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mWriteMoovBoxToMemory(false),
424e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mFreeBoxOffset(0),
425e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mStreamableFile(false),
4267837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
4277c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang      mMoovExtraSize(0),
42807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mInterleaveDurationUs(1000000),
429e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mTimeScale(-1),
430e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mStartTimestampUs(-1ll),
43107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLatitudex10000(0),
43207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLongitudex10000(0),
43386b7f47aa7482424cf8fd248f1315311919be3b0James Dong      mAreGeoTagsAvailable(false),
434ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar      mStartTimeOffsetMs(-1),
435ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar      mMetaKeys(new AMessage()) {
4367c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    addDeviceMeta();
4372aa74dc097fe860abc84769abf2b6e0962718471Robert Shih
4382aa74dc097fe860abc84769abf2b6e0962718471Robert Shih    // Verify mFd is seekable
4392aa74dc097fe860abc84769abf2b6e0962718471Robert Shih    off64_t off = lseek64(mFd, 0, SEEK_SET);
4402aa74dc097fe860abc84769abf2b6e0962718471Robert Shih    if (off < 0) {
4412aa74dc097fe860abc84769abf2b6e0962718471Robert Shih        ALOGE("cannot seek mFd: %s (%d)", strerror(errno), errno);
4422aa74dc097fe860abc84769abf2b6e0962718471Robert Shih        release();
4432aa74dc097fe860abc84769abf2b6e0962718471Robert Shih    }
44430ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
44530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
44620111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
4478bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong    reset();
44820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4491f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    while (!mTracks.empty()) {
4501f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        List<Track *>::iterator it = mTracks.begin();
45120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
4521f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        (*it) = NULL;
4531f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mTracks.erase(it);
45420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
45520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
45620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
45720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
458dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump(
459dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) {
460dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
461dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
462dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
463dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "   MPEG4Writer %p\n", this);
464dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
465dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     mStarted: %s\n", mStarted? "true": "false");
466dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
467dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
468dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    for (List<Track *>::iterator it = mTracks.begin();
469dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong         it != mTracks.end(); ++it) {
470dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        (*it)->dump(fd, args);
471dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    }
472dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
473dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
474dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
475dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump(
47684333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        int fd, const Vector<String16>& /* args */) const {
477dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
478dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
479dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
480dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     %s track\n", mIsAudio? "Audio": "Video");
481dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
482dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "       reached EOS: %s\n",
483dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong            mReachedEOS? "true": "false");
484dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
485c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    snprintf(buffer, SIZE, "       frames encoded : %d\n", mStszTableEntries->count());
48613210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
487377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    snprintf(buffer, SIZE, "       duration encoded : %" PRId64 " us\n", mTrackDurationUs);
48813210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
489dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
490dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
491dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
492dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
4938b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan// static
4948b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavanconst char *MPEG4Writer::Track::getFourCCForMime(const char *mime) {
4958b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (mime == NULL) {
4968b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        return NULL;
4978b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    }
4988b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (!strncasecmp(mime, "audio/", 6)) {
4998b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
5008b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "samr";
5018b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
5028b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "sawb";
5038b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
5048b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "mp4a";
5058b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        }
5068b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    } else if (!strncasecmp(mime, "video/", 6)) {
5078b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
5088b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "mp4v";
5098b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
5108b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "s263";
5118b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
5128b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "avc1";
5139aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
5149aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return "hvc1";
5158b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        }
5168b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    } else {
5178b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        ALOGE("Track (%s) other than video or audio is not supported", mime);
5188b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    }
5198b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    return NULL;
5208b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan}
5218b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan
522b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissenstatus_t MPEG4Writer::addSource(const sp<IMediaSource> &source) {
523bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    Mutex::Autolock l(mLock);
524bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    if (mStarted) {
52529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Attempt to add source AFTER recording is started");
526bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        return UNKNOWN_ERROR;
527bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    }
528acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
529acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // At most 2 tracks can be supported.
530acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    if (mTracks.size() >= 2) {
531a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGE("Too many tracks (%zu) to add", mTracks.size());
532acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return ERROR_UNSUPPORTED;
533acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
534acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
535acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    CHECK(source.get() != NULL);
536acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
537acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    const char *mime;
538acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    source->getFormat()->findCString(kKeyMIMEType, &mime);
539acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    bool isAudio = !strncasecmp(mime, "audio/", 6);
5408b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (Track::getFourCCForMime(mime) == NULL) {
5418b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        ALOGE("Unsupported mime '%s'", mime);
542acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return ERROR_UNSUPPORTED;
543acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
544acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
545acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // At this point, we know the track to be added is either
546acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // video or audio. Thus, we only need to check whether it
547acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // is an audio track or not (if it is not, then it must be
548acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // a video track).
549acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
550acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // No more than one video or one audio track is supported.
551acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    for (List<Track*>::iterator it = mTracks.begin();
552acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong         it != mTracks.end(); ++it) {
553acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        if ((*it)->isAudio() == isAudio) {
554acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong            ALOGE("%s track already exists", isAudio? "Audio": "Video");
555acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong            return ERROR_UNSUPPORTED;
556acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        }
557acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
558acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
559acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // This is the first track of either audio or video.
560acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // Go ahead to add the track.
561219f195159f93d627af2b243732e3f9020511a46James Dong    Track *track = new Track(this, source, 1 + mTracks.size());
56220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
5632dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
5642dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
56520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
56620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
56793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) {
568acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    if (mTracks.empty()) {
569acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        ALOGE("No source added");
570acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return INVALID_OPERATION;
571acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
572acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
573a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
574a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
57593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        status_t err = (*it)->start(params);
576a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
577a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (err != OK) {
578a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            for (List<Track *>::iterator it2 = mTracks.begin();
579a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                 it2 != it; ++it2) {
580a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                (*it2)->stop();
581a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            }
582a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
583a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            return err;
584a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
585a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
586a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
587a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
588a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
5897c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangvoid MPEG4Writer::addDeviceMeta() {
5907c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // add device info and estimate space in 'moov'
5917c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    char val[PROPERTY_VALUE_MAX];
5927c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    size_t n;
5937c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // meta size is estimated by adding up the following:
5947c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // - meta header structures, which occur only once (total 66 bytes)
5957c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // - size for each key, which consists of a fixed header (32 bytes),
5967c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    //   plus key length and data length.
5977c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += 66;
5987c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.build.version.release", val, NULL)
5997c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
6007c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Version, val, n + 1);
6017c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Version) + n + 32;
6027c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
6037c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#ifdef SHOW_MODEL_BUILD
6047c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.product.model", val, NULL)
6057c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
6067c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Model, val, n + 1);
6077c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Model) + n + 32;
6087c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
6097c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.build.display.id", val, NULL)
6107c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
6117c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Build, val, n + 1);
6127c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Build) + n + 32;
6137c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
6147c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#endif
6157c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang}
6167c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
6172dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
6182dec2b5be2056c6d9428897dc672185872d30d17James Dong    // This implementation is highly experimental/heurisitic.
6192dec2b5be2056c6d9428897dc672185872d30d17James Dong    //
6202dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Statistical analysis shows that metadata usually accounts
6212dec2b5be2056c6d9428897dc672185872d30d17James Dong    // for a small portion of the total file size, usually < 0.6%.
6222dec2b5be2056c6d9428897dc672185872d30d17James Dong
62378a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2,
6242dec2b5be2056c6d9428897dc672185872d30d17James Dong    // where 1MB is the common file size limit for MMS application.
62578a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MAX _MOOV_BOX_SIZE value is based on about 3
6262dec2b5be2056c6d9428897dc672185872d30d17James Dong    // minute video recording with a bit rate about 3 Mbps, because
6272dec2b5be2056c6d9428897dc672185872d30d17James Dong    // statistics also show that most of the video captured are going
6282dec2b5be2056c6d9428897dc672185872d30d17James Dong    // to be less than 3 minutes.
6292dec2b5be2056c6d9428897dc672185872d30d17James Dong
6302dec2b5be2056c6d9428897dc672185872d30d17James Dong    // If the estimation is wrong, we will pay the price of wasting
6312dec2b5be2056c6d9428897dc672185872d30d17James Dong    // some reserved space. This should not happen so often statistically.
6322dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int32_t factor = mUse32BitOffset? 1: 2;
63378a1a286f736888ae7af8860b2c424af0d978848James Dong    static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024;  // 3 KB
6342dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
6352dec2b5be2056c6d9428897dc672185872d30d17James Dong    int64_t size = MIN_MOOV_BOX_SIZE;
6362dec2b5be2056c6d9428897dc672185872d30d17James Dong
63778a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file size limit is set
638a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
63978a1a286f736888ae7af8860b2c424af0d978848James Dong        size = mMaxFileSizeLimitBytes * 6 / 1000;
64078a1a286f736888ae7af8860b2c424af0d978848James Dong    }
64178a1a286f736888ae7af8860b2c424af0d978848James Dong
64278a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file duration limit is set
64378a1a286f736888ae7af8860b2c424af0d978848James Dong    if (mMaxFileDurationLimitUs != 0) {
64478a1a286f736888ae7af8860b2c424af0d978848James Dong        if (bitRate > 0) {
64578a1a286f736888ae7af8860b2c424af0d978848James Dong            int64_t size2 =
64678a1a286f736888ae7af8860b2c424af0d978848James Dong                ((mMaxFileDurationLimitUs * bitRate * 6) / 1000 / 8000000);
64778a1a286f736888ae7af8860b2c424af0d978848James Dong            if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
64878a1a286f736888ae7af8860b2c424af0d978848James Dong                // When both file size and duration limits are set,
64978a1a286f736888ae7af8860b2c424af0d978848James Dong                // we use the smaller limit of the two.
65078a1a286f736888ae7af8860b2c424af0d978848James Dong                if (size > size2) {
65178a1a286f736888ae7af8860b2c424af0d978848James Dong                    size = size2;
65278a1a286f736888ae7af8860b2c424af0d978848James Dong                }
65378a1a286f736888ae7af8860b2c424af0d978848James Dong            } else {
65478a1a286f736888ae7af8860b2c424af0d978848James Dong                // Only max file duration limit is set
65578a1a286f736888ae7af8860b2c424af0d978848James Dong                size = size2;
65678a1a286f736888ae7af8860b2c424af0d978848James Dong            }
6572dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
6582dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
65978a1a286f736888ae7af8860b2c424af0d978848James Dong
6602dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size < MIN_MOOV_BOX_SIZE) {
6612dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MIN_MOOV_BOX_SIZE;
6622dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
6632dec2b5be2056c6d9428897dc672185872d30d17James Dong
6642dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Any long duration recording will be probably end up with
6652dec2b5be2056c6d9428897dc672185872d30d17James Dong    // non-streamable mp4 file.
6662dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size > MAX_MOOV_BOX_SIZE) {
6672dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MAX_MOOV_BOX_SIZE;
6682dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
6692dec2b5be2056c6d9428897dc672185872d30d17James Dong
6707c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // Account for the extra stuff (Geo, meta keys, etc.)
6717c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    size += mMoovExtraSize;
6727c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
673a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGI("limits: %" PRId64 "/%" PRId64 " bytes/us, bit rate: %d bps and the"
674a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn         " estimated moov size %" PRId64 " bytes",
6752dec2b5be2056c6d9428897dc672185872d30d17James Dong         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
6762dec2b5be2056c6d9428897dc672185872d30d17James Dong    return factor * size;
6772dec2b5be2056c6d9428897dc672185872d30d17James Dong}
6782dec2b5be2056c6d9428897dc672185872d30d17James Dong
6792dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) {
680674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
68125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
68220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
68320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
684a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    /*
685a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * Check mMaxFileSizeLimitBytes at the beginning
686a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * since mMaxFileSizeLimitBytes may be implicitly
687a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * changed later for 32-bit file offset even if
688a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * user does not ask to set it explicitly.
689a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     */
690a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0) {
691a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong        mIsFileSizeLimitExplicitlyRequested = true;
692a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    }
693a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong
6942dec2b5be2056c6d9428897dc672185872d30d17James Dong    int32_t use64BitOffset;
6952dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (param &&
6962dec2b5be2056c6d9428897dc672185872d30d17James Dong        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
6972dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64BitOffset) {
6982dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
6992dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
7002dec2b5be2056c6d9428897dc672185872d30d17James Dong
7011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    if (mUse32BitOffset) {
7021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // Implicit 32 bit file size limit
7031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes == 0) {
7041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
7051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
7061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
7071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // If file size is set to be larger than the 32 bit file
7081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // size limit, treat it as an error.
7091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
710a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGW("32-bit file size limit (%" PRId64 " bytes) too big. "
711a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                 "It is changed to %" PRId64 " bytes",
712d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                mMaxFileSizeLimitBytes, kMax32BitFileSize);
713d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
7141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
7151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    }
7161f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
717b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    int32_t use2ByteNalLength;
718b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (param &&
719b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) &&
720b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        use2ByteNalLength) {
721b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mUse4ByteNalLength = false;
7222dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
7232dec2b5be2056c6d9428897dc672185872d30d17James Dong
724de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    int32_t isRealTimeRecording;
725de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (param && param->findInt32(kKeyRealTimeRecording, &isRealTimeRecording)) {
726de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        mIsRealTimeRecording = isRealTimeRecording;
727de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    }
728de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
729065d1aff96818df54456053f1574aec8a234d0deJames Dong    mStartTimestampUs = -1;
73093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
731a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mStarted) {
732a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused) {
733a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mPaused = false;
73493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return startTracks(param);
735a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
736a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
737a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
738a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
7398f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (!param ||
7408f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
7418f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mTimeScale = 1000;
7428f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
74343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
7443856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("movie time scale: %d", mTimeScale);
7458f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
74677e8ae9967a078770416619e99ddb5b010def312James Dong    /*
74777e8ae9967a078770416619e99ddb5b010def312James Dong     * When the requested file size limit is small, the priority
74877e8ae9967a078770416619e99ddb5b010def312James Dong     * is to meet the file size limit requirement, rather than
7497b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to make the file streamable. mStreamableFile does not tell
7507b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * whether the actual recorded file is streamable or not.
75177e8ae9967a078770416619e99ddb5b010def312James Dong     */
75277e8ae9967a078770416619e99ddb5b010def312James Dong    mStreamableFile =
75377e8ae9967a078770416619e99ddb5b010def312James Dong        (mMaxFileSizeLimitBytes != 0 &&
75477e8ae9967a078770416619e99ddb5b010def312James Dong         mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes);
75577e8ae9967a078770416619e99ddb5b010def312James Dong
7567b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    /*
7577b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mWriteMoovBoxToMemory is true if the amount of data in moov box is
7587b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * smaller than the reserved free space at the beginning of a file, AND
7597b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * when the content of moov box is constructed. Note that video/audio
7607b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * frame data is always written to the file but not in the memory.
7617b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7627b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * Before stop()/reset() is called, mWriteMoovBoxToMemory is always
7637b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * false. When reset() is called at the end of a recording session,
7647b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * Moov box needs to be constructed.
7657b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7667b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 1) Right before a moov box is constructed, mWriteMoovBoxToMemory
7677b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to set to mStreamableFile so that if
7687b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * the file is intended to be streamable, it is set to true;
7697b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * otherwise, it is set to false. When the value is set to false,
7707b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * all the content of the moov box is written immediately to
7717b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * the end of the file. When the value is set to true, all the
7727b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * content of the moov box is written to an in-memory cache,
7737b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mMoovBoxBuffer, util the following condition happens. Note
7747b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * that the size of the in-memory cache is the same as the
7757b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * reserved free space at the beginning of the file.
7767b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7777b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 2) While the data of the moov box is written to an in-memory
7787b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * cache, the data size is checked against the reserved space.
7797b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * If the data size surpasses the reserved space, subsequent moov
7807b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * data could no longer be hold in the in-memory cache. This also
7817b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * indicates that the reserved space was too small. At this point,
7827b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * _all_ moov data must be written to the end of the file.
7837b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mWriteMoovBoxToMemory must be set to false to direct the write
7847b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to the file.
7857b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7867b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 3) If the data size in moov box is smaller than the reserved
7877b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * space after moov box is completely constructed, the in-memory
7887b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * cache copy of the moov box is written to the reserved free
7897b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * space. Thus, immediately after the moov is completedly
7907b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * constructed, mWriteMoovBoxToMemory is always set to false.
7917b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     */
7927b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    mWriteMoovBoxToMemory = false;
7937837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = NULL;
7947837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
7957837c17063a4c50bc856ba59418516fdab731de7James Dong
796b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeFtypBox(param);
79720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7987837c17063a4c50bc856ba59418516fdab731de7James Dong    mFreeBoxOffset = mOffset;
79920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8007837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mEstimatedMoovBoxSize == 0) {
8012dec2b5be2056c6d9428897dc672185872d30d17James Dong        int32_t bitRate = -1;
8022dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (param) {
8032dec2b5be2056c6d9428897dc672185872d30d17James Dong            param->findInt32(kKeyBitRate, &bitRate);
8042dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
8052dec2b5be2056c6d9428897dc672185872d30d17James Dong        mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
8067837c17063a4c50bc856ba59418516fdab731de7James Dong    }
80743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(mEstimatedMoovBoxSize, 8);
80877e8ae9967a078770416619e99ddb5b010def312James Dong    if (mStreamableFile) {
80977e8ae9967a078770416619e99ddb5b010def312James Dong        // Reserve a 'free' box only for streamable file
81077e8ae9967a078770416619e99ddb5b010def312James Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
81177e8ae9967a078770416619e99ddb5b010def312James Dong        writeInt32(mEstimatedMoovBoxSize);
81277e8ae9967a078770416619e99ddb5b010def312James Dong        write("free", 4);
81377e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
81477e8ae9967a078770416619e99ddb5b010def312James Dong    } else {
81577e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mOffset;
81677e8ae9967a078770416619e99ddb5b010def312James Dong    }
8177837c17063a4c50bc856ba59418516fdab731de7James Dong
8187837c17063a4c50bc856ba59418516fdab731de7James Dong    mOffset = mMdatOffset;
819c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mMdatOffset, SEEK_SET);
8201acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
8211acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("????mdat", 8);
8221acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
8231acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("\x00\x00\x00\x01mdat????????", 16);
8241acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
8251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    status_t err = startWriterThread();
8271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (err != OK) {
8281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return err;
8291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    err = startTracks(param);
832a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (err != OK) {
833a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return err;
83420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
8351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
836a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = true;
83725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
83820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
83920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8401f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const {
8411f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    return mUse32BitOffset;
8421f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
8431f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
84437187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() {
845674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
84637187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
847a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
848a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
84937187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
850a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
851a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
85237187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->pause();
85337187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (status != OK) {
85437187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
85537187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
856a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
85737187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
858a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
859a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
8601c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() {
861b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Stopping writer thread");
862411ba422e3635d534928ffd81abf54f4f291c739James Dong    if (!mWriterThreadStarted) {
863411ba422e3635d534928ffd81abf54f4f291c739James Dong        return;
864411ba422e3635d534928ffd81abf54f4f291c739James Dong    }
8651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
8671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
8681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mDone = true;
8701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkReadyCondition.signal();
8711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void *dummy;
8741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_join(mThread, &dummy);
875411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = false;
876b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Writer thread stopped");
8771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
8781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
87913f6284305e4b27395a23db7882d670bdb1bcae1James Dong/*
88013f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix:
88113f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a  b  u |
88213f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c  d  v |
88313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x  y  w |
88413f6284305e4b27395a23db7882d670bdb1bcae1James Dong *
88513f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following
88613f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w},
88713f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while
88813f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format.
88913f6284305e4b27395a23db7882d670bdb1bcae1James Dong */
89013f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) {
8913856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeCompositionMatrix");
89213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t a = 0x00010000;
89313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t b = 0;
89413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t c = 0;
89513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t d = 0x00010000;
89613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    switch (degrees) {
89713f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 0:
89813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
89913f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 90:
90013f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
90113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0x00010000;
90213f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0xFFFF0000;
90313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
90413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
90513f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 180:
90613f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0xFFFF0000;
90713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0xFFFF0000;
90813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
90913f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 270:
91013f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
91113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0xFFFF0000;
91213f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0x00010000;
91313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
91413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
91513f6284305e4b27395a23db7882d670bdb1bcae1James Dong        default:
91613f6284305e4b27395a23db7882d670bdb1bcae1James Dong            CHECK(!"Should never reach this unknown rotation");
91713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
91813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
91913f6284305e4b27395a23db7882d670bdb1bcae1James Dong
92013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(a);           // a
92113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(b);           // b
92213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // u
92313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(c);           // c
92413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(d);           // d
92513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // v
92613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // x
92713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // y
92813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0x40000000);  // w
92913f6284305e4b27395a23db7882d670bdb1bcae1James Dong}
93013f6284305e4b27395a23db7882d670bdb1bcae1James Dong
931411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() {
932411ba422e3635d534928ffd81abf54f4f291c739James Dong    close(mFd);
933411ba422e3635d534928ffd81abf54f4f291c739James Dong    mFd = -1;
934411ba422e3635d534928ffd81abf54f4f291c739James Dong    mInitCheck = NO_INIT;
935411ba422e3635d534928ffd81abf54f4f291c739James Dong    mStarted = false;
9364c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary    free(mMoovBoxBuffer);
9374c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary    mMoovBoxBuffer = NULL;
938411ba422e3635d534928ffd81abf54f4f291c739James Dong}
93913f6284305e4b27395a23db7882d670bdb1bcae1James Dong
9408bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dongstatus_t MPEG4Writer::reset() {
941674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
94237187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
943411ba422e3635d534928ffd81abf54f4f291c739James Dong    } else {
944411ba422e3635d534928ffd81abf54f4f291c739James Dong        if (!mWriterThreadStarted ||
945411ba422e3635d534928ffd81abf54f4f291c739James Dong            !mStarted) {
946411ba422e3635d534928ffd81abf54f4f291c739James Dong            if (mWriterThreadStarted) {
947411ba422e3635d534928ffd81abf54f4f291c739James Dong                stopWriterThread();
948411ba422e3635d534928ffd81abf54f4f291c739James Dong            }
949411ba422e3635d534928ffd81abf54f4f291c739James Dong            release();
950411ba422e3635d534928ffd81abf54f4f291c739James Dong            return OK;
951411ba422e3635d534928ffd81abf54f4f291c739James Dong        }
95220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
95320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
95437187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
9558f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t maxDurationUs = 0;
95665b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    int64_t minDurationUs = 0x7fffffffffffffffLL;
95720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
95820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
95937187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->stop();
96037187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK) {
96137187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
96237187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
96320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9648f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int64_t durationUs = (*it)->getDurationUs();
9658f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (durationUs > maxDurationUs) {
9668f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            maxDurationUs = durationUs;
96720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
96865b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        if (durationUs < minDurationUs) {
96965b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs = durationUs;
97065b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        }
97165b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    }
97265b3d76025c71d755b0fb3b6ead90255f25417edJames Dong
97365b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    if (mTracks.size() > 1) {
974a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGD("Duration from tracks range is [%" PRId64 ", %" PRId64 "] us",
97565b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs, maxDurationUs);
97620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
97720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    stopWriterThread();
9797837c17063a4c50bc856ba59418516fdab731de7James Dong
98037187916a486504acaf83bea30147eb5fbf46ae5James Dong    // Do not write out movie header on error.
98137187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err != OK) {
982411ba422e3635d534928ffd81abf54f4f291c739James Dong        release();
98337187916a486504acaf83bea30147eb5fbf46ae5James Dong        return err;
98437187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
98537187916a486504acaf83bea30147eb5fbf46ae5James Dong
98620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
9871acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
988c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset, SEEK_SET);
9891f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad        uint32_t size = htonl(static_cast<uint32_t>(mOffset - mMdatOffset));
990c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 4);
9911acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
992c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset + 8, SEEK_SET);
9931f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad        uint64_t size = mOffset - mMdatOffset;
9941acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        size = hton64(size);
995c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 8);
9961acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
997c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mOffset, SEEK_SET);
99820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9997b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // Construct moov box now
10007837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
10017b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    mWriteMoovBoxToMemory = mStreamableFile;
10027b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mWriteMoovBoxToMemory) {
10037b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // There is no need to allocate in-memory cache
10047b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // for moov box if the file is not streamable.
10057b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
10067b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
10077b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        CHECK(mMoovBoxBuffer != NULL);
10087b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    }
1009b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMoovBox(maxDurationUs);
101020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10117b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // mWriteMoovBoxToMemory could be set to false in
10127b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // MPEG4Writer::write() method
10137b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mWriteMoovBoxToMemory) {
10147b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        mWriteMoovBoxToMemory = false;
10157b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // Content of the moov box is saved in the cache, and the in-memory
10167b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // moov box needs to be written to the file in a single shot.
10177b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
101843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize);
10197837c17063a4c50bc856ba59418516fdab731de7James Dong
10207837c17063a4c50bc856ba59418516fdab731de7James Dong        // Moov box
1021c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
10227837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset = mFreeBoxOffset;
1023674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset);
10247837c17063a4c50bc856ba59418516fdab731de7James Dong
10257837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free box
1026c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
10277837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
10287837c17063a4c50bc856ba59418516fdab731de7James Dong        write("free", 4);
10297b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    } else {
10307b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        ALOGI("The mp4 file will not be streamable.");
10317b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    }
10327837c17063a4c50bc856ba59418516fdab731de7James Dong
10337b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // Free in-memory cache for moov box
10347b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mMoovBoxBuffer != NULL) {
10357837c17063a4c50bc856ba59418516fdab731de7James Dong        free(mMoovBoxBuffer);
10367837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBuffer = NULL;
10377837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBufferOffset = 0;
10387837c17063a4c50bc856ba59418516fdab731de7James Dong    }
10397837c17063a4c50bc856ba59418516fdab731de7James Dong
10400c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
104120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1042411ba422e3635d534928ffd81abf54f4f291c739James Dong    release();
104337187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
104420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
104520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1046efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonuint32_t MPEG4Writer::getMpeg4Time() {
1047b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    time_t now = time(NULL);
1048efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // MP4 file uses time counting seconds since midnight, Jan. 1, 1904
1049efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // while time function returns Unix epoch values which starts
1050efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // at 1970-01-01. Lets add the number of seconds between them
10512b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    static const uint32_t delta = (66 * 365 + 17) * (24 * 60 * 60);
10522b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    if (now < 0 || uint32_t(now) > UINT32_MAX - delta) {
10532b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen        return 0;
10542b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    }
10552b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    uint32_t mpeg4Time = uint32_t(now) + delta;
1056efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    return mpeg4Time;
1057efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson}
1058efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson
1059efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) {
1060efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
1061b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("mvhd");
1062b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // version=0, flags=0
1063b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // creation time
1064b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // modification time
1065b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTimeScale);    // mvhd timescale
1066b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6;
1067b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(duration);
1068b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0x10000);       // rate: 1.0
1069b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0x100);         // volume
1070b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0);             // reserved
1071b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
1072b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
1073b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeCompositionMatrix(0); // matrix
1074b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1075b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1076b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1077b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1078b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1079b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1080b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTracks.size() + 1);  // nextTrackID
1081b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // mvhd
1082b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1083b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1084b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) {
1085b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("moov");
1086b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMvhdBox(durationUs);
108707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (mAreGeoTagsAvailable) {
108807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        writeUdtaBox();
108907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
1090e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeMetaBox();
1091b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t id = 1;
1092b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    for (List<Track *>::iterator it = mTracks.begin();
1093b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        it != mTracks.end(); ++it, ++id) {
1094b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (*it)->writeTrackHeader(mUse32BitOffset);
1095b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
1096b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // moov
1097b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1098b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
10992cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) {
1100b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("ftyp");
1101b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1102b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t fileType;
1103b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (param && param->findInt32(kKeyFileType, &fileType) &&
1104b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fileType != OUTPUT_FORMAT_MPEG_4) {
1105b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("3gp4");
11068284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeInt32(0);
11078284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("isom");
11088284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("3gp4");
1109b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
11108284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("mp42");
11118284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeInt32(0);
1112b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("isom");
11138284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("mp42");
1114b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
1115b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1116b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();
1117b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1118b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
111907ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() {
112007ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5)
112107ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5"
112207ec01904613a0bac32caaa8444b4690998faed7James Dong#endif
112307ec01904613a0bac32caaa8444b4690998faed7James Dong
112407ec01904613a0bac32caaa8444b4690998faed7James Dong    // Test mode is enabled only if rw.media.record.test system
112507ec01904613a0bac32caaa8444b4690998faed7James Dong    // property is enabled.
112607ec01904613a0bac32caaa8444b4690998faed7James Dong    char value[PROPERTY_VALUE_MAX];
112707ec01904613a0bac32caaa8444b4690998faed7James Dong    if (property_get("rw.media.record.test", value, NULL) &&
112807ec01904613a0bac32caaa8444b4690998faed7James Dong        (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) {
112907ec01904613a0bac32caaa8444b4690998faed7James Dong        return true;
113007ec01904613a0bac32caaa8444b4690998faed7James Dong    }
113107ec01904613a0bac32caaa8444b4690998faed7James Dong    return false;
113207ec01904613a0bac32caaa8444b4690998faed7James Dong}
113307ec01904613a0bac32caaa8444b4690998faed7James Dong
113470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() {
113507ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send session summary only if test mode is enabled
113607ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
113707ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
113807ec01904613a0bac32caaa8444b4690998faed7James Dong    }
113907ec01904613a0bac32caaa8444b4690998faed7James Dong
114070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
114170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong         it != mChunkInfos.end(); ++it) {
114270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int trackNum = it->mTrack->getTrackId() << 28;
114370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
114470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS,
114570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs);
114670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    }
114770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong}
114870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
114913aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
115013aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
115113aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
115213aec890216948b0c364f8f92792129d0335f506James Dong}
115313aec890216948b0c364f8f92792129d0335f506James Dong
115413aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() {
115513aec890216948b0c364f8f92792129d0335f506James Dong    mLock.lock();
115613aec890216948b0c364f8f92792129d0335f506James Dong}
115713aec890216948b0c364f8f92792129d0335f506James Dong
115813aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() {
115913aec890216948b0c364f8f92792129d0335f506James Dong    mLock.unlock();
116013aec890216948b0c364f8f92792129d0335f506James Dong}
116120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1162c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
1163c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
116420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1165c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    ::write(mFd,
1166c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          (const uint8_t *)buffer->data() + buffer->range_offset(),
1167c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          buffer->range_length());
116820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
116920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
117020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
117120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
117220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
117320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
117403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
117503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
117603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
117703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
117803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
117903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
118003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
118103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
118203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
118303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
118403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
118503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
118603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
118703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
118880f78b773f92048944a850efb7b60629643370cdPraveen Chavanoff64_t MPEG4Writer::addMultipleLengthPrefixedSamples_l(MediaBuffer *buffer) {
118980f78b773f92048944a850efb7b60629643370cdPraveen Chavan    off64_t old_offset = mOffset;
119080f78b773f92048944a850efb7b60629643370cdPraveen Chavan
119180f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const size_t kExtensionNALSearchRange = 64; // bytes to look for non-VCL NALUs
119280f78b773f92048944a850efb7b60629643370cdPraveen Chavan
119380f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *dataStart = (const uint8_t *)buffer->data() + buffer->range_offset();
119480f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *currentNalStart = dataStart;
119580f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *nextNalStart;
119680f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *data = dataStart;
119780f78b773f92048944a850efb7b60629643370cdPraveen Chavan    size_t nextNalSize;
119880f78b773f92048944a850efb7b60629643370cdPraveen Chavan    size_t searchSize = buffer->range_length() > kExtensionNALSearchRange ?
119980f78b773f92048944a850efb7b60629643370cdPraveen Chavan                   kExtensionNALSearchRange : buffer->range_length();
120080f78b773f92048944a850efb7b60629643370cdPraveen Chavan
120180f78b773f92048944a850efb7b60629643370cdPraveen Chavan    while (getNextNALUnit(&data, &searchSize, &nextNalStart,
120280f78b773f92048944a850efb7b60629643370cdPraveen Chavan            &nextNalSize, true) == OK) {
120310cc12c4eec9ff974edb72f9140b05762fa50907Lajos Molnar        size_t currentNalSize = nextNalStart - currentNalStart - 4 /* strip start-code */;
120480f78b773f92048944a850efb7b60629643370cdPraveen Chavan        MediaBuffer *nalBuf = new MediaBuffer((void *)currentNalStart, currentNalSize);
120580f78b773f92048944a850efb7b60629643370cdPraveen Chavan        addLengthPrefixedSample_l(nalBuf);
120680f78b773f92048944a850efb7b60629643370cdPraveen Chavan        nalBuf->release();
120780f78b773f92048944a850efb7b60629643370cdPraveen Chavan
120880f78b773f92048944a850efb7b60629643370cdPraveen Chavan        currentNalStart = nextNalStart;
120980f78b773f92048944a850efb7b60629643370cdPraveen Chavan    }
121080f78b773f92048944a850efb7b60629643370cdPraveen Chavan
121180f78b773f92048944a850efb7b60629643370cdPraveen Chavan    size_t currentNalOffset = currentNalStart - dataStart;
121280f78b773f92048944a850efb7b60629643370cdPraveen Chavan    buffer->set_range(buffer->range_offset() + currentNalOffset,
121380f78b773f92048944a850efb7b60629643370cdPraveen Chavan            buffer->range_length() - currentNalOffset);
121480f78b773f92048944a850efb7b60629643370cdPraveen Chavan    addLengthPrefixedSample_l(buffer);
121580f78b773f92048944a850efb7b60629643370cdPraveen Chavan
121680f78b773f92048944a850efb7b60629643370cdPraveen Chavan    return old_offset;
121780f78b773f92048944a850efb7b60629643370cdPraveen Chavan}
121880f78b773f92048944a850efb7b60629643370cdPraveen Chavan
1219c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
1220c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
122130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
122230ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
122303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1224b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mUse4ByteNalLength) {
1225b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 24;
1226c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1227b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 16) & 0xff;
1228c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1229b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 8) & 0xff;
1230c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1231b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
1232c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1233c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong
1234c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd,
1235c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              (const uint8_t *)buffer->data() + buffer->range_offset(),
1236c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              length);
1237b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
1238b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 4;
1239b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
124043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_LT(length, 65536);
124130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1242b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 8;
1243c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1244b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
1245c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1246c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length);
1247b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 2;
1248b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
124930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
125030ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
125130ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
125230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
12537837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write(
1254674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        const void *ptr, size_t size, size_t nmemb) {
12557837c17063a4c50bc856ba59418516fdab731de7James Dong
12567837c17063a4c50bc856ba59418516fdab731de7James Dong    const size_t bytes = size * nmemb;
12577837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
12587b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
1259c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
12601acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        if (moovBoxSize > mEstimatedMoovBoxSize) {
12617b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // The reserved moov box at the beginning of the file
12627b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // is not big enough. Moov box should be written to
12637b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // the end of the file from now on, but not to the
12647b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // in-memory cache.
12657b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
12667b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // We write partial moov box that is in the memory to
12677b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // the file first.
1268c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            for (List<off64_t>::iterator it = mBoxes.begin();
12697837c17063a4c50bc856ba59418516fdab731de7James Dong                 it != mBoxes.end(); ++it) {
12707837c17063a4c50bc856ba59418516fdab731de7James Dong                (*it) += mOffset;
12717837c17063a4c50bc856ba59418516fdab731de7James Dong            }
1272674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            lseek64(mFd, mOffset, SEEK_SET);
1273674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset);
12747b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            ::write(mFd, ptr, bytes);
12757837c17063a4c50bc856ba59418516fdab731de7James Dong            mOffset += (bytes + mMoovBoxBufferOffset);
12767b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
12777b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // All subsequent moov box content will be written
12787b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // to the end of the file.
12797837c17063a4c50bc856ba59418516fdab731de7James Dong            mWriteMoovBoxToMemory = false;
12807837c17063a4c50bc856ba59418516fdab731de7James Dong        } else {
12817837c17063a4c50bc856ba59418516fdab731de7James Dong            memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
12827837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset += bytes;
12837837c17063a4c50bc856ba59418516fdab731de7James Dong        }
12847837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1285674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        ::write(mFd, ptr, size * nmemb);
12867837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset += bytes;
12877837c17063a4c50bc856ba59418516fdab731de7James Dong    }
12887837c17063a4c50bc856ba59418516fdab731de7James Dong    return bytes;
12897837c17063a4c50bc856ba59418516fdab731de7James Dong}
12907837c17063a4c50bc856ba59418516fdab731de7James Dong
1291e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::beginBox(uint32_t id) {
1292e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    mBoxes.push_back(mWriteMoovBoxToMemory?
1293e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            mMoovBoxBufferOffset: mOffset);
1294e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
1295e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0);
1296e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(id);
1297e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
1298e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
129920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
13000c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(fourcc), 4);
130120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13027837c17063a4c50bc856ba59418516fdab731de7James Dong    mBoxes.push_back(mWriteMoovBoxToMemory?
13037837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset: mOffset);
130420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
130520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
130620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
130720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
130820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
130920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
13100c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
131120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1312c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = *--mBoxes.end();
131320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
131420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13157837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
13167837c17063a4c50bc856ba59418516fdab731de7James Dong       int32_t x = htonl(mMoovBoxBufferOffset - offset);
13177837c17063a4c50bc856ba59418516fdab731de7James Dong       memcpy(mMoovBoxBuffer + offset, &x, 4);
13187837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1319c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, offset, SEEK_SET);
13207837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mOffset - offset);
13217837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset -= 4;
1322c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
13237837c17063a4c50bc856ba59418516fdab731de7James Dong    }
132420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
132520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
132620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
1327674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 1);
132820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
132920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
133020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
133120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
1332674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 2);
133320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
133420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
133520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
133620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
1337674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 4);
133820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
133920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
134020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
134120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
1342674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 8);
134320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
134420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
134520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
134620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
1347674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, n + 1);
134820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
134920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
135020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
13510c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(s), 4);
1352674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, 4);
135320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
135420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
135507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
135607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format
135707b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) {
135807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
135907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
136007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
136107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
136207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[9];
136307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
136407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
136507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%c%.2d.", sign, wholePart);
136607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
136707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%+.2d.", wholePart);
136807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
136907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
137007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
137107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
137207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
137307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
137407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
137507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[4], 5, "%.4d", fractionalPart);
137607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
137707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
137807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 8);
137907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
138007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
138107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format
138207b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) {
138307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
138407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
138507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
138607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
138707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[10];
138807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
138907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
139007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%c%.3d.", sign, wholePart);
139107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
139207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%+.3d.", wholePart);
139307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
139407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
139507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
139607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
139707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
139807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
139907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
140007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[5], 5, "%.4d", fractionalPart);
140107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
140207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
140307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 9);
140407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
140507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
140607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
140707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
140807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and
140907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000.
141007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and
141107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180]
141207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
141307b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) {
141407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Is latitude or longitude out of range?
141507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (latitudex10000 < -900000 || latitudex10000 > 900000 ||
141607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        longitudex10000 < -1800000 || longitudex10000 > 1800000) {
141707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        return BAD_VALUE;
141807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
141907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
142007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLatitudex10000 = latitudex10000;
142107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLongitudex10000 = longitudex10000;
142207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mAreGeoTagsAvailable = true;
14237c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += 30;
142407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    return OK;
142507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
142607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
1427e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangstatus_t MPEG4Writer::setCaptureRate(float captureFps) {
1428e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    if (captureFps <= 0.0f) {
1429e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        return BAD_VALUE;
1430e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
1431e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
14327c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMetaKeys->setFloat(kMetaKey_CaptureFps, captureFps);
14337c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += sizeof(kMetaKey_CaptureFps) + 4 + 32;
14347c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
1435e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    return OK;
1436e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
1437e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
14384dbff11975e737482537e1636051690188f3fbc4Praveen Chavanstatus_t MPEG4Writer::setTemporalLayerCount(uint32_t layerCount) {
14394dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    if (layerCount > 9) {
14404dbff11975e737482537e1636051690188f3fbc4Praveen Chavan        return BAD_VALUE;
14414dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    }
14424dbff11975e737482537e1636051690188f3fbc4Praveen Chavan
14434dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    if (layerCount > 0) {
14444dbff11975e737482537e1636051690188f3fbc4Praveen Chavan        mMetaKeys->setInt32(kMetaKey_TemporalLayerCount, layerCount);
14454dbff11975e737482537e1636051690188f3fbc4Praveen Chavan        mMoovExtraSize += sizeof(kMetaKey_TemporalLayerCount) + 4 + 32;
14464dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    }
14474dbff11975e737482537e1636051690188f3fbc4Praveen Chavan
14484dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    return OK;
14494dbff11975e737482537e1636051690188f3fbc4Praveen Chavan}
14504dbff11975e737482537e1636051690188f3fbc4Praveen Chavan
145120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
1452674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(data, 1, size);
145320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
145420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
145578a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const {
145678a1a286f736888ae7af8860b2c424af0d978848James Dong    return mStreamableFile;
145778a1a286f736888ae7af8860b2c424af0d978848James Dong}
145878a1a286f736888ae7af8860b2c424af0d978848James Dong
1459d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() {
1460d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1461d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeLimitBytes == 0) {
1462d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1463d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1464d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1465956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
1466d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1467d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1468d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
1469d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
14701f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
147177e8ae9967a078770416619e99ddb5b010def312James Dong    if (!mStreamableFile) {
147277e8ae9967a078770416619e99ddb5b010def312James Dong        // Add 1024 bytes as error tolerance
147377e8ae9967a078770416619e99ddb5b010def312James Dong        return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes;
147477e8ae9967a078770416619e99ddb5b010def312James Dong    }
1475acd234bba9f048971d66890009eeff9a8db94be3James Dong    // Be conservative in the estimate: do not exceed 95% of
1476acd234bba9f048971d66890009eeff9a8db94be3James Dong    // the target file limit. For small target file size limit, though,
1477acd234bba9f048971d66890009eeff9a8db94be3James Dong    // this will not help.
1478acd234bba9f048971d66890009eeff9a8db94be3James Dong    return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100);
1479d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1480d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1481d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() {
1482d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1483d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationLimitUs == 0) {
1484d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1485d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1486d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1487d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1488d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1489d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
1490d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            return true;
1491d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1492d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1493d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return false;
1494d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1495d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
149625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
149725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
149825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
149925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
150025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
150125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
150225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
150325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
150425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
150525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
150625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
150725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
150825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
1509f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
1510a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGI("setStartTimestampUs: %" PRId64, timeUs);
151143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(timeUs, 0ll);
15123c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
1513065d1aff96818df54456053f1574aec8a234d0deJames Dong    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
1514f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimestampUs = timeUs;
1515a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Earliest track starting time: %" PRId64, mStartTimestampUs);
15163c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    }
15173c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
15183c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
1519f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() {
15203c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
15213c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    return mStartTimestampUs;
15223c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
15233c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
152458ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() {
152558ae9c530247668f8af36e30d228c716c226b3d4James Dong    Mutex::Autolock autolock(mLock);
152658ae9c530247668f8af36e30d228c716c226b3d4James Dong    return mTracks.size();
152758ae9c530247668f8af36e30d228c716c226b3d4James Dong}
152858ae9c530247668f8af36e30d228c716c226b3d4James Dong
152920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
153020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
153120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
1532b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen        MPEG4Writer *owner, const sp<IMediaSource> &source, size_t trackId)
153320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
153425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
153520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
153620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
1537a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
1538a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mResumed(false),
1539eaae38445a340c4857c1c5569475879a728e63b7James Dong      mStarted(false),
15409db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang      mIsMalformed(false),
1541bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong      mTrackId(trackId),
1542c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong      mTrackDurationUs(0),
1543956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mEstimatedTrackSizeBytes(0),
1544be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong      mSamplesHaveSameSize(true),
1545c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mStszTableEntries(new ListTableEntries<uint32_t, 1>(1000)),
1546c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mStcoTableEntries(new ListTableEntries<uint32_t, 1>(1000)),
1547c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mCo64TableEntries(new ListTableEntries<off64_t, 1>(1000)),
1548c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mStscTableEntries(new ListTableEntries<uint32_t, 3>(1000)),
1549c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mStssTableEntries(new ListTableEntries<uint32_t, 1>(1000)),
1550c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mSttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)),
1551c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mCttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)),
155220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
155325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
1554548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
155513f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mReachedEOS(false),
155613f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mRotation(0) {
155719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    getCodecSpecificDataFromInputFormatIfPossible();
15588f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
15591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    const char *mime;
15601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMeta->findCString(kKeyMIMEType, &mime);
15611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
15629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mIsHevc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC);
15631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAudio = !strncasecmp(mime, "audio/", 6);
15641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
15651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
15661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1567b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar    // store temporal layer count
1568b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar    if (!mIsAudio) {
1569b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar        int32_t count;
1570b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar        if (mMeta->findInt32(kKeyTemporalLayerCount, &count) && count > 1) {
1571b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar            mOwner->setTemporalLayerCount(count);
1572b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar        }
1573b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar    }
1574b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar
1575c059860c73678a202bfa33062723e8f82fb779d9James Dong    setTimeScale();
1576c059860c73678a202bfa33062723e8f82fb779d9James Dong}
1577c059860c73678a202bfa33062723e8f82fb779d9James Dong
15781f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() {
15791f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1580c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t stcoBoxCount = (mOwner->use32BitFileOffset()
1581c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                            ? mStcoTableEntries->count()
1582c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                            : mCo64TableEntries->count());
1583c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    int64_t stcoBoxSizeBytes = stcoBoxCount * 4;
1584c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4);
15851f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
158678a1a286f736888ae7af8860b2c424af0d978848James Dong    mEstimatedTrackSizeBytes = mMdatSizeBytes;  // media data size
158778a1a286f736888ae7af8860b2c424af0d978848James Dong    if (!mOwner->isFileStreamable()) {
158878a1a286f736888ae7af8860b2c424af0d978848James Dong        // Reserved free space is not large enough to hold
158978a1a286f736888ae7af8860b2c424af0d978848James Dong        // all meta data and thus wasted.
1590c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 +  // stsc box size
1591c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mStssTableEntries->count() * 4 +   // stss box size
1592c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mSttsTableEntries->count() * 8 +   // stts box size
1593c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mCttsTableEntries->count() * 8 +   // ctts box size
159478a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stcoBoxSizeBytes +           // stco box size
159578a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stszBoxSizeBytes;            // stsz box size
159678a1a286f736888ae7af8860b2c424af0d978848James Dong    }
15971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
15981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
15991f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry(
16001f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        size_t chunkId, size_t sampleId) {
16011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1602c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(chunkId));
1603c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(sampleId));
1604c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(1));
16051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
16061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
16071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) {
1608c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->add(htonl(sampleId));
16091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
16101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
16111f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry(
161279761ab096f57c3027fad9556c2bc436672d614eJames Dong        size_t sampleCount, int32_t duration) {
16131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
16145a217fba010e801c255503602bda4b86ac5a6ac9James Dong    if (duration == 0) {
1615377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGW("0-duration samples found: %zu", sampleCount);
16165a217fba010e801c255503602bda4b86ac5a6ac9James Dong    }
1617c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(sampleCount));
1618c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(duration));
16191f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
16201f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1621965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry(
1622965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        size_t sampleCount, int32_t duration) {
1623965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1624965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if (mIsAudio) {
1625965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
1626965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
1627c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(sampleCount));
1628c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(duration));
1629965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
1630965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1631c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) {
1632c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mOwner->use32BitFileOffset()) {
1633c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t value = offset;
1634c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->add(htonl(value));
1635c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
1636c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->add(hton64(offset));
1637c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    }
16381f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
16391f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1640c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() {
16413856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setTimeScale");
1642c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Default time scale
1643c059860c73678a202bfa33062723e8f82fb779d9James Dong    mTimeScale = 90000;
1644c059860c73678a202bfa33062723e8f82fb779d9James Dong
1645c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mIsAudio) {
1646c059860c73678a202bfa33062723e8f82fb779d9James Dong        // Use the sampling rate as the default time scale for audio track.
1647c059860c73678a202bfa33062723e8f82fb779d9James Dong        int32_t sampleRate;
1648c059860c73678a202bfa33062723e8f82fb779d9James Dong        bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
1649c059860c73678a202bfa33062723e8f82fb779d9James Dong        CHECK(success);
1650c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = sampleRate;
1651c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1652c059860c73678a202bfa33062723e8f82fb779d9James Dong
1653c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If someone would like to overwrite the timescale, use user-supplied value.
1654c059860c73678a202bfa33062723e8f82fb779d9James Dong    int32_t timeScale;
1655c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
1656c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = timeScale;
1657c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1658c059860c73678a202bfa33062723e8f82fb779d9James Dong
165943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
166019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber}
166119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
166219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
166319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    const char *mime;
166419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
166519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
16669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    uint32_t type;
16679aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const void *data = NULL;
16689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t size = 0;
166919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
16709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mMeta->findData(kKeyAVCC, &type, &data, &size);
16719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
16729aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mMeta->findData(kKeyHVCC, &type, &data, &size);
167319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
167419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
167519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
167619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            ESDS esds(data, size);
16779aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            if (esds.getCodecSpecificInfo(&data, &size) != OK) {
16789aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                data = NULL;
16799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                size = 0;
168019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            }
168119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
168219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
16839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (data != NULL && copyCodecSpecificData((uint8_t *)data, size) == OK) {
16849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mGotAllCodecSpecificData = true;
16859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
168620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
168720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
168820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
168920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
169020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1691c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStszTableEntries;
1692c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStcoTableEntries;
1693c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCo64TableEntries;
1694c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStscTableEntries;
1695c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mSttsTableEntries;
1696c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStssTableEntries;
1697c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCttsTableEntries;
1698c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
1699c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries = NULL;
1700c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStcoTableEntries = NULL;
1701c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCo64TableEntries = NULL;
1702c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries = NULL;
1703c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries = NULL;
1704c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries = NULL;
1705c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries = NULL;
1706c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
170720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
170820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
170920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
171020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
171120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
171220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
171393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
17143856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("initTrackingProgressStatus");
171593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mPreviousTrackTimeUs = -1;
171693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackingProgressStatus = false;
171793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
171893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    {
171993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeUs;
172093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
1721a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGV("Receive request to track progress status for every %" PRId64 " us", timeUs);
172293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackEveryTimeDurationUs = timeUs;
172393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackingProgressStatus = true;
172493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
172593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
172693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
172793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
17281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static
17291c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) {
17303856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("ThreadWrapper: %p", me);
17311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
17321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    writer->threadFunc();
17331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return NULL;
17341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
17351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17361c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) {
17373856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk: %p", chunk.mTrack);
17381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Mutex::Autolock autolock(mLock);
17391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK_EQ(mDone, false);
17401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
17421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
17431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (chunk.mTrack == it->mTrack) {  // Found owner
17451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            it->mChunks.push_back(chunk);
17461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.signal();
17471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            return;
17481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
17491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
17501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
175143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK(!"Received a chunk for a unknown track");
17521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
17531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1754fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) {
1755a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("writeChunkToFile: %" PRId64 " from %s track",
17565410afcbb0af5d29d9f710a1c2978c500f9792dcPannag Sanketi        chunk->mTimeStampUs, chunk->mTrack->isAudio()? "audio": "video");
1757fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1758fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    int32_t isFirstSample = true;
1759fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    while (!chunk->mSamples.empty()) {
1760fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        List<MediaBuffer *>::iterator it = chunk->mSamples.begin();
1761fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
17629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        off64_t offset = (chunk->mTrack->isAvc() || chunk->mTrack->isHevc())
176380f78b773f92048944a850efb7b60629643370cdPraveen Chavan                                ? addMultipleLengthPrefixedSamples_l(*it)
1764fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong                                : addSample_l(*it);
1765fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1766fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (isFirstSample) {
1767fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            chunk->mTrack->addChunkOffset(offset);
1768fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            isFirstSample = false;
17691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
17701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it)->release();
17721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it) = NULL;
1773fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        chunk->mSamples.erase(it);
17741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1775fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    chunk->mSamples.clear();
17761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
17771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1778fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() {
17793856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeAllChunks");
17801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    size_t outstandingChunks = 0;
178170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    Chunk chunk;
178270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    while (findChunkToWrite(&chunk)) {
1783e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong        writeChunkToFile(&chunk);
178470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        ++outstandingChunks;
17851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
178670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
178770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    sendSessionSummary();
178870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
17891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mChunkInfos.clear();
1790377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    ALOGD("%zu chunks are written in the last batch", outstandingChunks);
17911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
17921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1793fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) {
17943856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("findChunkToWrite");
17951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
17971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Track *track = NULL;
17981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
17991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
18001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (!it->mChunks.empty()) {
18011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            List<Chunk>::iterator chunkIt = it->mChunks.begin();
18021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (chunkIt->mTimeStampUs < minTimestampUs) {
18031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                minTimestampUs = chunkIt->mTimeStampUs;
18041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                track = it->mTrack;
18051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            }
18061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
18071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
18081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (track == NULL) {
18103856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Nothing to be written after all");
1811fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        return false;
18121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
18131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mIsFirstChunk) {
18151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsFirstChunk = false;
18161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1817fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
18181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
18191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
18201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it->mTrack == track) {
1821fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            *chunk = *(it->mChunks.begin());
1822fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            it->mChunks.erase(it->mChunks.begin());
1823fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            CHECK_EQ(chunk->mTrack, track);
182470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
182570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t interChunkTimeUs =
182670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                chunk->mTimeStampUs - it->mPrevChunkTimestampUs;
182770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            if (interChunkTimeUs > it->mPrevChunkTimestampUs) {
182870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs = interChunkTimeUs;
182970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            }
183070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
1831fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            return true;
18321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
18331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1834fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1835fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    return false;
18361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
18371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18381c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() {
18393856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("threadFunc");
18401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1841a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0);
1842fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1843fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    Mutex::Autolock autoLock(mLock);
18441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mDone) {
1845fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        Chunk chunk;
1846fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        bool chunkFound = false;
1847fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1848fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) {
18491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.wait(mLock);
18501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
18511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1852de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // In real time recording mode, write without holding the lock in order
1853de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // to reduce the blocking time for media track threads.
1854de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // Otherwise, hold the lock until the existing chunks get written to the
1855de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // file.
1856fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (chunkFound) {
1857de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            if (mIsRealTimeRecording) {
1858de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui                mLock.unlock();
1859de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            }
1860fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            writeChunkToFile(&chunk);
1861de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            if (mIsRealTimeRecording) {
1862de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui                mLock.lock();
1863de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            }
1864fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        }
18651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1866fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1867fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    writeAllChunks();
18681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
18691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18701c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() {
18713856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("startWriterThread");
18721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mDone = false;
18741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsFirstChunk = true;
1875e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    mDriftTimeUs = 0;
18761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<Track *>::iterator it = mTracks.begin();
18771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mTracks.end(); ++it) {
18781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        ChunkInfo info;
18791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        info.mTrack = *it;
188070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mPrevChunkTimestampUs = 0;
188170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mMaxInterChunkDurUs = 0;
18821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.push_back(info);
18831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
18841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_t attr;
18861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_init(&attr);
18871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
18881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_create(&mThread, &attr, ThreadWrapper, this);
18891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_destroy(&attr);
1890411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = true;
18911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
18921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
18931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
189593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) {
1896a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (!mDone && mPaused) {
1897a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mPaused = false;
1898a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mResumed = true;
1899a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
1900a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
190125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
190293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t startTimeUs;
190319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
190419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        startTimeUs = 0;
190519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
190670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    mStartTimeRealUs = startTimeUs;
190719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
190813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t rotationDegrees;
190913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) {
191013f6284305e4b27395a23db7882d670bdb1bcae1James Dong        mRotation = rotationDegrees;
191113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
191213f6284305e4b27395a23db7882d670bdb1bcae1James Dong
191393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    initTrackingProgressStatus(params);
191493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
1915f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    sp<MetaData> meta = new MetaData;
1916de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) {
1917a472613aec322e25891abf5c77bf3f7e3c244920James Dong        /*
1918a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * This extra delay of accepting incoming audio/video signals
1919a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * helps to align a/v start time at the beginning of a recording
1920a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * session, and it also helps eliminate the "recording" sound for
1921a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * camcorder applications.
1922a472613aec322e25891abf5c77bf3f7e3c244920James Dong         *
192386b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * If client does not set the start time offset, we fall back to
192486b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * use the default initial delay value.
1925a472613aec322e25891abf5c77bf3f7e3c244920James Dong         */
192686b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
192786b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
192886b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
192986b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
193086b7f47aa7482424cf8fd248f1315311919be3b0James Dong        startTimeUs += startTimeOffsetUs;
1931a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Start time offset: %" PRId64 " us", startTimeOffsetUs);
1932a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
1933a472613aec322e25891abf5c77bf3f7e3c244920James Dong
1934f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    meta->setInt64(kKeyTime, startTimeUs);
1935a472613aec322e25891abf5c77bf3f7e3c244920James Dong
1936f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    status_t err = mSource->start(meta.get());
193725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
193825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
193925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
194025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
194120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
194220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
194320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
194420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
194520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
194620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
1947eaae38445a340c4857c1c5569475879a728e63b7James Dong    mStarted = true;
1948c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs = 0;
194925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
1950956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mEstimatedTrackSizeBytes = 0;
19511f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mMdatSizeBytes = 0;
195243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mMaxChunkDurationUs = 0;
1953826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar    mLastDecodingTimeUs = -1;
195420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
195525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
195620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
195725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
195825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
195920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
196020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
196137187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() {
1962a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
196337187916a486504acaf83bea30147eb5fbf46ae5James Dong    return OK;
1964a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
1965a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
196637187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() {
196772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGD("%s track stopping", mIsAudio? "Audio": "Video");
1968eaae38445a340c4857c1c5569475879a728e63b7James Dong    if (!mStarted) {
196929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Stop() called but track is not started");
1970eaae38445a340c4857c1c5569475879a728e63b7James Dong        return ERROR_END_OF_STREAM;
1971eaae38445a340c4857c1c5569475879a728e63b7James Dong    }
1972eaae38445a340c4857c1c5569475879a728e63b7James Dong
197320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
197437187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
197520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
197620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = true;
197720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
197872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGD("%s track source stopping", mIsAudio? "Audio": "Video");
197972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mSource->stop();
198072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGD("%s track source stopped", mIsAudio? "Audio": "Video");
198172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
198220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
198320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
1984377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy));
198537187916a486504acaf83bea30147eb5fbf46ae5James Dong
1986b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("%s track stopped", mIsAudio? "Audio": "Video");
198737187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
198820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
198920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
199025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
199125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
199225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
199325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
199420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
199520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
199620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
199720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
199837187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = track->threadEntry();
1999377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    return (void *)(uintptr_t)err;
200020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
200120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) {
20033856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("getNalUnitType: %d", byte);
20043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // nal_unit_type: 5-bit unsigned integer
20063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *type = (byte & 0x1F);
20073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
20083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet(
20103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
20113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20123856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseParamSet");
20133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    CHECK(type == kNalUnitTypeSeqParamSet ||
20143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong          type == kNalUnitTypePicParamSet);
20153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
201647d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar    const uint8_t *nextStartCode = findNextNalStartCode(data, length);
20173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *paramSetLen = nextStartCode - data;
20183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (*paramSetLen == 0) {
201929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Param set is malformed, since its length is 0");
20203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return NULL;
20213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
20223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    AVCParamSet paramSet(*paramSetLen, data);
20243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (type == kNalUnitTypeSeqParamSet) {
20253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (*paramSetLen < 4) {
202629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Seq parameter set malformed");
20273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return NULL;
20283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mSeqParamSets.empty()) {
20303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc = data[1];
20313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileCompatible = data[2];
20323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mLevelIdc = data[3];
20333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
20343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (mProfileIdc != data[1] ||
20353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mProfileCompatible != data[2] ||
20363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mLevelIdc != data[3]) {
203707b2fbfb40770f3be0f674596f2e51d257c6d2bdLajos Molnar                // COULD DO: set profile/level to the lowest required to support all SPSs
203829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Inconsistent profile/level found in seq parameter sets");
20393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return NULL;
20403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
20413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mSeqParamSets.push_back(paramSet);
20433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    } else {
20443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mPicParamSets.push_back(paramSet);
20453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
20463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return nextStartCode;
20473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
20483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData(
20503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
20513856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("copyAVCCodecSpecificData");
20523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 2 bytes for each of the parameter set length field
20543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // plus the 7 bytes for the header
20559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return copyCodecSpecificData(data, size, 4 + 7);
20569aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
20579aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
20589aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyHEVCCodecSpecificData(
20599aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size) {
20609aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ALOGV("copyHEVCCodecSpecificData");
20619aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
20629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Min length of HEVC CSD is 23. (ISO/IEC 14496-15:2014 Chapter 8.3.3.1.2)
20639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return copyCodecSpecificData(data, size, 23);
20649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
20659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
20669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyCodecSpecificData(
20679aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size, size_t minLength) {
20689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (size < minLength) {
2069377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGE("Codec specific data length too short: %zu", size);
20703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return ERROR_MALFORMED;
20713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
20723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificData = malloc(size);
20749aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
20759aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
20769aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
20779aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
20789aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificDataSize = size;
20793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    memcpy(mCodecSpecificData, data, size);
20803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
20813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
20823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData(
20843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
20853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20863856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseAVCCodecSpecificData");
20873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data starts with a start code.
20883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // SPS and PPS are separated with start codes.
20893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Also, SPS must come before PPS
20903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t type = kNalUnitTypeSeqParamSet;
20913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotSps = false;
20923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotPps = false;
20933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *tmp = data;
20943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = data;
20953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = size;
20963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t paramSetLen = 0;
20973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = 0;
20983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
20993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        getNalUnitType(*(tmp + 4), &type);
21003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (type == kNalUnitTypeSeqParamSet) {
21013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (gotPps) {
210229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
21033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
21043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
21053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
21063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotSps = true;
21073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
21083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
21093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else if (type == kNalUnitTypePicParamSet) {
21103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
211129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
21123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
21133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
21143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotPps) {
21153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotPps = true;
21163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
21173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
21183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
211929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Only SPS and PPS Nal units are expected");
21203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
21213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
21223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nextStartCode == NULL) {
21243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
21253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
21263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Move on to find the next parameter set
21283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft -= nextStartCode - tmp;
21293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        tmp = nextStartCode;
21303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mCodecSpecificDataSize += (2 + paramSetLen);
21313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
21323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
21343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of seq parameter sets
21353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nSeqParamSets = mSeqParamSets.size();
21363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets == 0) {
213729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find sequence parameter set");
21383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
21393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
21403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets > 0x1F) {
2142377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets);
21433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
21443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
21453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
21463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
21483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of pic parameter sets
21493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nPicParamSets = mPicParamSets.size();
21503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets == 0) {
215129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find picture parameter set");
21523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
21533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
21543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets > 0xFF) {
2155377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets);
21563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
21573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
21583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
21591374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME:
21601374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above
21611374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0
21621374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0
21633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
21643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the profiles
21653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // These profiles requires additional parameter set extensions
21663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mProfileIdc == 100 || mProfileIdc == 110 ||
21673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc == 122 || mProfileIdc == 144) {
216829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
21693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return BAD_VALUE;
21703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
21713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
21721374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif
21733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
21743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
2175548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
217603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
217703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
2178548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
217903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
218029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Already have codec specific data");
218103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
218203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
218303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
21843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4) {
2185377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGE("Codec specific data length too short: %zu", size);
218603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
218703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
218803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
21893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data is in the form of AVCCodecSpecificData
21903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (memcmp("\x00\x00\x00\x01", data, 4)) {
21913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return copyAVCCodecSpecificData(data, size);
219203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
219303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
21943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (parseAVCCodecSpecificData(data, size) != OK) {
219503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
219603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
219703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
21983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // ISO 14496-15: AVC file format
21993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize += 7;  // 7 more bytes in the header
220003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
22019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
22029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mCodecSpecificDataSize = 0;
22039aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
22049aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
22059aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
220603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
22073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = 1;                     // version
22083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[1] = mProfileIdc;           // profile indication
22093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[2] = mProfileCompatible;    // profile compatibility
22103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[3] = mLevelIdc;
221103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
22123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
2213b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mOwner->useNalLengthFour()) {
2214b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 3;  // length size == 4 bytes
2215b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
2216b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 1;  // length size == 2 bytes
2217b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
221803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
22193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 3-bit '111' followed by 5-bit numSequenceParameterSets
22203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nSequenceParamSets = mSeqParamSets.size();
22213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[5] = 0xe0 | nSequenceParamSets;
22223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 6;
22233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
22243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mSeqParamSets.end(); ++it) {
22253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit sequence parameter set length
22263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t seqParamSetLength = it->mLength;
22273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = seqParamSetLength >> 8;
22283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = seqParamSetLength & 0xff;
22293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // SPS NAL unit (sequence parameter length bytes)
22313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, seqParamSetLength);
22323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + seqParamSetLength);
22333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
22343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 8-bit nPictureParameterSets
22363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nPictureParamSets = mPicParamSets.size();
22373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = nPictureParamSets;
22383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 1;
22393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
22403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mPicParamSets.end(); ++it) {
22413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit picture parameter set length
22423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t picParamSetLength = it->mLength;
22433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = picParamSetLength >> 8;
22443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = picParamSetLength & 0xff;
22453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // PPS Nal unit (picture parameter set length bytes)
22473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, picParamSetLength);
22483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + picParamSetLength);
22493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
225003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
225103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
225203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
225303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
22549aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::parseHEVCCodecSpecificData(
22569aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size, HevcParameterSets &paramSets) {
22579aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22589aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ALOGV("parseHEVCCodecSpecificData");
22599aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const uint8_t *tmp = data;
22609aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const uint8_t *nextStartCode = data;
22619aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t bytesLeft = size;
22629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
226347d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar        nextStartCode = findNextNalStartCode(tmp + 4, bytesLeft - 4);
22649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        status_t err = paramSets.addNalUnit(tmp + 4, (nextStartCode - tmp) - 4);
22659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (err != OK) {
22669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
22679aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
22689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22699aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        // Move on to find the next parameter set
22709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        bytesLeft -= nextStartCode - tmp;
22719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        tmp = nextStartCode;
22729aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
22739aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22749aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t csdSize = 23;
22759aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const size_t numNalUnits = paramSets.getNumNalUnits();
22769aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    for (size_t i = 0; i < ARRAY_SIZE(kMandatoryHevcNalUnitTypes); ++i) {
22779aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        int type = kMandatoryHevcNalUnitTypes[i];
22789aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        size_t numParamSets = paramSets.getNumNalUnitsOfType(type);
22799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (numParamSets == 0) {
22809aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            ALOGE("Cound not find NAL unit of type %d", type);
22819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
22829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
22839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
22849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    for (size_t i = 0; i < ARRAY_SIZE(kHevcNalUnitTypes); ++i) {
22859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        int type = kHevcNalUnitTypes[i];
22869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        size_t numParamSets = paramSets.getNumNalUnitsOfType(type);
22879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (numParamSets > 0xffff) {
22889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            ALOGE("Too many seq parameter sets (%zu) found", numParamSets);
22899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
22909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
22919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        csdSize += 3;
22929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        for (size_t j = 0; j < numNalUnits; ++j) {
22939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            if (paramSets.getType(j) != type) {
22949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                continue;
22959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            }
22969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            csdSize += 2 + paramSets.getSize(j);
22979aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
22989aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
22999aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificDataSize = csdSize;
23009aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return OK;
23019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
23029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
23039aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::makeHEVCCodecSpecificData(
23049aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size) {
23059aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
23069aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData != NULL) {
23079aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Already have codec specific data");
23089aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
23099aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
23109aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
23119aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (size < 4) {
23129aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Codec specific data length too short: %zu", size);
23139aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
23149aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
23159aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
23169aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Data is in the form of HEVCCodecSpecificData
23179aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (memcmp("\x00\x00\x00\x01", data, 4)) {
23189aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return copyHEVCCodecSpecificData(data, size);
23199aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
23209aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
23219aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    HevcParameterSets paramSets;
23229aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (parseHEVCCodecSpecificData(data, size, paramSets) != OK) {
23233d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim        ALOGE("failed parsing codec specific data");
23249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
23259aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
23269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
23279aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificData = malloc(mCodecSpecificDataSize);
23289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
23299aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mCodecSpecificDataSize = 0;
23309aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
23319aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
23329aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
23339aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t err = paramSets.makeHvcc((uint8_t *)mCodecSpecificData,
23343d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim            &mCodecSpecificDataSize, mOwner->useNalLengthFour() ? 4 : 2);
23359aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (err != OK) {
23363d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim        ALOGE("failed constructing HVCC atom");
23379aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return err;
23389aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
23399aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
23409aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return OK;
23419aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
23429aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
2343872a481558350634a3fd5cb67939de288af00ecbJames Dong/*
2344872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that
2345872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information
2346872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio
2347872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger
2348872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5,
2349872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined.
2350872a481558350634a3fd5cb67939de288af00ecbJames Dong */
2351872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) {
2352872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t driftTimeUs = 0;
2353872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) {
2354872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t prevDriftTimeUs = mOwner->getDriftTimeUs();
2355872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1;
2356872a481558350634a3fd5cb67939de288af00ecbJames Dong        mOwner->setDriftTimeUs(timeUs);
2357872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2358872a481558350634a3fd5cb67939de288af00ecbJames Dong}
2359872a481558350634a3fd5cb67939de288af00ecbJames Dong
236037187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() {
236130ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
236213aec890216948b0c364f8f92792129d0335f506James Dong    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
236343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    const bool hasMultipleTracks = (mOwner->numTracks() > 1);
236413aec890216948b0c364f8f92792129d0335f506James Dong    int64_t chunkTimestampUs = 0;
236513aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nChunks = 0;
23667c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar    int32_t nActualFrames = 0;        // frames containing non-CSD data (non-0 length)
236713aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nZeroLengthFrames = 0;
2368965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastTimestampUs = 0;      // Previous sample time stamp
2369965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationUs = 0;       // Between the previous two samples
2370965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t currDurationTicks = 0;    // Timescale based ticks
2371965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationTicks = 0;    // Timescale based ticks
2372965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int32_t sampleCount = 1;          // Sample count in the current stts table entry
2373000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    uint32_t previousSampleSize = 0;  // Size of the previous sample
2374a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t previousPausedDurationUs = 0;
2375965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t timestampUs = 0;
2376000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t cttsOffsetTimeUs = 0;
2377000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t currCttsOffsetTimeTicks = 0;   // Timescale based ticks
2378000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t lastCttsOffsetTimeTicks = -1;  // Timescale based ticks
237943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    int32_t cttsSampleCount = 0;           // Sample count in the current ctts table entry
2380c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t lastSamplesPerChunk = 0;
2381e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2382a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    if (mIsAudio) {
2383a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
2384a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    } else {
2385a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
2386a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    }
2387de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
2388de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (mOwner->isRealTimeRecording()) {
2389de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
2390de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    }
2391985f838934510983d8a887461e98dca60a6e858fJames Dong
2392d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong    sp<MetaData> meta_data;
239320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
239493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t err = OK;
239520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
239611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih    const char *trackName = mIsAudio ? "Audio" : "Video";
239793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    while (!mDone && (err = mSource->read(&buffer)) == OK) {
239820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
239920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
240020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
240113aec890216948b0c364f8f92792129d0335f506James Dong            ++nZeroLengthFrames;
240220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
240320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
240420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2405a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // If the codec specific data has not been received yet, delay pause.
2406a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // After the codec specific data is received, discard what we received
2407a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // when the track is to be paused.
2408a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused && !mResumed) {
2409a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer->release();
2410a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer = NULL;
2411a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            continue;
2412a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2413a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
241430ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
241530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
241603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
241703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
241803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
24197c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // if config format (at track addition) already had CSD, keep that
24207c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // UNLESS we have not received any frames yet.
24217c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // TODO: for now the entire CSD has to come in one frame for encoders, even though
24227c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // they need to be spread out for decoders.
24237c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            if (mGotAllCodecSpecificData && nActualFrames > 0) {
24247c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                ALOGI("ignoring additional CSD for video track after first frame");
24257c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            } else {
24267c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                mMeta = mSource->getFormat(); // get output format after format change
24277c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar
24287c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                if (mIsAvc) {
24297c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    status_t err = makeAVCCodecSpecificData(
24307c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            (const uint8_t *)buffer->data()
24317c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                                + buffer->range_offset(),
24327c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
24337c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    CHECK_EQ((status_t)OK, err);
24347c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                } else if (mIsHevc) {
24357c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    status_t err = makeHEVCCodecSpecificData(
24367c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            (const uint8_t *)buffer->data()
24377c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                                + buffer->range_offset(),
24387c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
24397c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    CHECK_EQ((status_t)OK, err);
24407c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                } else if (mIsMPEG4) {
24417c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    copyCodecSpecificData((const uint8_t *)buffer->data() + buffer->range_offset(),
24427c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
24437c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                }
244430ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
244530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
244630ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
244730ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
244830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
2449548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
245030ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
2451a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2452a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
24537c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar        ++nActualFrames;
24547c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar
2455d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // Make a deep copy of the MediaBuffer and Metadata and release
2456d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // the original as soon as we can
2457d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
2458d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
2459d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                buffer->range_length());
2460d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        copy->set_range(0, buffer->range_length());
2461d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data = new MetaData(*buffer->meta_data().get());
2462d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer->release();
2463d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer = NULL;
2464d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
24659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (mIsAvc || mIsHevc) StripStartcode(copy);
2466e136c3bb38e88315bf8797a464ebf2c788296b22James Dong
2467b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        size_t sampleSize = copy->range_length();
24689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (mIsAvc || mIsHevc) {
2469b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            if (mOwner->useNalLengthFour()) {
2470b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 4;
2471b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            } else {
2472b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 2;
2473b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            }
2474b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        }
2475050b28a593350047845a45a14cc5026221ac1620James Dong
2476d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        // Max file size or duration handling
24771f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mMdatSizeBytes += sampleSize;
24781f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        updateTrackSizeEstimate();
24791f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
2480d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileSizeLimit()) {
2481316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang            ALOGW("Recorded file size exceeds limit %" PRId64 "bytes",
2482316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang                    mOwner->mMaxFileSizeLimitBytes);
2483d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
2484d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            copy->release();
2485d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            mSource->stop();
2486d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2487d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2488d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileDurationLimit()) {
2489316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang            ALOGW("Recorded file duration exceeds limit %" PRId64 "microseconds",
2490316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang                    mOwner->mMaxFileDurationLimitUs);
2491d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
2492d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            copy->release();
2493d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            mSource->stop();
2494d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2495d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2496d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2497050b28a593350047845a45a14cc5026221ac1620James Dong
2498d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        int32_t isSync = false;
2499d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
2500d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
2501d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
2502d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong////////////////////////////////////////////////////////////////////////////////
2503c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (mStszTableEntries->count() == 0) {
250470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mFirstSampleTimeRealUs = systemTime() / 1000;
2505f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimestampUs = timestampUs;
2506f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mOwner->setStartTimestampUs(mStartTimestampUs);
25078428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs = mStartTimestampUs;
25083c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        }
250948c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
2510a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mResumed) {
25118428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
251211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) {
251311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
2514d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang                mSource->stop();
25159db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                mIsMalformed = true;
25169db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                break;
251711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
251811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
25198428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
252011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) {
252111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
2522d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang                mSource->stop();
25239db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                mIsMalformed = true;
25249db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                break;
252511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
252611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
25278428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs += pausedDurationUs - lastDurationUs;
2528a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mResumed = false;
2529a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2530a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2531a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        timestampUs -= previousPausedDurationUs;
253211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
253311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
2534d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            mSource->stop();
25359db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            mIsMalformed = true;
25369db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            break;
253711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        }
253811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2539000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        if (!mIsAudio) {
2540965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            /*
2541965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Composition time: timestampUs
2542965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Decoding time: decodingTimeUs
2543000e18370baae60ffd9f25b509501dd8c26deabfJames Dong             * Composition time offset = composition time - decoding time
2544965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             */
2545965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            int64_t decodingTimeUs;
2546965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
2547965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            decodingTimeUs -= previousPausedDurationUs;
2548826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar
2549826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            // ensure non-negative, monotonic decoding time
2550826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            if (mLastDecodingTimeUs < 0) {
2551826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar                decodingTimeUs = std::max((int64_t)0, decodingTimeUs);
2552826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            } else {
2553826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar                // increase decoding time by at least 1 tick
2554826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar                decodingTimeUs = std::max(
2555826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar                        mLastDecodingTimeUs + divUp(1000000, mTimeScale), decodingTimeUs);
2556826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            }
2557826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar
2558826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            mLastDecodingTimeUs = decodingTimeUs;
2559000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            cttsOffsetTimeUs =
2560000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
256111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) {
256211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
2563d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang                mSource->stop();
25649db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                mIsMalformed = true;
25659db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                break;
256611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
256711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2568965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            timestampUs = decodingTimeUs;
2569a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGV("decoding time: %" PRId64 " and ctts offset time: %" PRId64,
2570000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                timestampUs, cttsOffsetTimeUs);
2571000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2572000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts box table if necessary
2573000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            currCttsOffsetTimeTicks =
2574000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL;
257511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) {
257611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
2577d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang                mSource->stop();
25789db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                mIsMalformed = true;
25799db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                break;
258011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
258111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2582c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 0) {
258343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // Force the first ctts table entry to have one single entry
258443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // so that we can do adjustment for the initial track start
258543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // time offset easily in writeCttsBox().
258643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
258743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                addOneCttsTableEntry(1, currCttsOffsetTimeTicks);
258843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                cttsSampleCount = 0;      // No sample in ctts box is pending
258943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            } else {
259043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) {
259143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
259243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
259343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    cttsSampleCount = 1;  // One sample in ctts box is pending
259443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                } else {
259543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    ++cttsSampleCount;
259643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                }
259743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            }
2598000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2599000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts time offset range
2600c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 0) {
2601000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2602000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2603000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            } else {
2604000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) {
2605000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2606000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) {
2607000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2608000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                }
2609000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            }
2610000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2611965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        }
2612872a481558350634a3fd5cb67939de288af00ecbJames Dong
2613de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        if (mOwner->isRealTimeRecording()) {
2614872a481558350634a3fd5cb67939de288af00ecbJames Dong            if (mIsAudio) {
2615872a481558350634a3fd5cb67939de288af00ecbJames Dong                updateDriftTime(meta_data);
2616e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
2617e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
2618872a481558350634a3fd5cb67939de288af00ecbJames Dong
261911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
262011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
2621d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            mSource->stop();
26229db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            mIsMalformed = true;
26239db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            break;
262411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        }
262511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2626a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("%s media time stamp: %" PRId64 " and previous paused duration %" PRId64,
262711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                trackName, timestampUs, previousPausedDurationUs);
2628c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong        if (timestampUs > mTrackDurationUs) {
2629c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong            mTrackDurationUs = timestampUs;
26303b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        }
26313b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber
26325a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // We need to use the time scale based ticks, rather than the
26335a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // timestamp itself to determine whether we have to use a new
26345a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // stts entry, since we may have rounding errors.
26355a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // The calculation is intended to reduce the accumulated
26365a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // rounding errors.
26375a217fba010e801c255503602bda4b86ac5a6ac9James Dong        currDurationTicks =
26385a217fba010e801c255503602bda4b86ac5a6ac9James Dong            ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
26395a217fba010e801c255503602bda4b86ac5a6ac9James Dong                (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
2640c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (currDurationTicks < 0ll) {
2641f85a83af8c6a98b46c394c32b90b09214a68f3e4Hangyu Kuang            ALOGE("do not support out of order frames (timestamp: %lld < last: %lld for %s track",
2642f85a83af8c6a98b46c394c32b90b09214a68f3e4Hangyu Kuang                    (long long)timestampUs, (long long)lastTimestampUs, trackName);
264311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
26440332fadec6e91c37fe39ab92b2c02922370bc853Hangyu Kuang            mSource->stop();
26459db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            mIsMalformed = true;
26469db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            break;
26478c460498c028888c533ab442be12b6d4b669b965James Dong        }
26488c460498c028888c533ab442be12b6d4b669b965James Dong
264985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // if the duration is different for this sample, see if it is close enough to the previous
265085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // duration that we can fudge it and use the same value, to avoid filling the stts table
265185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // with lots of near-identical entries.
265285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // "close enough" here means that the current duration needs to be adjusted by less
265385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // than 0.1 milliseconds
265485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) {
265585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL
265685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                    + (mTimeScale / 2)) / mTimeScale;
265785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            if (deltaUs > -100 && deltaUs < 100) {
265885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                // use previous ticks, and adjust timestamp as if it was actually that number
265985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                // of ticks
266085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                currDurationTicks = lastDurationTicks;
266185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                timestampUs += deltaUs;
266285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            }
266385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        }
266485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen
2665c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStszTableEntries->add(htonl(sampleSize));
2666c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (mStszTableEntries->count() > 2) {
2667c059860c73678a202bfa33062723e8f82fb779d9James Dong
2668a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // Force the first sample to have its own stts entry so that
2669a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // we can adjust its value later to maintain the A/V sync.
2670c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) {
267179761ab096f57c3027fad9556c2bc436672d614eJames Dong                addOneSttsTableEntry(sampleCount, lastDurationTicks);
2672be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                sampleCount = 1;
2673be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
2674be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                ++sampleCount;
2675be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
2676965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2677be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
2678be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        if (mSamplesHaveSameSize) {
2679c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) {
2680be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSamplesHaveSameSize = false;
2681be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
26828644c14618d30d9e57a69df40ed939986ebf02c4James Dong            previousSampleSize = sampleSize;
2683be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
2684a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("%s timestampUs/lastTimestampUs: %" PRId64 "/%" PRId64,
268511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                trackName, timestampUs, lastTimestampUs);
26868644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastDurationUs = timestampUs - lastTimestampUs;
2687c059860c73678a202bfa33062723e8f82fb779d9James Dong        lastDurationTicks = currDurationTicks;
26888644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastTimestampUs = timestampUs;
268920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2690d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        if (isSync != 0) {
2691c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            addOneStssTableEntry(mStszTableEntries->count());
2692d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        }
2693d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
269493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (mTrackingProgressStatus) {
269593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            if (mPreviousTrackTimeUs <= 0) {
269693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong                mPreviousTrackTimeUs = mStartTimestampUs;
269793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            }
2698faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong            trackProgressStatus(timestampUs);
269993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
270043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        if (!hasMultipleTracks) {
270180f78b773f92048944a850efb7b60629643370cdPraveen Chavan            off64_t offset = (mIsAvc || mIsHevc) ? mOwner->addMultipleLengthPrefixedSamples_l(copy)
270258ae9c530247668f8af36e30d228c716c226b3d4James Dong                                 : mOwner->addSample_l(copy);
2703c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2704c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t count = (mOwner->use32BitFileOffset()
2705c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        ? mStcoTableEntries->count()
2706c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        : mCo64TableEntries->count());
2707c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2708c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (count == 0) {
27091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                addChunkOffset(offset);
271058ae9c530247668f8af36e30d228c716c226b3d4James Dong            }
271158ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy->release();
271258ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy = NULL;
271358ae9c530247668f8af36e30d228c716c226b3d4James Dong            continue;
271458ae9c530247668f8af36e30d228c716c226b3d4James Dong        }
271513aec890216948b0c364f8f92792129d0335f506James Dong
271613aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.push_back(copy);
271713aec890216948b0c364f8f92792129d0335f506James Dong        if (interleaveDurationUs == 0) {
27181f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStscTableEntry(++nChunks, 1);
27191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            bufferChunk(timestampUs);
272013aec890216948b0c364f8f92792129d0335f506James Dong        } else {
272113aec890216948b0c364f8f92792129d0335f506James Dong            if (chunkTimestampUs == 0) {
272213aec890216948b0c364f8f92792129d0335f506James Dong                chunkTimestampUs = timestampUs;
272313aec890216948b0c364f8f92792129d0335f506James Dong            } else {
272443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                int64_t chunkDurationUs = timestampUs - chunkTimestampUs;
272543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                if (chunkDurationUs > interleaveDurationUs) {
272643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    if (chunkDurationUs > mMaxChunkDurationUs) {
272743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                        mMaxChunkDurationUs = chunkDurationUs;
272843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    }
272913aec890216948b0c364f8f92792129d0335f506James Dong                    ++nChunks;
273013aec890216948b0c364f8f92792129d0335f506James Dong                    if (nChunks == 1 ||  // First chunk
2731c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk != mChunkSamples.size()) {
2732c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk = mChunkSamples.size();
2733c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        addOneStscTableEntry(nChunks, lastSamplesPerChunk);
273413aec890216948b0c364f8f92792129d0335f506James Dong                    }
27351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                    bufferChunk(timestampUs);
273613aec890216948b0c364f8f92792129d0335f506James Dong                    chunkTimestampUs = timestampUs;
273713aec890216948b0c364f8f92792129d0335f506James Dong                }
273813aec890216948b0c364f8f92792129d0335f506James Dong            }
273913aec890216948b0c364f8f92792129d0335f506James Dong        }
274013aec890216948b0c364f8f92792129d0335f506James Dong
274120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
274225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
274345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (isTrackMalFormed()) {
2744690f546b0ee548dbfe997df36418e5302ec2d786James Dong        err = ERROR_MALFORMED;
2745f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    }
274645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
2747bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    mOwner->trackProgressStatus(mTrackId, -1, err);
2748be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
274913aec890216948b0c364f8f92792129d0335f506James Dong    // Last chunk
275043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (!hasMultipleTracks) {
2751c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        addOneStscTableEntry(1, mStszTableEntries->count());
275258ae9c530247668f8af36e30d228c716c226b3d4James Dong    } else if (!mChunkSamples.empty()) {
27531f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        addOneStscTableEntry(++nChunks, mChunkSamples.size());
27541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        bufferChunk(timestampUs);
275513aec890216948b0c364f8f92792129d0335f506James Dong    }
275613aec890216948b0c364f8f92792129d0335f506James Dong
2757be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // We don't really know how long the last frame lasts, since
2758be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // there is no frame time after it, just repeat the previous
2759be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // frame's duration.
2760c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() == 1) {
27618f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        lastDurationUs = 0;  // A single sample's duration
276279761ab096f57c3027fad9556c2bc436672d614eJames Dong        lastDurationTicks = 0;
2763be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    } else {
2764be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        ++sampleCount;  // Count for the last sample
2765be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    }
2766a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2767c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() <= 2) {
276879761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(1, lastDurationTicks);
2769a472613aec322e25891abf5c77bf3f7e3c244920James Dong        if (sampleCount - 1 > 0) {
277079761ab096f57c3027fad9556c2bc436672d614eJames Dong            addOneSttsTableEntry(sampleCount - 1, lastDurationTicks);
2771a472613aec322e25891abf5c77bf3f7e3c244920James Dong        }
2772a472613aec322e25891abf5c77bf3f7e3c244920James Dong    } else {
277379761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(sampleCount, lastDurationTicks);
2774a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
2775a472613aec322e25891abf5c77bf3f7e3c244920James Dong
277643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // The last ctts box may not have been written yet, and this
277743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // is to make sure that we write out the last ctts box.
277843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) {
277943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        if (cttsSampleCount > 0) {
278043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
278143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        }
278243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    }
278343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong
2784c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs += lastDurationUs;
278525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
278643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
278743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    sendTrackSummary(hasMultipleTracks);
278843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
2789df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
279011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            count, nZeroLengthFrames, mStszTableEntries->count(), trackName);
2791872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (mIsAudio) {
2792a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Audio track drift time: %" PRId64 " us", mOwner->getDriftTimeUs());
2793872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2794365a963142093a1cd8efdcea76b5f65096a5b115James Dong
279537187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err == ERROR_END_OF_STREAM) {
279637187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
279737187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
279837187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
2799365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
2800365a963142093a1cd8efdcea76b5f65096a5b115James Dong
280145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const {
28029db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang    if (mIsMalformed) {
28039db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang        return true;
28049db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang    }
28059db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang
2806c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() == 0) {                      // no samples written
280729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("The number of recorded samples is 0");
280845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
280945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
281045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
2811c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (!mIsAudio && mStssTableEntries->count() == 0) {  // no sync frames for video
281229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("There are no sync frames for video track");
281345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
281445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
281545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
281645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (OK != checkCodecSpecificData()) {         // no codec specific data
281745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
281845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
281945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
282045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    return false;
282145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong}
282245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
282343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) {
282407ec01904613a0bac32caaa8444b4690998faed7James Dong
282507ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send track summary only if test mode is enabled.
282607ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
282707ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
282807ec01904613a0bac32caaa8444b4690998faed7James Dong    }
282907ec01904613a0bac32caaa8444b4690998faed7James Dong
283043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int trackNum = (mTrackId << 28);
283143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
283243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
283343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE,
283443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mIsAudio? 0: 1);
283543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
283643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
283743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS,
283843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mTrackDurationUs / 1000);
283943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
284043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
284143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES,
2842c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    mStszTableEntries->count());
284343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
284486b7f47aa7482424cf8fd248f1315311919be3b0James Dong    {
284586b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // The system delay time excluding the requested initial delay that
284686b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // is used to eliminate the recording sound.
284786b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
284886b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
284986b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
285086b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
285186b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t initialDelayUs =
285286b7f47aa7482424cf8fd248f1315311919be3b0James Dong            mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs;
285386b7f47aa7482424cf8fd248f1315311919be3b0James Dong
285486b7f47aa7482424cf8fd248f1315311919be3b0James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
285570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS,
285670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    (initialDelayUs) / 1000);
285786b7f47aa7482424cf8fd248f1315311919be3b0James Dong    }
285870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
285907ec01904613a0bac32caaa8444b4690998faed7James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
286007ec01904613a0bac32caaa8444b4690998faed7James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES,
286107ec01904613a0bac32caaa8444b4690998faed7James Dong                    mMdatSizeBytes / 1024);
286207ec01904613a0bac32caaa8444b4690998faed7James Dong
286343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (hasMultipleTracks) {
286443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
286543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS,
286643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mMaxChunkDurationUs / 1000);
286770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
286870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
286970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        if (mStartTimestampUs != moovStartTimeUs) {
287070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
287170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
287270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS,
287370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    startTimeOffsetUs / 1000);
287470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        }
287543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    }
287643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong}
287743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
2878faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
2879a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("trackProgressStatus: %" PRId64 " us", timeUs);
2880c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2881215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    if (mTrackEveryTimeDurationUs > 0 &&
2882215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
2883a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("Fire time tracking progress status at %" PRId64 " us", timeUs);
2884bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err);
288593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        mPreviousTrackTimeUs = timeUs;
288693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
288793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
288893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
2889faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus(
2890bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        size_t trackId, int64_t timeUs, status_t err) {
2891faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    Mutex::Autolock lock(mLock);
2892bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t trackNum = (trackId << 28);
2893faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2894faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Error notification
2895faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Do not consider ERROR_END_OF_STREAM an error
2896faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (err != OK && err != ERROR_END_OF_STREAM) {
2897bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
2898bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL,
2899faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2900faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
2901faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2902faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2903faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (timeUs == -1) {
2904faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send completion notification
2905bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2906bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS,
2907faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2908faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    } else {
2909faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send progress status
2910bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2911bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME,
2912faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               timeUs / 1000);
2913faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2914faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong}
2915faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2916d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) {
2917a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("setDriftTimeUs: %" PRId64 " us", driftTimeUs);
2918e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2919d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    mDriftTimeUs = driftTimeUs;
2920e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2921e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2922e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() {
2923a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("getDriftTimeUs: %" PRId64 " us", mDriftTimeUs);
2924e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2925e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    return mDriftTimeUs;
2926e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2927e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2928de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghuibool MPEG4Writer::isRealTimeRecording() const {
2929de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    return mIsRealTimeRecording;
2930de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui}
2931de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
2932b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() {
2933b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    return mUse4ByteNalLength;
2934b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong}
2935b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
29361c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
29373856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk");
29381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
29391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Chunk chunk(this, timestampUs, mChunkSamples);
29401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mOwner->bufferChunk(chunk);
294113aec890216948b0c364f8f92792129d0335f506James Dong    mChunkSamples.clear();
294220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
294320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29443b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
2945c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    return mTrackDurationUs;
294620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
294720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2948d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
2949d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return mEstimatedTrackSizeBytes;
2950d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
2951d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2952690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const {
2953690f546b0ee548dbfe997df36418e5302ec2d786James Dong    const char *mime;
2954690f546b0ee548dbfe997df36418e5302ec2d786James Dong    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
2955690f546b0ee548dbfe997df36418e5302ec2d786James Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
2956690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
29579aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime) ||
29589aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        !strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
2959690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (!mCodecSpecificData ||
2960690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize <= 0) {
296129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Missing codec specific data");
2962690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2963690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2964690f546b0ee548dbfe997df36418e5302ec2d786James Dong    } else {
2965690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (mCodecSpecificData ||
2966690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize > 0) {
296729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Unexepected codec specific data found");
2968690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2969690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2970690f546b0ee548dbfe997df36418e5302ec2d786James Dong    }
2971690f546b0ee548dbfe997df36418e5302ec2d786James Dong    return OK;
2972690f546b0ee548dbfe997df36418e5302ec2d786James Dong}
2973690f546b0ee548dbfe997df36418e5302ec2d786James Dong
2974b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) {
297520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29763856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("%s track time scale: %d",
29771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsAudio? "Audio": "Video", mTimeScale);
29788f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
2979efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
2980b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("trak");
2981b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeTkhdBox(now);
2982b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("mdia");
2983b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeMdhdBox(now);
2984b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeHdlrBox();
2985b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->beginBox("minf");
2986b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                if (mIsAudio) {
2987b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeSmhdBox();
2988b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                } else {
2989b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeVmhdBox();
2990b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                }
2991b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeDinfBox();
2992b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeStblBox(use32BitOffset);
2993b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->endBox();  // minf
2994b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->endBox();  // mdia
2995b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // trak
2996b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2997b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2998b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) {
2999b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stbl");
3000b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsd");
3001b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);               // version=0, flags=0
3002b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);               // entry count
3003b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
3004b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAudioFourCCBox();
3005b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
3006b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeVideoFourCCBox();
3007b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3008b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsd
3009b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeSttsBox();
3010965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    writeCttsBox();
3011b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!mIsAudio) {
3012b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeStssBox();
3013b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3014b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStszBox();
3015b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStscBox();
3016b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStcoBox(use32BitOffset);
3017b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stbl
3018b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3019b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3020b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() {
3021b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
3022b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
3023b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
30248b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    const char *fourcc = getFourCCForMime(mime);
30258b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (fourcc == NULL) {
302629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
3027b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(!"should not be here, unknown mime type.");
3028b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3029b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
30308b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    mOwner->beginBox(fourcc);        // video format
3031b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3032b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3033b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // data ref index
3034b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
3035b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3036b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
3037b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
3038b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
3039b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3040b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t width, height;
3041b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeyWidth, &width);
3042b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = success && mMeta->findInt32(kKeyHeight, &height);
3043b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
3044b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3045b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(width);
3046b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(height);
3047b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // horiz resolution
3048b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // vert resolution
3049b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3050b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // frame count
3051c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo    mOwner->writeInt8(0);            // compressor string length
3052c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo    mOwner->write("                               ", 31);
3053b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x18);        // depth
3054b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(-1);          // predefined
3055b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3056b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
3057b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4vEsdsBox();
3058b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
3059b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeD263Box();
3060b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
3061b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAvccBox();
30629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
30639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        writeHvccBox();
3064b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3065b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3066b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writePaspBox();
306758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    writeColrBox();
3068b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // mp4v, s263 or avc1
3069b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3070b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
307158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnarvoid MPEG4Writer::Track::writeColrBox() {
307258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    ColorAspects aspects;
307358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    memset(&aspects, 0, sizeof(aspects));
307458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    // TRICKY: using | instead of || because we want to execute all findInt32-s
307558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    if (mMeta->findInt32(kKeyColorPrimaries, (int32_t*)&aspects.mPrimaries)
307658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyTransferFunction, (int32_t*)&aspects.mTransfer)
307758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyColorMatrix, (int32_t*)&aspects.mMatrixCoeffs)
307858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyColorRange, (int32_t*)&aspects.mRange)) {
307958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        int32_t primaries, transfer, coeffs;
308058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        bool fullRange;
308158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        ColorUtils::convertCodecColorAspectsToIsoAspects(
308258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar                aspects, &primaries, &transfer, &coeffs, &fullRange);
308358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->beginBox("colr");
308458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeFourcc("nclx");
308558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(primaries);
308658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(transfer);
308758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(coeffs);
308858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt8(fullRange ? 128 : 0);
308958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->endBox(); // colr
309058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    }
309158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar}
309258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
3093b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() {
3094b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
3095b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
3096b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
30978b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    const char *fourcc = getFourCCForMime(mime);
30988b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (fourcc == NULL) {
309929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
3100b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(!"should not be here, unknown mime type.");
3101b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3102b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3103b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(fourcc);        // audio format
3104b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3105b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3106b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x1);         // data ref index
3107b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3108b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3109b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t nChannels;
3110b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
3111b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(nChannels);   // channel count
3112b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(16);          // sample size
3113b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
3114b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3115b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3116b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t samplerate;
3117b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeySampleRate, &samplerate);
3118b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
3119b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(samplerate << 16);
3120b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
3121b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4aEsdsBox();
3122b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
3123b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong               !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
3124b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeDamrBox();
3125b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3126b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3127b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3128b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3129b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() {
3130b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
3131b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
313243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mCodecSpecificDataSize, 0);
3133b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3134b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Make sure all sizes encode to a single byte.
313543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_LT(mCodecSpecificDataSize + 23, 128);
3136b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3137b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);     // version=0, flags=0
3138b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);   // ES_DescrTag
3139b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
3140b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);// ES_ID
3141b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x00);
3142b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3143b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
3144b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
3145b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
3146b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x15);   // streamType AudioStream
3147b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3148b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x03);  // XXX
314946f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt8(0x00);   // buffer size 24-bit (0x300)
315046f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar
315196bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t avgBitrate = 0;
315246f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyBitRate, &avgBitrate);
315396bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t maxBitrate = 0;
315446f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate);
315546f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(maxBitrate);
315646f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(avgBitrate);
3157b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3158b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
3159b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
3160b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3161b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3162b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
3163b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
3164b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
3165b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
3166b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3167b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
3168b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3169b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
3170b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3171b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3172b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() {
3173b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
317443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mCodecSpecificDataSize, 0);
3175bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan
3176bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan    // Make sure all sizes encode to a single byte.
3177bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan    CHECK_LT(23 + mCodecSpecificDataSize, 128);
3178bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan
3179b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
3180b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3181b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);    // version=0, flags=0
3182b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3183b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);  // ES_DescrTag
3184b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
3185b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);  // ES_ID
3186b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x1f);
3187b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3188b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
3189b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
3190b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
3191b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x11);  // streamType VisualStream
3192b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3193b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData[] = {
319446f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar        0x01, 0x77, 0x00, // buffer size 96000 bytes
3195b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3196b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData, sizeof(kData));
3197b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
319896bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t avgBitrate = 0;
319946f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyBitRate, &avgBitrate);
320096bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t maxBitrate = 0;
320146f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate);
320246f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(maxBitrate);
320346f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(avgBitrate);
320446f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar
3205b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
3206b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3207b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
3208b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3209b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3210b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
3211b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
3212b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
3213b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
3214b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3215b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
3216b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3217b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
3218b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3219b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3220efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeTkhdBox(uint32_t now) {
3221b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("tkhd");
3222b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Flags = 7 to indicate that the track is enabled, and
3223b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // part of the presentation
3224b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x07);          // version=0, flags=7
3225b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
3226b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
3227219f195159f93d627af2b243732e3f9020511a46James Dong    mOwner->writeInt32(mTrackId);      // track id starts with 1
3228b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
32298f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t trakDurationUs = getDurationUs();
3230b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mvhdTimeScale = mOwner->getTimeScale();
3231b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t tkhdDuration =
3232b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
3233b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
3234b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3235b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3236b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // layer
3237b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // alternate group
3238b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
3239b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // reserved
3240b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3241b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCompositionMatrix(mRotation);       // matrix
324220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3243b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
3244b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
3245b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
3246b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
3247b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        int32_t width, height;
3248b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        bool success = mMeta->findInt32(kKeyWidth, &width);
3249b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        success = success && mMeta->findInt32(kKeyHeight, &height);
3250b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(success);
3251b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3252b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
3253b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
3254b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3255b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // tkhd
3256b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3257b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3258b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() {
3259b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("vmhd");
3260b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x01);        // version=0, flags=1
3261b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // graphics mode
3262b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // opcolor
3263b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
3264b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
3265b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3266b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3267b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3268b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() {
3269b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("smhd");
3270b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // version=0, flags=0
3271b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // balance
3272b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3273b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3274b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3275b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3276b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() {
3277b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("hdlr");
3278b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
3279b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // component type: should be mhlr
3280b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeFourcc(mIsAudio ? "soun" : "vide");  // component subtype
3281b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3282b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3283b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3284b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Removing "r" for the name string just makes the string 4 byte aligned
3285b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle");  // name
3286b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3287b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3288b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3289efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeMdhdBox(uint32_t now) {
3290b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t trakDurationUs = getDurationUs();
3291b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("mdhd");
3292b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
3293b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
3294b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
3295b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mTimeScale);    // media timescale
3296b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
3297b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mdhdDuration);  // use media timescale
3298b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Language follows the three letter standard ISO-639-2/T
3299b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 'e', 'n', 'g' for "English", for instance.
3300b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Each character is packed as the difference between its ASCII value and 0x60.
3301b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // For "English", these are 00101, 01110, 00111.
3302b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // XXX: Where is the padding bit located: 0x15C7?
3303b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // language code
3304b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // predefined
3305b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3306b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3307b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3308b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() {
3309b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 3gpp2 Spec AMRSampleEntry fields
3310b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("damr");
3311b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString("   ");  // vendor: 4 bytes
3312b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // decoder version
3313b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x83FF);   // mode set: all enabled
3314b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // mode change period
3315b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(1);         // frames per sample
3316b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3317b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3318b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3319b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() {
3320b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // The table index here refers to the sample description index
3321b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // in the sample table entries.
3322b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("url ");
3323b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
3324b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // url
3325b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3326b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3327b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() {
3328b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dref");
3329b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3330b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // entry count (either url or urn)
3331b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeUrlBox();
3332b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dref
3333b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3334b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3335b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() {
3336b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dinf");
3337b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeDrefBox();
3338b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dinf
3339b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3340b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3341b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() {
3342b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
334343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(mCodecSpecificDataSize, 5);
3344b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3345b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Patch avcc's lengthSize field to match the number
3346b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // of bytes we use to indicate the size of a nal unit.
3347b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
3348b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
3349b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("avcC");
3350b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3351b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // avcC
3352b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3353b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
33549aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
33559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimvoid MPEG4Writer::Track::writeHvccBox() {
33569aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    CHECK(mCodecSpecificData);
33579aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    CHECK_GE(mCodecSpecificDataSize, 5);
33589aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
33599aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Patch avcc's lengthSize field to match the number
33609aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // of bytes we use to indicate the size of a nal unit.
33619aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
33629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ptr[21] = (ptr[21] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
33639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->beginBox("hvcC");
33649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
33659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->endBox();  // hvcC
33669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
33679aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
3368b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() {
3369b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("d263");
3370b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // vendor
3371b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // decoder version
3372b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(10);  // level: 10
3373b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // profile: 0
3374b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // d263
3375b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3376b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3377b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square
3378b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() {
3379b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("pasp");
3380b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // hspacing
3381b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // vspacing
3382b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // pasp
3383b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3384b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3385000e18370baae60ffd9f25b509501dd8c26deabfJames Dongint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const {
3386a472613aec322e25891abf5c77bf3f7e3c244920James Dong    int64_t trackStartTimeOffsetUs = 0;
3387b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
3388b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mStartTimestampUs != moovStartTimeUs) {
338943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_GT(mStartTimestampUs, moovStartTimeUs);
3390b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
3391b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3392000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    return (trackStartTimeOffsetUs *  mTimeScale + 500000LL) / 1000000LL;
3393000e18370baae60ffd9f25b509501dd8c26deabfJames Dong}
3394000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
3395000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() {
3396000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->beginBox("stts");
3397000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3398c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t duration;
3399c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    CHECK(mSttsTableEntries->get(duration, 1));
3400c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    duration = htonl(duration);  // Back to host byte order
3401c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1);
3402c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->write(mOwner);
3403b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stts
3404b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
340520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3406965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() {
3407965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if (mIsAudio) {  // ctts is not for audio
3408965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
3409965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
3410965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3411000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    // There is no B frame at all
3412000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) {
3413000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        return;
3414000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    }
3415000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
3416965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    // Do not write ctts box when there is no need to have it.
3417c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mCttsTableEntries->count() == 0) {
3418965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
3419965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
3420965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3421a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("ctts box has %d entries with range [%" PRId64 ", %" PRId64 "]",
3422c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs);
3423965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3424965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->beginBox("ctts");
3425000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3426c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    uint32_t delta = mMinCttsOffsetTimeUs - getStartTimeOffsetScaledTime();
3427c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    mCttsTableEntries->adjustEntries([delta](size_t /* ix */, uint32_t (&value)[2]) {
3428c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        // entries are <count, ctts> pairs; adjust only ctts
3429c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        uint32_t duration = htonl(value[1]); // back to host byte order
3430c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        value[1] = htonl(duration - delta);
3431c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    });
3432c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->write(mOwner);
3433965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->endBox();  // ctts
3434965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
3435965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3436b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() {
3437b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stss");
3438b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3439c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->write(mOwner);
3440b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stss
3441b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
344225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
3443b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() {
3444b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsz");
3445b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3446c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mOwner->writeInt32(0);
3447c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries->write(mOwner);
3448b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsz
3449b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
345020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3451b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() {
3452b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsc");
3453b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3454c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries->write(mOwner);
3455b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsc
3456b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
345720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3458b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) {
3459b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(use32BitOffset? "stco": "co64");
3460b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3461c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (use32BitOffset) {
3462c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->write(mOwner);
3463c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
3464c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->write(mOwner);
3465b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3466b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stco or co64
346720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
346820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
346907b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() {
347007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("udta");
347107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeGeoDataBox();
347207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
347307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
347407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
3475e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeHdlr() {
3476e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("hdlr");
3477e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Version, Flags
3478e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Predefined
3479e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeFourcc("mdta");
3480e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[0]
3481e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[1]
3482e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[2]
3483e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt8(0);  // Name (empty)
3484e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3485e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3486e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3487e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeKeys() {
3488e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3489e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3490e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("keys");
3491e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0);     // Version, Flags
3492e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(count); // Entry_count
3493e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    for (size_t i = 0; i < count; i++) {
3494e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        AMessage::Type type;
3495e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        const char *key = mMetaKeys->getEntryNameAt(i, &type);
3496e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        size_t n = strlen(key);
3497e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writeInt32(n + 8);
3498e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writeFourcc("mdta");
3499e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        write(key, n); // write without the \0
3500e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3501e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3502e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3503e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3504e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeIlst() {
3505e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3506e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3507e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("ilst");
3508e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    for (size_t i = 0; i < count; i++) {
3509e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        beginBox(i + 1); // key id (1-based)
3510e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        beginBox("data");
3511e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        AMessage::Type type;
3512e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        const char *key = mMetaKeys->getEntryNameAt(i, &type);
3513e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        switch (type) {
35147c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            case AMessage::kTypeString:
35157c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            {
35167c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                AString val;
35177c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                CHECK(mMetaKeys->findString(key, &val));
35187c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(1); // type = UTF8
35197c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0); // default country/language
35207c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                write(val.c_str(), strlen(val.c_str())); // write without \0
35217c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                break;
35227c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            }
35237c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
3524e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            case AMessage::kTypeFloat:
3525e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3526e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                float val;
3527e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                CHECK(mMetaKeys->findFloat(key, &val));
35287c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(23); // type = float32
35297c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3530e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(*reinterpret_cast<int32_t *>(&val));
3531e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3532e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3533e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3534e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            case AMessage::kTypeInt32:
3535e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3536e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                int32_t val;
3537e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                CHECK(mMetaKeys->findInt32(key, &val));
35387c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(67); // type = signed int32
35397c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3540e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(val);
3541e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3542e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3543e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3544e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            default:
3545e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3546e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                ALOGW("Unsupported key type, writing 0 instead");
35477c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(77); // type = unsigned int32
35487c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3549e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(0);
3550e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3551e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3552e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        }
3553e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        endBox(); // data
3554e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        endBox(); // key id
3555e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3556e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox(); // ilst
3557e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3558e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3559e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeMetaBox() {
3560e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3561e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    if (count == 0) {
3562e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        return;
3563e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3564e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3565e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("meta");
3566e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeHdlr();
3567e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeKeys();
3568e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeIlst();
3569e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3570e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3571e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
357207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
357307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
357407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
357507b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() {
357607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("\xA9xyz");
357707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    /*
357807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * For historical reasons, any user data start
357907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * with "\0xA9", must be followed by its assoicated
358007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * language code.
3581432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x0012: text string length
3582432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x15c7: lang (locale) code: en
358307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     */
358407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt32(0x001215c7);
358507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLatitude(mLatitudex10000);
358607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLongitude(mLongitudex10000);
358707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt8(0x2F);
358807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
358907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
359007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
359120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
3592