MPEG4Writer.cpp revision fe44e4f74fe2582cbf012687059278dbcbdaa6f7
120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber/*
220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Copyright (C) 2009 The Android Open Source Project
320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * you may not use this file except in compliance with the License.
620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * You may obtain a copy of the License at
720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
1020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Unless required by applicable law or agreed to in writing, software
1120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * See the License for the specific language governing permissions and
1420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * limitations under the License.
1520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber */
1620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17050b28a593350047845a45a14cc5026221ac1620James Dong//#define LOG_NDEBUG 0
18050b28a593350047845a45a14cc5026221ac1620James Dong#define LOG_TAG "MPEG4Writer"
19050b28a593350047845a45a14cc5026221ac1620James Dong
20826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar#include <algorithm>
21826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar
2220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <arpa/inet.h>
23a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <fcntl.h>
24a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <inttypes.h>
2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <pthread.h>
26a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong#include <sys/prctl.h>
27a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <sys/stat.h>
28a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <sys/types.h>
29a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <unistd.h>
30a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn
31a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <utils/Log.h>
3220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar#include <functional>
34c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar
3543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong#include <media/stagefright/foundation/ADebug.h>
36e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang#include <media/stagefright/foundation/AMessage.h>
37826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar#include <media/stagefright/foundation/AUtils.h>
3858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar#include <media/stagefright/foundation/ColorUtils.h>
3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h>
4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h>
4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
4218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
4303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#include <media/stagefright/MediaErrors.h>
4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h>
4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h>
46d599cd4573b5a2d5914c5040e0565ef866749b77James Dong#include <media/mediarecorder.h>
4707ec01904613a0bac32caaa8444b4690998faed7James Dong#include <cutils/properties.h>
4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber#include "include/ESDS.h"
509aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim#include "include/HevcUtils.h"
5180f78b773f92048944a850efb7b60629643370cdPraveen Chavan#include "include/avc_utils.h"
52dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn
53dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#ifndef __predict_false
54dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#define __predict_false(exp) __builtin_expect((exp) != 0, 0)
55dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#endif
56dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn
5711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih#define WARN_UNLESS(condition, message, ...) \
58dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn( (__predict_false(condition)) ? false : ({ \
5911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih    ALOGW("Condition %s failed "  message, #condition, ##__VA_ARGS__); \
6011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih    true; \
6111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih}))
6211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
6320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6577e8ae9967a078770416619e99ddb5b010def312James Dongstatic const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024;
661f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachadstatic const int64_t kMax32BitFileSize = 0x00ffffffffLL; // 2^32-1 : max FAT32
671f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad                                                         // filesystem file size
681f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad                                                         // used by most SD cards
693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypeSeqParamSet = 0x07;
703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypePicParamSet = 0x08;
7170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongstatic const int64_t kInitialDelayTimeUs     = 700000LL;
72e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuangstatic const int64_t kMaxMetadataSize = 0x4000000LL;   // 64MB max per-frame metadata size
735b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong
747c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Version[]    = "com.android.version";
753b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnar#ifdef SHOW_MODEL_BUILD
763b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnarstatic const char kMetaKey_Model[]      = "com.android.model";
777c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Build[]      = "com.android.build";
783b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnar#endif
797c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_CaptureFps[] = "com.android.capture.fps";
804dbff11975e737482537e1636051690188f3fbc4Praveen Chavanstatic const char kMetaKey_TemporalLayerCount[] = "com.android.video.temporal_layers_count";
817c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatic const uint8_t kMandatoryHevcNalUnitTypes[3] = {
839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeVps,
849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeSps,
859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypePps,
869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim};
879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatic const uint8_t kHevcNalUnitTypes[5] = {
889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeVps,
899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeSps,
909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypePps,
919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypePrefixSei,
929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeSuffixSei,
939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim};
947c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang/* uncomment to include model and build in meta */
957c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang//#define SHOW_MODEL_BUILD 1
967c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
9720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track {
9820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
99b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen    Track(MPEG4Writer *owner, const sp<IMediaSource> &source, size_t trackId);
1008f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ~Track();
10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t start(MetaData *params);
104fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    status_t stop(bool stopSource = true);
10537187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t pause();
10625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool reachedEOS();
10720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1083b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    int64_t getDurationUs() const;
109d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t getEstimatedTrackSizeBytes() const;
110b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeTrackHeader(bool use32BitOffset = true);
1111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void bufferChunk(int64_t timestampUs);
1121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAvc() const { return mIsAvc; }
1139aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    bool isHevc() const { return mIsHevc; }
1141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAudio() const { return mIsAudio; }
1151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isMPEG4() const { return mIsMPEG4; }
116c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    void addChunkOffset(off64_t offset);
11770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int32_t getTrackId() const { return mTrackId; }
118dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    status_t dump(int fd, const Vector<String16>& args) const;
1198b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    static const char *getFourCCForMime(const char *mime);
12025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    const char *getTrackType() const;
121fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    void resetInternal();
12220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
124000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    enum {
125000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        kMaxCttsOffsetTimeUs = 1000000LL,  // 1 second
1268c460498c028888c533ab442be12b6d4b669b965James Dong        kSampleArraySize = 1000,
127000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    };
128000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
129c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    // A helper class to handle faster write box with table entries
130c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    template<class TYPE, unsigned ENTRY_SIZE>
131c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    // ENTRY_SIZE: # of values in each entry
132c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    struct ListTableEntries {
133c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        static_assert(ENTRY_SIZE > 0, "ENTRY_SIZE must be positive");
134c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        ListTableEntries(uint32_t elementCapacity)
135c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            : mElementCapacity(elementCapacity),
136c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mTotalNumTableEntries(0),
137c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mNumValuesInCurrEntry(0),
138c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCurrTableEntriesElement(NULL) {
139c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_GT(mElementCapacity, 0);
1402177f21c1ae5bf5cb8c1113a1adbe1fd7db34206Wei Jia            // Ensure no integer overflow on allocation in add().
141c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            CHECK_LT(ENTRY_SIZE, UINT32_MAX / mElementCapacity);
142c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
143c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
144c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Free the allocated memory.
145c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        ~ListTableEntries() {
146c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (!mTableEntryList.empty()) {
147c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                typename List<TYPE *>::iterator it = mTableEntryList.begin();
148c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                delete[] (*it);
149c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.erase(it);
150c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
151c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
152c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
153c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Replace the value at the given position by the given value.
154c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // There must be an existing value at the given position.
155c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order
156c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
157c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void set(const TYPE& value, uint32_t pos) {
158c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            CHECK_LT(pos, mTotalNumTableEntries * ENTRY_SIZE);
159c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
160c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            typename List<TYPE *>::iterator it = mTableEntryList.begin();
161c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            uint32_t iterations = (pos / (mElementCapacity * ENTRY_SIZE));
162c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (it != mTableEntryList.end() && iterations > 0) {
163c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++it;
164c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                --iterations;
165c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
166c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK(it != mTableEntryList.end());
167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_EQ(iterations, 0);
168c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
169c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            (*it)[(pos % (mElementCapacity * ENTRY_SIZE))] = value;
170c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
171c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
172c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Get the value at the given position by the given value.
173c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value the retrieved value at the position in network byte order.
174c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @return true if a value is found.
176c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        bool get(TYPE& value, uint32_t pos) const {
177c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            if (pos >= mTotalNumTableEntries * ENTRY_SIZE) {
178c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                return false;
179c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
180c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
181c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            typename List<TYPE *>::iterator it = mTableEntryList.begin();
182c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            uint32_t iterations = (pos / (mElementCapacity * ENTRY_SIZE));
183c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (it != mTableEntryList.end() && iterations > 0) {
184c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++it;
185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                --iterations;
186c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
187c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK(it != mTableEntryList.end());
188c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_EQ(iterations, 0);
189c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
190c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            value = (*it)[(pos % (mElementCapacity * ENTRY_SIZE))];
191c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            return true;
192c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
193c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
194c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        // adjusts all values by |adjust(value)|
195c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        void adjustEntries(
196c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                std::function<void(size_t /* ix */, TYPE(& /* entry */)[ENTRY_SIZE])> update) {
197c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            size_t nEntries = mTotalNumTableEntries + mNumValuesInCurrEntry / ENTRY_SIZE;
198c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            size_t ix = 0;
199c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            for (TYPE *entryArray : mTableEntryList) {
200c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                size_t num = std::min(nEntries, (size_t)mElementCapacity);
201c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                for (size_t i = 0; i < num; ++i) {
202c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                    update(ix++, (TYPE(&)[ENTRY_SIZE])(*entryArray));
203c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                    entryArray += ENTRY_SIZE;
204c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                }
205c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                nEntries -= num;
206c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            }
207c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        }
208c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar
209c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Store a single value.
210c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order.
211c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void add(const TYPE& value) {
212c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_LT(mNumValuesInCurrEntry, mElementCapacity);
213c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries % mElementCapacity;
214c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            uint32_t nValues  = mNumValuesInCurrEntry % ENTRY_SIZE;
215c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (nEntries == 0 && nValues == 0) {
216c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                mCurrTableEntriesElement = new TYPE[ENTRY_SIZE * mElementCapacity];
217c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                CHECK(mCurrTableEntriesElement != NULL);
218c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.push_back(mCurrTableEntriesElement);
219c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
220c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
221c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            uint32_t pos = nEntries * ENTRY_SIZE + nValues;
222c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCurrTableEntriesElement[pos] = value;
223c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
224c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            ++mNumValuesInCurrEntry;
225c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            if ((mNumValuesInCurrEntry % ENTRY_SIZE) == 0) {
226c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++mTotalNumTableEntries;
227c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mNumValuesInCurrEntry = 0;
228c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
229c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
230c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
231c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Write out the table entries:
232c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 1. the number of entries goes first
233c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 2. followed by the values in the table enties in order
234c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg writer the writer to actual write to the storage
235c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void write(MPEG4Writer *writer) const {
236c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            CHECK_EQ(mNumValuesInCurrEntry % ENTRY_SIZE, 0);
237c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries;
238c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            writer->writeInt32(nEntries);
239c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            for (typename List<TYPE *>::iterator it = mTableEntryList.begin();
240c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                it != mTableEntryList.end(); ++it) {
241c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                CHECK_GT(nEntries, 0);
242c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                if (nEntries >= mElementCapacity) {
243c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                    writer->write(*it, sizeof(TYPE) * ENTRY_SIZE, mElementCapacity);
244c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    nEntries -= mElementCapacity;
245c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                } else {
246c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                    writer->write(*it, sizeof(TYPE) * ENTRY_SIZE, nEntries);
247c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    break;
248c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                }
249c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
250c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
251c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
252c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Return the number of entries in the table.
253c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t count() const { return mTotalNumTableEntries; }
254c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
255c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    private:
256c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mElementCapacity;  // # entries in an element
257c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mTotalNumTableEntries;
258c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        uint32_t         mNumValuesInCurrEntry;  // up to ENTRY_SIZE
259c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        TYPE             *mCurrTableEntriesElement;
260c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mutable List<TYPE *>     mTableEntryList;
261c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
262c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries);
263c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    };
264c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
265c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
266c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
26720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Writer *mOwner;
26820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mMeta;
269b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen    sp<IMediaSource> mSource;
27020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    volatile bool mDone;
271a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mPaused;
272a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mResumed;
273eaae38445a340c4857c1c5569475879a728e63b7James Dong    volatile bool mStarted;
2741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAvc;
2759aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    bool mIsHevc;
2761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAudio;
27725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    bool mIsVideo;
2781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsMPEG4;
279fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    bool mGotStartKeyFrame;
2809db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang    bool mIsMalformed;
281bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t mTrackId;
282c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    int64_t mTrackDurationUs;
28343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int64_t mMaxChunkDurationUs;
284826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar    int64_t mLastDecodingTimeUs;
285e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
286d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t mEstimatedTrackSizeBytes;
2871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t mMdatSizeBytes;
2888f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mTimeScale;
28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_t mThread;
29120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
292be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
29313aec890216948b0c364f8f92792129d0335f506James Dong    List<MediaBuffer *> mChunkSamples;
2941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
295c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    bool                mSamplesHaveSameSize;
296c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 1> *mStszTableEntries;
297be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
298c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 1> *mStcoTableEntries;
299c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<off64_t, 1> *mCo64TableEntries;
300c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 3> *mStscTableEntries;
301c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 1> *mStssTableEntries;
302c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 2> *mSttsTableEntries;
303c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 2> *mCttsTableEntries;
304965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
305000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMinCttsOffsetTimeUs;
306000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMaxCttsOffsetTimeUs;
307965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Sequence parameter set or picture parameter set
3093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    struct AVCParamSet {
3103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        AVCParamSet(uint16_t length, const uint8_t *data)
3113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            : mLength(length), mData(data) {}
3123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
3133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t mLength;
3143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *mData;
3153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    };
3163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mSeqParamSets;
3173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mPicParamSets;
3183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileIdc;
3193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileCompatible;
3203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mLevelIdc;
3213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
32220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *mCodecSpecificData;
32320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t mCodecSpecificDataSize;
324548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    bool mGotAllCodecSpecificData;
32593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    bool mTrackingProgressStatus;
32620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool mReachedEOS;
3283c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    int64_t mStartTimestampUs;
32970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mStartTimeRealUs;
33070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mFirstSampleTimeRealUs;
33193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mPreviousTrackTimeUs;
33293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mTrackEveryTimeDurationUs;
33325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
334872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Update the audio track's drift information.
335872a481558350634a3fd5cb67939de288af00ecbJames Dong    void updateDriftTime(const sp<MetaData>& meta);
336872a481558350634a3fd5cb67939de288af00ecbJames Dong
337000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int32_t getStartTimeOffsetScaledTime() const;
338000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
33920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static void *ThreadWrapper(void *me);
34037187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t threadEntry();
34120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *parseParamSet(
3433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen);
3443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
3459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t copyCodecSpecificData(const uint8_t *data, size_t size, size_t minLength = 0);
3469aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
347b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size);
348b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size);
349b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size);
350215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong
3519aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t makeHEVCCodecSpecificData(const uint8_t *data, size_t size);
3529aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t copyHEVCCodecSpecificData(const uint8_t *data, size_t size);
3539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t parseHEVCCodecSpecificData(
3549aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            const uint8_t *data, size_t size, HevcParameterSets &paramSets);
3559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
356215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    // Track authoring progress status
357faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    void trackProgressStatus(int64_t timeUs, status_t err = OK);
35893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    void initTrackingProgressStatus(MetaData *params);
35903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
36019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    void getCodecSpecificDataFromInputFormatIfPossible();
36119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
362c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Determine the track time scale
363c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If it is an audio track, try to use the sampling rate as
364c059860c73678a202bfa33062723e8f82fb779d9James Dong    // the time scale; however, if user chooses the overwrite
365c059860c73678a202bfa33062723e8f82fb779d9James Dong    // value, the user-supplied time scale will be used.
366c059860c73678a202bfa33062723e8f82fb779d9James Dong    void setTimeScale();
367c059860c73678a202bfa33062723e8f82fb779d9James Dong
368690f546b0ee548dbfe997df36418e5302ec2d786James Dong    // Simple validation on the codec specific data
369690f546b0ee548dbfe997df36418e5302ec2d786James Dong    status_t checkCodecSpecificData() const;
37013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t mRotation;
371690f546b0ee548dbfe997df36418e5302ec2d786James Dong
3721f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void updateTrackSizeEstimate();
3731f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStscTableEntry(size_t chunkId, size_t sampleId);
3741f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStssTableEntry(size_t sampleId);
37579761ab096f57c3027fad9556c2bc436672d614eJames Dong
37679761ab096f57c3027fad9556c2bc436672d614eJames Dong    // Duration is time scale based
37779761ab096f57c3027fad9556c2bc436672d614eJames Dong    void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
378965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
37945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
38045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    bool isTrackMalFormed() const;
38143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    void sendTrackSummary(bool hasMultipleTracks);
3821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
383b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Write the boxes
384b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStcoBox(bool use32BitOffset);
385b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStscBox();
386b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStszBox();
387b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStssBox();
388b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSttsBox();
389965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void writeCttsBox();
390b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeD263Box();
391b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writePaspBox();
392b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAvccBox();
3939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    void writeHvccBox();
394b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeUrlBox();
395b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDrefBox();
396b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDinfBox();
397b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDamrBox();
398efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeMdhdBox(uint32_t now);
399b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSmhdBox();
400b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVmhdBox();
40125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    void writeNmhdBox();
402b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeHdlrBox();
403efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeTkhdBox(uint32_t now);
40458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    void writeColrBox();
405b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4aEsdsBox();
406b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4vEsdsBox();
407b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAudioFourCCBox();
408b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVideoFourCCBox();
40925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    void writeMetadataFourCCBox();
410b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStblBox(bool use32BitOffset);
411b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
41220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track(const Track &);
41320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track &operator=(const Track &);
41420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
41520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
416fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu KuangMPEG4Writer::MPEG4Writer(int fd) {
417fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    initInternal(fd);
41830ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
41930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
42020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
4218bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong    reset();
42220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4231f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    while (!mTracks.empty()) {
4241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        List<Track *>::iterator it = mTracks.begin();
42520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
4261f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        (*it) = NULL;
4271f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mTracks.erase(it);
42820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
42920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
430fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
431fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mNextFd != -1) {
432fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        close(mNextFd);
433fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
434fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
435fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
436fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::initInternal(int fd) {
437fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGV("initInternal");
438fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mFd = fd;
439fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mNextFd = -1;
440fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mInitCheck = mFd < 0? NO_INIT: OK;
441fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mIsRealTimeRecording = true;
442fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mUse4ByteNalLength = true;
443fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mUse32BitOffset = true;
444fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mIsFileSizeLimitExplicitlyRequested = false;
445fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mPaused = false;
446fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mStarted = false;
447fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mWriterThreadStarted = false;
448fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mSendNotify = false;
449fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mOffset = 0;
450fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mMdatOffset = 0;
451fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mMoovBoxBuffer = NULL;
452fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mMoovBoxBufferOffset = 0;
453fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mWriteMoovBoxToMemory = false;
454fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mFreeBoxOffset = 0;
455fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mStreamableFile = false;
456fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mEstimatedMoovBoxSize = 0;
457fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mMoovExtraSize = 0;
458fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mInterleaveDurationUs = 1000000;
459fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mTimeScale = -1;
460fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mStartTimestampUs = -1ll;
461fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mLatitudex10000 = 0;
462fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mLongitudex10000 = 0;
463fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mAreGeoTagsAvailable = false;
464fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mStartTimeOffsetMs = -1;
465fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mSwitchPending = false;
466fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mMetaKeys = new AMessage();
467fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    addDeviceMeta();
468fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    // Verify mFd is seekable
469fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    off64_t off = lseek64(mFd, 0, SEEK_SET);
470fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (off < 0) {
471fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        ALOGE("cannot seek mFd: %s (%d) %lld", strerror(errno), errno, (long long)mFd);
472fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        release();
473fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
474fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    for (List<Track *>::iterator it = mTracks.begin();
475fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         it != mTracks.end(); ++it) {
476fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        (*it)->resetInternal();
477fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
47820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
47920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
480dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump(
481dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) {
482dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
483dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
484dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
485dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "   MPEG4Writer %p\n", this);
486dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
487dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     mStarted: %s\n", mStarted? "true": "false");
488dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
489dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
490dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    for (List<Track *>::iterator it = mTracks.begin();
491dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong         it != mTracks.end(); ++it) {
492dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        (*it)->dump(fd, args);
493dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    }
494dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
495dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
496dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
497dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump(
49884333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        int fd, const Vector<String16>& /* args */) const {
499dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
500dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
501dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
50225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    snprintf(buffer, SIZE, "     %s track\n", getTrackType());
503dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
504dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "       reached EOS: %s\n",
505dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong            mReachedEOS? "true": "false");
506dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
507c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    snprintf(buffer, SIZE, "       frames encoded : %d\n", mStszTableEntries->count());
50813210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
509377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    snprintf(buffer, SIZE, "       duration encoded : %" PRId64 " us\n", mTrackDurationUs);
51013210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
511dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
512dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
513dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
514dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
5158b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan// static
5168b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavanconst char *MPEG4Writer::Track::getFourCCForMime(const char *mime) {
5178b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (mime == NULL) {
5188b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        return NULL;
5198b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    }
5208b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (!strncasecmp(mime, "audio/", 6)) {
5218b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
5228b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "samr";
5238b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
5248b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "sawb";
5258b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
5268b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "mp4a";
5278b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        }
5288b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    } else if (!strncasecmp(mime, "video/", 6)) {
5298b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
5308b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "mp4v";
5318b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
5328b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "s263";
5338b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
5348b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "avc1";
5359aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
5369aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return "hvc1";
5378b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        }
53825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else if (!strncasecmp(mime, "application/", 12)) {
53925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        return "mett";
5408b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    } else {
54125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        ALOGE("Track (%s) other than video/audio/metadata is not supported", mime);
5428b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    }
5438b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    return NULL;
5448b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan}
5458b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan
546b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissenstatus_t MPEG4Writer::addSource(const sp<IMediaSource> &source) {
547bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    Mutex::Autolock l(mLock);
548bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    if (mStarted) {
54929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Attempt to add source AFTER recording is started");
550bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        return UNKNOWN_ERROR;
551bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    }
552acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
553acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    CHECK(source.get() != NULL);
554acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
555acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    const char *mime;
556acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    source->getFormat()->findCString(kKeyMIMEType, &mime);
557acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
55825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (Track::getFourCCForMime(mime) == NULL) {
55925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        ALOGE("Unsupported mime '%s'", mime);
56025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        return ERROR_UNSUPPORTED;
56125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    }
56225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang
56325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    // This is a metadata track or the first track of either audio or video
564acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // Go ahead to add the track.
565219f195159f93d627af2b243732e3f9020511a46James Dong    Track *track = new Track(this, source, 1 + mTracks.size());
56620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
5672dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
5682dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
56920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
57020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
57193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) {
572acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    if (mTracks.empty()) {
573acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        ALOGE("No source added");
574acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return INVALID_OPERATION;
575acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
576acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
577a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
578a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
57993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        status_t err = (*it)->start(params);
580a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
581a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (err != OK) {
582a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            for (List<Track *>::iterator it2 = mTracks.begin();
583a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                 it2 != it; ++it2) {
584a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                (*it2)->stop();
585a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            }
586a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
587a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            return err;
588a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
589a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
590a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
591a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
592a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
5937c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangvoid MPEG4Writer::addDeviceMeta() {
5947c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // add device info and estimate space in 'moov'
5957c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    char val[PROPERTY_VALUE_MAX];
5967c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    size_t n;
5977c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // meta size is estimated by adding up the following:
5987c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // - meta header structures, which occur only once (total 66 bytes)
5997c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // - size for each key, which consists of a fixed header (32 bytes),
6007c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    //   plus key length and data length.
6017c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += 66;
6027c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.build.version.release", val, NULL)
6037c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
6047c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Version, val, n + 1);
6057c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Version) + n + 32;
6067c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
6077c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#ifdef SHOW_MODEL_BUILD
6087c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.product.model", val, NULL)
6097c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
6107c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Model, val, n + 1);
6117c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Model) + n + 32;
6127c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
6137c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.build.display.id", val, NULL)
6147c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
6157c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Build, val, n + 1);
6167c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Build) + n + 32;
6177c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
6187c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#endif
6197c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang}
6207c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
6212dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
6222dec2b5be2056c6d9428897dc672185872d30d17James Dong    // This implementation is highly experimental/heurisitic.
6232dec2b5be2056c6d9428897dc672185872d30d17James Dong    //
6242dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Statistical analysis shows that metadata usually accounts
6252dec2b5be2056c6d9428897dc672185872d30d17James Dong    // for a small portion of the total file size, usually < 0.6%.
6262dec2b5be2056c6d9428897dc672185872d30d17James Dong
62778a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2,
6282dec2b5be2056c6d9428897dc672185872d30d17James Dong    // where 1MB is the common file size limit for MMS application.
62978a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MAX _MOOV_BOX_SIZE value is based on about 3
6302dec2b5be2056c6d9428897dc672185872d30d17James Dong    // minute video recording with a bit rate about 3 Mbps, because
6312dec2b5be2056c6d9428897dc672185872d30d17James Dong    // statistics also show that most of the video captured are going
6322dec2b5be2056c6d9428897dc672185872d30d17James Dong    // to be less than 3 minutes.
6332dec2b5be2056c6d9428897dc672185872d30d17James Dong
6342dec2b5be2056c6d9428897dc672185872d30d17James Dong    // If the estimation is wrong, we will pay the price of wasting
6352dec2b5be2056c6d9428897dc672185872d30d17James Dong    // some reserved space. This should not happen so often statistically.
6362dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int32_t factor = mUse32BitOffset? 1: 2;
63778a1a286f736888ae7af8860b2c424af0d978848James Dong    static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024;  // 3 KB
6382dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
6392dec2b5be2056c6d9428897dc672185872d30d17James Dong    int64_t size = MIN_MOOV_BOX_SIZE;
6402dec2b5be2056c6d9428897dc672185872d30d17James Dong
64178a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file size limit is set
642a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
64378a1a286f736888ae7af8860b2c424af0d978848James Dong        size = mMaxFileSizeLimitBytes * 6 / 1000;
64478a1a286f736888ae7af8860b2c424af0d978848James Dong    }
64578a1a286f736888ae7af8860b2c424af0d978848James Dong
64678a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file duration limit is set
64778a1a286f736888ae7af8860b2c424af0d978848James Dong    if (mMaxFileDurationLimitUs != 0) {
64878a1a286f736888ae7af8860b2c424af0d978848James Dong        if (bitRate > 0) {
64978a1a286f736888ae7af8860b2c424af0d978848James Dong            int64_t size2 =
6500ca31521644b9396829850f7400d23f9b107cc64Johan Redestig                ((mMaxFileDurationLimitUs / 1000) * bitRate * 6) / 8000000;
65178a1a286f736888ae7af8860b2c424af0d978848James Dong            if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
65278a1a286f736888ae7af8860b2c424af0d978848James Dong                // When both file size and duration limits are set,
65378a1a286f736888ae7af8860b2c424af0d978848James Dong                // we use the smaller limit of the two.
65478a1a286f736888ae7af8860b2c424af0d978848James Dong                if (size > size2) {
65578a1a286f736888ae7af8860b2c424af0d978848James Dong                    size = size2;
65678a1a286f736888ae7af8860b2c424af0d978848James Dong                }
65778a1a286f736888ae7af8860b2c424af0d978848James Dong            } else {
65878a1a286f736888ae7af8860b2c424af0d978848James Dong                // Only max file duration limit is set
65978a1a286f736888ae7af8860b2c424af0d978848James Dong                size = size2;
66078a1a286f736888ae7af8860b2c424af0d978848James Dong            }
6612dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
6622dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
66378a1a286f736888ae7af8860b2c424af0d978848James Dong
6642dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size < MIN_MOOV_BOX_SIZE) {
6652dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MIN_MOOV_BOX_SIZE;
6662dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
6672dec2b5be2056c6d9428897dc672185872d30d17James Dong
6682dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Any long duration recording will be probably end up with
6692dec2b5be2056c6d9428897dc672185872d30d17James Dong    // non-streamable mp4 file.
6702dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size > MAX_MOOV_BOX_SIZE) {
6712dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MAX_MOOV_BOX_SIZE;
6722dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
6732dec2b5be2056c6d9428897dc672185872d30d17James Dong
6747c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // Account for the extra stuff (Geo, meta keys, etc.)
6757c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    size += mMoovExtraSize;
6767c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
677a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGI("limits: %" PRId64 "/%" PRId64 " bytes/us, bit rate: %d bps and the"
678a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn         " estimated moov size %" PRId64 " bytes",
6792dec2b5be2056c6d9428897dc672185872d30d17James Dong         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
6802dec2b5be2056c6d9428897dc672185872d30d17James Dong    return factor * size;
6812dec2b5be2056c6d9428897dc672185872d30d17James Dong}
6822dec2b5be2056c6d9428897dc672185872d30d17James Dong
6832dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) {
684674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
68525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
68620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
687fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mStartMeta = param;
68820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
689a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    /*
690a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * Check mMaxFileSizeLimitBytes at the beginning
691a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * since mMaxFileSizeLimitBytes may be implicitly
692a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * changed later for 32-bit file offset even if
693a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * user does not ask to set it explicitly.
694a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     */
695a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0) {
696a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong        mIsFileSizeLimitExplicitlyRequested = true;
697a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    }
698a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong
6992dec2b5be2056c6d9428897dc672185872d30d17James Dong    int32_t use64BitOffset;
7002dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (param &&
7012dec2b5be2056c6d9428897dc672185872d30d17James Dong        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
7022dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64BitOffset) {
7032dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
7042dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
7052dec2b5be2056c6d9428897dc672185872d30d17James Dong
7061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    if (mUse32BitOffset) {
7071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // Implicit 32 bit file size limit
7081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes == 0) {
7091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
7101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
7111f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
7121f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // If file size is set to be larger than the 32 bit file
7131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // size limit, treat it as an error.
7141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
715a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGW("32-bit file size limit (%" PRId64 " bytes) too big. "
716a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                 "It is changed to %" PRId64 " bytes",
717d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                mMaxFileSizeLimitBytes, kMax32BitFileSize);
718d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
7191f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
7201f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    }
7211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
722b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    int32_t use2ByteNalLength;
723b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (param &&
724b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) &&
725b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        use2ByteNalLength) {
726b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mUse4ByteNalLength = false;
7272dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
7282dec2b5be2056c6d9428897dc672185872d30d17James Dong
729de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    int32_t isRealTimeRecording;
730de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (param && param->findInt32(kKeyRealTimeRecording, &isRealTimeRecording)) {
731de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        mIsRealTimeRecording = isRealTimeRecording;
732de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    }
733de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
734065d1aff96818df54456053f1574aec8a234d0deJames Dong    mStartTimestampUs = -1;
73593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
736a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mStarted) {
737a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused) {
738a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mPaused = false;
73993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return startTracks(param);
740a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
741a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
742a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
743a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
7448f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (!param ||
7458f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
7468f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mTimeScale = 1000;
7478f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
74843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
7493856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("movie time scale: %d", mTimeScale);
7508f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
75177e8ae9967a078770416619e99ddb5b010def312James Dong    /*
75277e8ae9967a078770416619e99ddb5b010def312James Dong     * When the requested file size limit is small, the priority
75377e8ae9967a078770416619e99ddb5b010def312James Dong     * is to meet the file size limit requirement, rather than
7547b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to make the file streamable. mStreamableFile does not tell
7557b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * whether the actual recorded file is streamable or not.
75677e8ae9967a078770416619e99ddb5b010def312James Dong     */
75777e8ae9967a078770416619e99ddb5b010def312James Dong    mStreamableFile =
75877e8ae9967a078770416619e99ddb5b010def312James Dong        (mMaxFileSizeLimitBytes != 0 &&
75977e8ae9967a078770416619e99ddb5b010def312James Dong         mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes);
76077e8ae9967a078770416619e99ddb5b010def312James Dong
7617b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    /*
7627b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mWriteMoovBoxToMemory is true if the amount of data in moov box is
7637b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * smaller than the reserved free space at the beginning of a file, AND
7647b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * when the content of moov box is constructed. Note that video/audio
7657b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * frame data is always written to the file but not in the memory.
7667b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7677b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * Before stop()/reset() is called, mWriteMoovBoxToMemory is always
7687b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * false. When reset() is called at the end of a recording session,
7697b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * Moov box needs to be constructed.
7707b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7717b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 1) Right before a moov box is constructed, mWriteMoovBoxToMemory
7727b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to set to mStreamableFile so that if
7737b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * the file is intended to be streamable, it is set to true;
7747b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * otherwise, it is set to false. When the value is set to false,
7757b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * all the content of the moov box is written immediately to
7767b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * the end of the file. When the value is set to true, all the
7777b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * content of the moov box is written to an in-memory cache,
7787b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mMoovBoxBuffer, util the following condition happens. Note
7797b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * that the size of the in-memory cache is the same as the
7807b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * reserved free space at the beginning of the file.
7817b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7827b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 2) While the data of the moov box is written to an in-memory
7837b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * cache, the data size is checked against the reserved space.
7847b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * If the data size surpasses the reserved space, subsequent moov
7857b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * data could no longer be hold in the in-memory cache. This also
7867b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * indicates that the reserved space was too small. At this point,
7877b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * _all_ moov data must be written to the end of the file.
7887b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mWriteMoovBoxToMemory must be set to false to direct the write
7897b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to the file.
7907b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7917b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 3) If the data size in moov box is smaller than the reserved
7927b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * space after moov box is completely constructed, the in-memory
7937b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * cache copy of the moov box is written to the reserved free
7947b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * space. Thus, immediately after the moov is completedly
7957b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * constructed, mWriteMoovBoxToMemory is always set to false.
7967b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     */
7977b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    mWriteMoovBoxToMemory = false;
7987837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = NULL;
7997837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
8007837c17063a4c50bc856ba59418516fdab731de7James Dong
801b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeFtypBox(param);
80220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8037837c17063a4c50bc856ba59418516fdab731de7James Dong    mFreeBoxOffset = mOffset;
80420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8057837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mEstimatedMoovBoxSize == 0) {
8062dec2b5be2056c6d9428897dc672185872d30d17James Dong        int32_t bitRate = -1;
8072dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (param) {
8082dec2b5be2056c6d9428897dc672185872d30d17James Dong            param->findInt32(kKeyBitRate, &bitRate);
8092dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
8102dec2b5be2056c6d9428897dc672185872d30d17James Dong        mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
8117837c17063a4c50bc856ba59418516fdab731de7James Dong    }
81243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(mEstimatedMoovBoxSize, 8);
81377e8ae9967a078770416619e99ddb5b010def312James Dong    if (mStreamableFile) {
81477e8ae9967a078770416619e99ddb5b010def312James Dong        // Reserve a 'free' box only for streamable file
81577e8ae9967a078770416619e99ddb5b010def312James Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
81677e8ae9967a078770416619e99ddb5b010def312James Dong        writeInt32(mEstimatedMoovBoxSize);
81777e8ae9967a078770416619e99ddb5b010def312James Dong        write("free", 4);
81877e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
81977e8ae9967a078770416619e99ddb5b010def312James Dong    } else {
82077e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mOffset;
82177e8ae9967a078770416619e99ddb5b010def312James Dong    }
8227837c17063a4c50bc856ba59418516fdab731de7James Dong
8237837c17063a4c50bc856ba59418516fdab731de7James Dong    mOffset = mMdatOffset;
824c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mMdatOffset, SEEK_SET);
8251acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
8261acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("????mdat", 8);
8271acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
8281acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("\x00\x00\x00\x01mdat????????", 16);
8291acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
8301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    status_t err = startWriterThread();
8321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (err != OK) {
8331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return err;
8341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    err = startTracks(param);
837a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (err != OK) {
838a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return err;
83920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
8401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
841a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = true;
84225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
84320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
84420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8451f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const {
8461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    return mUse32BitOffset;
8471f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
8481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
84937187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() {
850674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
85137187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
852a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
853a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
85437187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
855a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
856a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
85737187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->pause();
85837187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (status != OK) {
85937187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
86037187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
861a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
86237187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
863a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
864a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
8651c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() {
866b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Stopping writer thread");
867411ba422e3635d534928ffd81abf54f4f291c739James Dong    if (!mWriterThreadStarted) {
868411ba422e3635d534928ffd81abf54f4f291c739James Dong        return;
869411ba422e3635d534928ffd81abf54f4f291c739James Dong    }
8701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
8721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
8731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mDone = true;
8751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkReadyCondition.signal();
8761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void *dummy;
8791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_join(mThread, &dummy);
880411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = false;
881b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Writer thread stopped");
8821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
8831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
88413f6284305e4b27395a23db7882d670bdb1bcae1James Dong/*
88513f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix:
88613f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a  b  u |
88713f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c  d  v |
88813f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x  y  w |
88913f6284305e4b27395a23db7882d670bdb1bcae1James Dong *
89013f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following
89113f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w},
89213f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while
89313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format.
89413f6284305e4b27395a23db7882d670bdb1bcae1James Dong */
89513f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) {
8963856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeCompositionMatrix");
89713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t a = 0x00010000;
89813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t b = 0;
89913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t c = 0;
90013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t d = 0x00010000;
90113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    switch (degrees) {
90213f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 0:
90313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
90413f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 90:
90513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
90613f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0x00010000;
90713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0xFFFF0000;
90813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
90913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
91013f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 180:
91113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0xFFFF0000;
91213f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0xFFFF0000;
91313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
91413f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 270:
91513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
91613f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0xFFFF0000;
91713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0x00010000;
91813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
91913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
92013f6284305e4b27395a23db7882d670bdb1bcae1James Dong        default:
92113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            CHECK(!"Should never reach this unknown rotation");
92213f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
92313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
92413f6284305e4b27395a23db7882d670bdb1bcae1James Dong
92513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(a);           // a
92613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(b);           // b
92713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // u
92813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(c);           // c
92913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(d);           // d
93013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // v
93113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // x
93213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // y
93313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0x40000000);  // w
93413f6284305e4b27395a23db7882d670bdb1bcae1James Dong}
93513f6284305e4b27395a23db7882d670bdb1bcae1James Dong
936411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() {
937411ba422e3635d534928ffd81abf54f4f291c739James Dong    close(mFd);
938411ba422e3635d534928ffd81abf54f4f291c739James Dong    mFd = -1;
939411ba422e3635d534928ffd81abf54f4f291c739James Dong    mInitCheck = NO_INIT;
940411ba422e3635d534928ffd81abf54f4f291c739James Dong    mStarted = false;
9414c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary    free(mMoovBoxBuffer);
9424c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary    mMoovBoxBuffer = NULL;
943411ba422e3635d534928ffd81abf54f4f291c739James Dong}
94413f6284305e4b27395a23db7882d670bdb1bcae1James Dong
945fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::finishCurrentSession() {
946fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    reset(false /* stopSource */);
947fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
948fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
949fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::switchFd() {
950fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGV("switchFd");
951fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    Mutex::Autolock l(mLock);
952fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mSwitchPending) {
953fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return OK;
954fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
955fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
956fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mNextFd == -1) {
957fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        ALOGW("No FileDescripter for next recording");
958fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return INVALID_OPERATION;
959fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
960fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
961fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mSwitchPending = true;
962fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    sp<AMessage> msg = new AMessage(kWhatSwitch, mReflector);
963fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    status_t err = msg->post();
964fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
965fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    return err;
966fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
967fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
968fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::reset(bool stopSource) {
969674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
97037187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
971411ba422e3635d534928ffd81abf54f4f291c739James Dong    } else {
972411ba422e3635d534928ffd81abf54f4f291c739James Dong        if (!mWriterThreadStarted ||
973411ba422e3635d534928ffd81abf54f4f291c739James Dong            !mStarted) {
974411ba422e3635d534928ffd81abf54f4f291c739James Dong            if (mWriterThreadStarted) {
975411ba422e3635d534928ffd81abf54f4f291c739James Dong                stopWriterThread();
976411ba422e3635d534928ffd81abf54f4f291c739James Dong            }
977411ba422e3635d534928ffd81abf54f4f291c739James Dong            release();
978411ba422e3635d534928ffd81abf54f4f291c739James Dong            return OK;
979411ba422e3635d534928ffd81abf54f4f291c739James Dong        }
98020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
98120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
98237187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
9838f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t maxDurationUs = 0;
98465b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    int64_t minDurationUs = 0x7fffffffffffffffLL;
98520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
98620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
987fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        status_t status = (*it)->stop(stopSource);
98837187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK) {
98937187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
99037187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
99120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9928f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int64_t durationUs = (*it)->getDurationUs();
9938f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (durationUs > maxDurationUs) {
9948f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            maxDurationUs = durationUs;
99520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
99665b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        if (durationUs < minDurationUs) {
99765b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs = durationUs;
99865b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        }
99965b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    }
100065b3d76025c71d755b0fb3b6ead90255f25417edJames Dong
100165b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    if (mTracks.size() > 1) {
1002a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGD("Duration from tracks range is [%" PRId64 ", %" PRId64 "] us",
100365b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs, maxDurationUs);
100420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
100520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    stopWriterThread();
10077837c17063a4c50bc856ba59418516fdab731de7James Dong
100837187916a486504acaf83bea30147eb5fbf46ae5James Dong    // Do not write out movie header on error.
100937187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err != OK) {
1010411ba422e3635d534928ffd81abf54f4f291c739James Dong        release();
101137187916a486504acaf83bea30147eb5fbf46ae5James Dong        return err;
101237187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
101337187916a486504acaf83bea30147eb5fbf46ae5James Dong
101420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
10151acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
1016c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset, SEEK_SET);
10171f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad        uint32_t size = htonl(static_cast<uint32_t>(mOffset - mMdatOffset));
1018c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 4);
10191acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
1020c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset + 8, SEEK_SET);
10211f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad        uint64_t size = mOffset - mMdatOffset;
10221acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        size = hton64(size);
1023c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 8);
10241acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
1025c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mOffset, SEEK_SET);
102620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10277b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // Construct moov box now
10287837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
10297b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    mWriteMoovBoxToMemory = mStreamableFile;
10307b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mWriteMoovBoxToMemory) {
10317b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // There is no need to allocate in-memory cache
10327b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // for moov box if the file is not streamable.
10337b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
10347b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
10357b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        CHECK(mMoovBoxBuffer != NULL);
10367b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    }
1037b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMoovBox(maxDurationUs);
103820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10397b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // mWriteMoovBoxToMemory could be set to false in
10407b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // MPEG4Writer::write() method
10417b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mWriteMoovBoxToMemory) {
10427b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        mWriteMoovBoxToMemory = false;
10437b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // Content of the moov box is saved in the cache, and the in-memory
10447b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // moov box needs to be written to the file in a single shot.
10457b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
104643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize);
10477837c17063a4c50bc856ba59418516fdab731de7James Dong
10487837c17063a4c50bc856ba59418516fdab731de7James Dong        // Moov box
1049c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
10507837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset = mFreeBoxOffset;
1051674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset);
10527837c17063a4c50bc856ba59418516fdab731de7James Dong
10537837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free box
1054c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
10557837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
10567837c17063a4c50bc856ba59418516fdab731de7James Dong        write("free", 4);
10577b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    } else {
10587b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        ALOGI("The mp4 file will not be streamable.");
10597b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    }
10607837c17063a4c50bc856ba59418516fdab731de7James Dong
10617b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // Free in-memory cache for moov box
10627b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mMoovBoxBuffer != NULL) {
10637837c17063a4c50bc856ba59418516fdab731de7James Dong        free(mMoovBoxBuffer);
10647837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBuffer = NULL;
10657837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBufferOffset = 0;
10667837c17063a4c50bc856ba59418516fdab731de7James Dong    }
10677837c17063a4c50bc856ba59418516fdab731de7James Dong
10680c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
106920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1070411ba422e3635d534928ffd81abf54f4f291c739James Dong    release();
107137187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
107220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
107320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1074efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonuint32_t MPEG4Writer::getMpeg4Time() {
1075b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    time_t now = time(NULL);
1076efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // MP4 file uses time counting seconds since midnight, Jan. 1, 1904
1077efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // while time function returns Unix epoch values which starts
1078efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // at 1970-01-01. Lets add the number of seconds between them
10792b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    static const uint32_t delta = (66 * 365 + 17) * (24 * 60 * 60);
10802b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    if (now < 0 || uint32_t(now) > UINT32_MAX - delta) {
10812b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen        return 0;
10822b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    }
10832b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    uint32_t mpeg4Time = uint32_t(now) + delta;
1084efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    return mpeg4Time;
1085efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson}
1086efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson
1087efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) {
1088efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
1089b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("mvhd");
1090b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // version=0, flags=0
1091b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // creation time
1092b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // modification time
1093b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTimeScale);    // mvhd timescale
1094b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6;
1095b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(duration);
1096b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0x10000);       // rate: 1.0
1097b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0x100);         // volume
1098b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0);             // reserved
1099b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
1100b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
1101b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeCompositionMatrix(0); // matrix
1102b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1103b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1104b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1105b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1106b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1107b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1108b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTracks.size() + 1);  // nextTrackID
1109b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // mvhd
1110b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1111b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1112b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) {
1113b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("moov");
1114b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMvhdBox(durationUs);
111507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (mAreGeoTagsAvailable) {
111607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        writeUdtaBox();
111707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
1118e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeMetaBox();
1119b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t id = 1;
1120b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    for (List<Track *>::iterator it = mTracks.begin();
1121b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        it != mTracks.end(); ++it, ++id) {
1122b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (*it)->writeTrackHeader(mUse32BitOffset);
1123b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
1124b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // moov
1125b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1126b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
11272cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) {
1128b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("ftyp");
1129b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1130b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t fileType;
1131b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (param && param->findInt32(kKeyFileType, &fileType) &&
1132b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fileType != OUTPUT_FORMAT_MPEG_4) {
1133b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("3gp4");
11348284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeInt32(0);
11358284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("isom");
11368284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("3gp4");
1137b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
11388284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("mp42");
11398284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeInt32(0);
1140b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("isom");
11418284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("mp42");
1142b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
1143b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1144b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();
1145b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1146b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
114707ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() {
114807ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5)
114907ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5"
115007ec01904613a0bac32caaa8444b4690998faed7James Dong#endif
115107ec01904613a0bac32caaa8444b4690998faed7James Dong
115207ec01904613a0bac32caaa8444b4690998faed7James Dong    // Test mode is enabled only if rw.media.record.test system
115307ec01904613a0bac32caaa8444b4690998faed7James Dong    // property is enabled.
115496626b7f9a4e5c9e1e04f7f710383631d1470364Marco Nelissen    if (property_get_bool("rw.media.record.test", false)) {
115507ec01904613a0bac32caaa8444b4690998faed7James Dong        return true;
115607ec01904613a0bac32caaa8444b4690998faed7James Dong    }
115707ec01904613a0bac32caaa8444b4690998faed7James Dong    return false;
115807ec01904613a0bac32caaa8444b4690998faed7James Dong}
115907ec01904613a0bac32caaa8444b4690998faed7James Dong
116070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() {
116107ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send session summary only if test mode is enabled
116207ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
116307ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
116407ec01904613a0bac32caaa8444b4690998faed7James Dong    }
116507ec01904613a0bac32caaa8444b4690998faed7James Dong
116670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
116770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong         it != mChunkInfos.end(); ++it) {
116870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int trackNum = it->mTrack->getTrackId() << 28;
116970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
117070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS,
117170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs);
117270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    }
117370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong}
117470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
117513aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
117613aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
117713aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
117813aec890216948b0c364f8f92792129d0335f506James Dong}
117913aec890216948b0c364f8f92792129d0335f506James Dong
118013aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() {
118113aec890216948b0c364f8f92792129d0335f506James Dong    mLock.lock();
118213aec890216948b0c364f8f92792129d0335f506James Dong}
118313aec890216948b0c364f8f92792129d0335f506James Dong
118413aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() {
118513aec890216948b0c364f8f92792129d0335f506James Dong    mLock.unlock();
118613aec890216948b0c364f8f92792129d0335f506James Dong}
118720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1188c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
1189c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
119020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1191c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    ::write(mFd,
1192c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          (const uint8_t *)buffer->data() + buffer->range_offset(),
1193c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          buffer->range_length());
119420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
119520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
119620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
119720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
119820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
119920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
120003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
120103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
120203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
120303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
120403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
120503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
120603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
120703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
120803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
120903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
121003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
121103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
121203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
121303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
121480f78b773f92048944a850efb7b60629643370cdPraveen Chavanoff64_t MPEG4Writer::addMultipleLengthPrefixedSamples_l(MediaBuffer *buffer) {
121580f78b773f92048944a850efb7b60629643370cdPraveen Chavan    off64_t old_offset = mOffset;
121680f78b773f92048944a850efb7b60629643370cdPraveen Chavan
121780f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const size_t kExtensionNALSearchRange = 64; // bytes to look for non-VCL NALUs
121880f78b773f92048944a850efb7b60629643370cdPraveen Chavan
121980f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *dataStart = (const uint8_t *)buffer->data() + buffer->range_offset();
122080f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *currentNalStart = dataStart;
122180f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *nextNalStart;
122280f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *data = dataStart;
122380f78b773f92048944a850efb7b60629643370cdPraveen Chavan    size_t nextNalSize;
122480f78b773f92048944a850efb7b60629643370cdPraveen Chavan    size_t searchSize = buffer->range_length() > kExtensionNALSearchRange ?
122580f78b773f92048944a850efb7b60629643370cdPraveen Chavan                   kExtensionNALSearchRange : buffer->range_length();
122680f78b773f92048944a850efb7b60629643370cdPraveen Chavan
122780f78b773f92048944a850efb7b60629643370cdPraveen Chavan    while (getNextNALUnit(&data, &searchSize, &nextNalStart,
122880f78b773f92048944a850efb7b60629643370cdPraveen Chavan            &nextNalSize, true) == OK) {
122910cc12c4eec9ff974edb72f9140b05762fa50907Lajos Molnar        size_t currentNalSize = nextNalStart - currentNalStart - 4 /* strip start-code */;
123080f78b773f92048944a850efb7b60629643370cdPraveen Chavan        MediaBuffer *nalBuf = new MediaBuffer((void *)currentNalStart, currentNalSize);
123180f78b773f92048944a850efb7b60629643370cdPraveen Chavan        addLengthPrefixedSample_l(nalBuf);
123280f78b773f92048944a850efb7b60629643370cdPraveen Chavan        nalBuf->release();
123380f78b773f92048944a850efb7b60629643370cdPraveen Chavan
123480f78b773f92048944a850efb7b60629643370cdPraveen Chavan        currentNalStart = nextNalStart;
123580f78b773f92048944a850efb7b60629643370cdPraveen Chavan    }
123680f78b773f92048944a850efb7b60629643370cdPraveen Chavan
123780f78b773f92048944a850efb7b60629643370cdPraveen Chavan    size_t currentNalOffset = currentNalStart - dataStart;
123880f78b773f92048944a850efb7b60629643370cdPraveen Chavan    buffer->set_range(buffer->range_offset() + currentNalOffset,
123980f78b773f92048944a850efb7b60629643370cdPraveen Chavan            buffer->range_length() - currentNalOffset);
124080f78b773f92048944a850efb7b60629643370cdPraveen Chavan    addLengthPrefixedSample_l(buffer);
124180f78b773f92048944a850efb7b60629643370cdPraveen Chavan
124280f78b773f92048944a850efb7b60629643370cdPraveen Chavan    return old_offset;
124380f78b773f92048944a850efb7b60629643370cdPraveen Chavan}
124480f78b773f92048944a850efb7b60629643370cdPraveen Chavan
1245c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
1246c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
124730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
124830ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
124903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1250b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mUse4ByteNalLength) {
1251b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 24;
1252c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1253b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 16) & 0xff;
1254c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1255b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 8) & 0xff;
1256c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1257b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
1258c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1259c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong
1260c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd,
1261c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              (const uint8_t *)buffer->data() + buffer->range_offset(),
1262c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              length);
1263b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
1264b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 4;
1265b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
126643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_LT(length, 65536);
126730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1268b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 8;
1269c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1270b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
1271c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1272c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length);
1273b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 2;
1274b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
127530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
127630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
127730ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
127830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
12797837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write(
1280674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        const void *ptr, size_t size, size_t nmemb) {
12817837c17063a4c50bc856ba59418516fdab731de7James Dong
12827837c17063a4c50bc856ba59418516fdab731de7James Dong    const size_t bytes = size * nmemb;
12837837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
12847b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
1285c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
12861acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        if (moovBoxSize > mEstimatedMoovBoxSize) {
12877b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // The reserved moov box at the beginning of the file
12887b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // is not big enough. Moov box should be written to
12897b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // the end of the file from now on, but not to the
12907b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // in-memory cache.
12917b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
12927b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // We write partial moov box that is in the memory to
12937b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // the file first.
1294c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            for (List<off64_t>::iterator it = mBoxes.begin();
12957837c17063a4c50bc856ba59418516fdab731de7James Dong                 it != mBoxes.end(); ++it) {
12967837c17063a4c50bc856ba59418516fdab731de7James Dong                (*it) += mOffset;
12977837c17063a4c50bc856ba59418516fdab731de7James Dong            }
1298674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            lseek64(mFd, mOffset, SEEK_SET);
1299674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset);
13007b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            ::write(mFd, ptr, bytes);
13017837c17063a4c50bc856ba59418516fdab731de7James Dong            mOffset += (bytes + mMoovBoxBufferOffset);
13027b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
13037b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // All subsequent moov box content will be written
13047b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // to the end of the file.
13057837c17063a4c50bc856ba59418516fdab731de7James Dong            mWriteMoovBoxToMemory = false;
13067837c17063a4c50bc856ba59418516fdab731de7James Dong        } else {
13077837c17063a4c50bc856ba59418516fdab731de7James Dong            memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
13087837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset += bytes;
13097837c17063a4c50bc856ba59418516fdab731de7James Dong        }
13107837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1311674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        ::write(mFd, ptr, size * nmemb);
13127837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset += bytes;
13137837c17063a4c50bc856ba59418516fdab731de7James Dong    }
13147837c17063a4c50bc856ba59418516fdab731de7James Dong    return bytes;
13157837c17063a4c50bc856ba59418516fdab731de7James Dong}
13167837c17063a4c50bc856ba59418516fdab731de7James Dong
1317e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::beginBox(uint32_t id) {
1318e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    mBoxes.push_back(mWriteMoovBoxToMemory?
1319e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            mMoovBoxBufferOffset: mOffset);
1320e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
1321e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0);
1322e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(id);
1323e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
1324e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
132520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
13260c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(fourcc), 4);
132720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13287837c17063a4c50bc856ba59418516fdab731de7James Dong    mBoxes.push_back(mWriteMoovBoxToMemory?
13297837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset: mOffset);
133020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
133120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
133220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
133320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
133420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
133520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
13360c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
133720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1338c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = *--mBoxes.end();
133920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
134020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13417837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
13427837c17063a4c50bc856ba59418516fdab731de7James Dong       int32_t x = htonl(mMoovBoxBufferOffset - offset);
13437837c17063a4c50bc856ba59418516fdab731de7James Dong       memcpy(mMoovBoxBuffer + offset, &x, 4);
13447837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1345c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, offset, SEEK_SET);
13467837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mOffset - offset);
13477837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset -= 4;
1348c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
13497837c17063a4c50bc856ba59418516fdab731de7James Dong    }
135020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
135120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
135220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
1353674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 1);
135420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
135520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
135620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
135720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
1358674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 2);
135920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
136020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
136120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
136220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
1363674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 4);
136420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
136520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
136620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
136720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
1368674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 8);
136920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
137020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
137120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
137220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
1373674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, n + 1);
137420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
137520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
137620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
13770c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(s), 4);
1378674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, 4);
137920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
138020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
138107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
138207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format
138307b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) {
138407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
138507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
138607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
138707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
138807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[9];
138907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
139007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
139107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%c%.2d.", sign, wholePart);
139207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
139307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%+.2d.", wholePart);
139407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
139507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
139607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
139707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
139807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
139907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
140007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
140107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[4], 5, "%.4d", fractionalPart);
140207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
140307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
140407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 8);
140507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
140607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
140707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format
140807b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) {
140907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
141007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
141107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
141207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
141307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[10];
141407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
141507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
141607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%c%.3d.", sign, wholePart);
141707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
141807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%+.3d.", wholePart);
141907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
142007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
142107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
142207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
142307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
142407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
142507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
142607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[5], 5, "%.4d", fractionalPart);
142707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
142807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
142907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 9);
143007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
143107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
143207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
143307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
143407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and
143507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000.
143607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and
143707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180]
143807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
143907b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) {
144007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Is latitude or longitude out of range?
144107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (latitudex10000 < -900000 || latitudex10000 > 900000 ||
144207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        longitudex10000 < -1800000 || longitudex10000 > 1800000) {
144307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        return BAD_VALUE;
144407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
144507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
144607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLatitudex10000 = latitudex10000;
144707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLongitudex10000 = longitudex10000;
144807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mAreGeoTagsAvailable = true;
14497c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += 30;
145007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    return OK;
145107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
145207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
1453e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangstatus_t MPEG4Writer::setCaptureRate(float captureFps) {
1454e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    if (captureFps <= 0.0f) {
1455e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        return BAD_VALUE;
1456e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
1457e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
14587c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMetaKeys->setFloat(kMetaKey_CaptureFps, captureFps);
14597c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += sizeof(kMetaKey_CaptureFps) + 4 + 32;
14607c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
1461e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    return OK;
1462e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
1463e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
14644dbff11975e737482537e1636051690188f3fbc4Praveen Chavanstatus_t MPEG4Writer::setTemporalLayerCount(uint32_t layerCount) {
14654dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    if (layerCount > 9) {
14664dbff11975e737482537e1636051690188f3fbc4Praveen Chavan        return BAD_VALUE;
14674dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    }
14684dbff11975e737482537e1636051690188f3fbc4Praveen Chavan
14694dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    if (layerCount > 0) {
14704dbff11975e737482537e1636051690188f3fbc4Praveen Chavan        mMetaKeys->setInt32(kMetaKey_TemporalLayerCount, layerCount);
14714dbff11975e737482537e1636051690188f3fbc4Praveen Chavan        mMoovExtraSize += sizeof(kMetaKey_TemporalLayerCount) + 4 + 32;
14724dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    }
14734dbff11975e737482537e1636051690188f3fbc4Praveen Chavan
14744dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    return OK;
14754dbff11975e737482537e1636051690188f3fbc4Praveen Chavan}
14764dbff11975e737482537e1636051690188f3fbc4Praveen Chavan
1477fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::notifyApproachingLimit() {
1478fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    Mutex::Autolock autolock(mLock);
1479fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    // Only notify once.
1480fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mSendNotify) {
1481fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return;
1482fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1483fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGW("Recorded file size is approaching limit %" PRId64 "bytes",
1484fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mMaxFileSizeLimitBytes);
1485fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING, 0);
1486fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mSendNotify = true;
1487fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
1488fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
148920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
1490674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(data, 1, size);
149120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
149220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
149378a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const {
149478a1a286f736888ae7af8860b2c424af0d978848James Dong    return mStreamableFile;
149578a1a286f736888ae7af8860b2c424af0d978848James Dong}
149678a1a286f736888ae7af8860b2c424af0d978848James Dong
1497d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() {
1498d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1499d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeLimitBytes == 0) {
1500d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1501d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1502956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
1503d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1504d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1505d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
1506d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
15071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
150877e8ae9967a078770416619e99ddb5b010def312James Dong    if (!mStreamableFile) {
150977e8ae9967a078770416619e99ddb5b010def312James Dong        // Add 1024 bytes as error tolerance
151077e8ae9967a078770416619e99ddb5b010def312James Dong        return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes;
151177e8ae9967a078770416619e99ddb5b010def312James Dong    }
1512fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1513acd234bba9f048971d66890009eeff9a8db94be3James Dong    // Be conservative in the estimate: do not exceed 95% of
1514acd234bba9f048971d66890009eeff9a8db94be3James Dong    // the target file limit. For small target file size limit, though,
1515acd234bba9f048971d66890009eeff9a8db94be3James Dong    // this will not help.
1516acd234bba9f048971d66890009eeff9a8db94be3James Dong    return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100);
1517d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1518d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1519fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangbool MPEG4Writer::approachingFileSizeLimit() {
1520fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    // No limit
1521fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mMaxFileSizeLimitBytes == 0) {
1522fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return false;
1523fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1524fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1525fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
1526fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    for (List<Track *>::iterator it = mTracks.begin();
1527fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         it != mTracks.end(); ++it) {
1528fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
1529fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1530fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1531fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (!mStreamableFile) {
1532fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        // Add 1024 bytes as error tolerance
1533fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return nTotalBytesEstimate + 1024 >= (90 * mMaxFileSizeLimitBytes) / 100;
1534fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1535fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1536fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    return (nTotalBytesEstimate >= (90 * mMaxFileSizeLimitBytes) / 100);
1537fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
1538fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1539d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() {
1540d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1541d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationLimitUs == 0) {
1542d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1543d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1544d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1545d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1546d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1547d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
1548d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            return true;
1549d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1550d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1551d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return false;
1552d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1553d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
155425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
155525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
155625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
155725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
155825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
155925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
156025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
156125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
156225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
156325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
156425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
156525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
156625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
1567f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
1568a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGI("setStartTimestampUs: %" PRId64, timeUs);
156943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(timeUs, 0ll);
15703c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
1571065d1aff96818df54456053f1574aec8a234d0deJames Dong    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
1572f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimestampUs = timeUs;
1573a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Earliest track starting time: %" PRId64, mStartTimestampUs);
15743c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    }
15753c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
15763c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
1577f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() {
15783c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
15793c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    return mStartTimestampUs;
15803c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
15813c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
158258ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() {
158358ae9c530247668f8af36e30d228c716c226b3d4James Dong    Mutex::Autolock autolock(mLock);
158458ae9c530247668f8af36e30d228c716c226b3d4James Dong    return mTracks.size();
158558ae9c530247668f8af36e30d228c716c226b3d4James Dong}
158658ae9c530247668f8af36e30d228c716c226b3d4James Dong
158720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
158820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
158920111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
1590b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen        MPEG4Writer *owner, const sp<IMediaSource> &source, size_t trackId)
159120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
159225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
159320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
159420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
1595a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
1596a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mResumed(false),
1597eaae38445a340c4857c1c5569475879a728e63b7James Dong      mStarted(false),
1598fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mGotStartKeyFrame(false),
15999db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang      mIsMalformed(false),
1600bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong      mTrackId(trackId),
1601c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong      mTrackDurationUs(0),
1602956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mEstimatedTrackSizeBytes(0),
1603be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong      mSamplesHaveSameSize(true),
1604c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mStszTableEntries(new ListTableEntries<uint32_t, 1>(1000)),
1605c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mStcoTableEntries(new ListTableEntries<uint32_t, 1>(1000)),
1606c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mCo64TableEntries(new ListTableEntries<off64_t, 1>(1000)),
1607c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mStscTableEntries(new ListTableEntries<uint32_t, 3>(1000)),
1608c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mStssTableEntries(new ListTableEntries<uint32_t, 1>(1000)),
1609c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mSttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)),
1610c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mCttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)),
161120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
161225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
1613548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
161413f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mReachedEOS(false),
161513f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mRotation(0) {
161619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    getCodecSpecificDataFromInputFormatIfPossible();
16178f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
16181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    const char *mime;
16191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMeta->findCString(kKeyMIMEType, &mime);
16201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
16219aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mIsHevc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC);
16221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAudio = !strncasecmp(mime, "audio/", 6);
162325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mIsVideo = !strncasecmp(mime, "video/", 6);
16241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
16251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
16261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1627b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar    // store temporal layer count
162825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (mIsVideo) {
1629b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar        int32_t count;
1630b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar        if (mMeta->findInt32(kKeyTemporalLayerCount, &count) && count > 1) {
1631b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar            mOwner->setTemporalLayerCount(count);
1632b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar        }
1633b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar    }
1634b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar
1635c059860c73678a202bfa33062723e8f82fb779d9James Dong    setTimeScale();
1636c059860c73678a202bfa33062723e8f82fb779d9James Dong}
1637c059860c73678a202bfa33062723e8f82fb779d9James Dong
1638fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang// Clear all the internal states except the CSD data.
1639fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::Track::resetInternal() {
1640fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mDone = false;
1641fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mPaused = false;
1642fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mResumed = false;
1643fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mStarted = false;
1644fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mGotStartKeyFrame = false;
1645fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mIsMalformed = false;
1646fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mTrackDurationUs = 0;
1647fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mEstimatedTrackSizeBytes = 0;
1648fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mSamplesHaveSameSize = 0;
1649fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mStszTableEntries != NULL) {
1650fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mStszTableEntries;
1651fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mStszTableEntries = new ListTableEntries<uint32_t, 1>(1000);
1652fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1653fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1654fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mStcoTableEntries != NULL) {
1655fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mStcoTableEntries;
1656fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mStcoTableEntries = new ListTableEntries<uint32_t, 1>(1000);
1657fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1658fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mCo64TableEntries != NULL) {
1659fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mCo64TableEntries;
1660fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mCo64TableEntries = new ListTableEntries<off64_t, 1>(1000);
1661fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1662fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1663fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mStscTableEntries != NULL) {
1664fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mStscTableEntries;
1665fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mStscTableEntries = new ListTableEntries<uint32_t, 3>(1000);
1666fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1667fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mStssTableEntries != NULL) {
1668fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mStssTableEntries;
1669fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mStssTableEntries = new ListTableEntries<uint32_t, 1>(1000);
1670fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1671fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mSttsTableEntries != NULL) {
1672fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mSttsTableEntries;
1673fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mSttsTableEntries = new ListTableEntries<uint32_t, 2>(1000);
1674fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1675fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mCttsTableEntries != NULL) {
1676fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mCttsTableEntries;
1677fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mCttsTableEntries = new ListTableEntries<uint32_t, 2>(1000);
1678fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1679fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mReachedEOS = false;
1680fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
1681fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
16821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() {
16831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1684c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t stcoBoxCount = (mOwner->use32BitFileOffset()
1685c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                            ? mStcoTableEntries->count()
1686c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                            : mCo64TableEntries->count());
1687c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    int64_t stcoBoxSizeBytes = stcoBoxCount * 4;
1688c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4);
16891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
169078a1a286f736888ae7af8860b2c424af0d978848James Dong    mEstimatedTrackSizeBytes = mMdatSizeBytes;  // media data size
169178a1a286f736888ae7af8860b2c424af0d978848James Dong    if (!mOwner->isFileStreamable()) {
169278a1a286f736888ae7af8860b2c424af0d978848James Dong        // Reserved free space is not large enough to hold
169378a1a286f736888ae7af8860b2c424af0d978848James Dong        // all meta data and thus wasted.
1694c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 +  // stsc box size
1695c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mStssTableEntries->count() * 4 +   // stss box size
1696c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mSttsTableEntries->count() * 8 +   // stts box size
1697c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mCttsTableEntries->count() * 8 +   // ctts box size
169878a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stcoBoxSizeBytes +           // stco box size
169978a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stszBoxSizeBytes;            // stsz box size
170078a1a286f736888ae7af8860b2c424af0d978848James Dong    }
17011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
17021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
17031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry(
17041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        size_t chunkId, size_t sampleId) {
17051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1706c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(chunkId));
1707c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(sampleId));
1708c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(1));
17091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
17101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
17111f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) {
1712c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->add(htonl(sampleId));
17131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
17141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
17151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry(
171679761ab096f57c3027fad9556c2bc436672d614eJames Dong        size_t sampleCount, int32_t duration) {
17171f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
17185a217fba010e801c255503602bda4b86ac5a6ac9James Dong    if (duration == 0) {
1719377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGW("0-duration samples found: %zu", sampleCount);
17205a217fba010e801c255503602bda4b86ac5a6ac9James Dong    }
1721c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(sampleCount));
1722c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(duration));
17231f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
17241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1725965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry(
1726965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        size_t sampleCount, int32_t duration) {
1727965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
172825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (!mIsVideo) {
1729965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
1730965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
1731c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(sampleCount));
1732c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(duration));
1733965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
1734965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1735fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::setNextFd(int fd) {
1736fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGV("addNextFd");
1737fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    Mutex::Autolock l(mLock);
1738fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mLooper == NULL) {
1739fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mReflector = new AHandlerReflector<MPEG4Writer>(this);
1740fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mLooper = new ALooper;
1741fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mLooper->registerHandler(mReflector);
1742fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mLooper->start();
1743fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1744fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1745fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mNextFd != -1) {
1746fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        // No need to set a new FD yet.
1747fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return INVALID_OPERATION;
1748fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1749fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mNextFd = fd;
1750fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    return OK;
1751fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
1752fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1753c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) {
1754c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mOwner->use32BitFileOffset()) {
1755c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t value = offset;
1756c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->add(htonl(value));
1757c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
1758c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->add(hton64(offset));
1759c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    }
17601f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
17611f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1762c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() {
17633856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setTimeScale");
1764c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Default time scale
1765c059860c73678a202bfa33062723e8f82fb779d9James Dong    mTimeScale = 90000;
1766c059860c73678a202bfa33062723e8f82fb779d9James Dong
1767c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mIsAudio) {
1768c059860c73678a202bfa33062723e8f82fb779d9James Dong        // Use the sampling rate as the default time scale for audio track.
1769c059860c73678a202bfa33062723e8f82fb779d9James Dong        int32_t sampleRate;
1770c059860c73678a202bfa33062723e8f82fb779d9James Dong        bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
1771c059860c73678a202bfa33062723e8f82fb779d9James Dong        CHECK(success);
1772c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = sampleRate;
1773c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1774c059860c73678a202bfa33062723e8f82fb779d9James Dong
1775c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If someone would like to overwrite the timescale, use user-supplied value.
1776c059860c73678a202bfa33062723e8f82fb779d9James Dong    int32_t timeScale;
1777c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
1778c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = timeScale;
1779c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1780c059860c73678a202bfa33062723e8f82fb779d9James Dong
178143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
178219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber}
178319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
1784fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::onMessageReceived(const sp<AMessage> &msg) {
1785fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    switch (msg->what()) {
1786fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        case kWhatSwitch:
1787fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        {
1788fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            finishCurrentSession();
1789fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mLock.lock();
1790fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            int fd = mNextFd;
1791fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mNextFd = -1;
1792fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mLock.unlock();
1793fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            initInternal(fd);
1794fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            start(mStartMeta.get());
1795fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mSwitchPending = false;
1796fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED, 0);
1797fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            break;
1798fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        }
1799fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        default:
1800fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        TRESPASS();
1801fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1802fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
1803fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
180419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
180519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    const char *mime;
1806fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
180719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
180819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
18099aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    uint32_t type;
18109aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const void *data = NULL;
18119aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t size = 0;
181219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
18139aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mMeta->findData(kKeyAVCC, &type, &data, &size);
18149aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
18159aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mMeta->findData(kKeyHVCC, &type, &data, &size);
181619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
181719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
181819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
181919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            ESDS esds(data, size);
18209aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            if (esds.getCodecSpecificInfo(&data, &size) != OK) {
18219aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                data = NULL;
18229aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                size = 0;
182319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            }
182419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
182519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
18269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (data != NULL && copyCodecSpecificData((uint8_t *)data, size) == OK) {
18279aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mGotAllCodecSpecificData = true;
18289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
182920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
183020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
183120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
183220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
183320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1834c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStszTableEntries;
1835c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStcoTableEntries;
1836c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCo64TableEntries;
1837c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStscTableEntries;
1838c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mSttsTableEntries;
1839c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStssTableEntries;
1840c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCttsTableEntries;
1841c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
1842c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries = NULL;
1843c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStcoTableEntries = NULL;
1844c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCo64TableEntries = NULL;
1845c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries = NULL;
1846c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries = NULL;
1847c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries = NULL;
1848c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries = NULL;
1849c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
185020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
185120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
185220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
185320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
185420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
185520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
185693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
18573856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("initTrackingProgressStatus");
185893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mPreviousTrackTimeUs = -1;
185993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackingProgressStatus = false;
186093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
186193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    {
186293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeUs;
186393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
1864a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGV("Receive request to track progress status for every %" PRId64 " us", timeUs);
186593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackEveryTimeDurationUs = timeUs;
186693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackingProgressStatus = true;
186793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
186893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
186993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
187093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
18711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static
18721c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) {
18733856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("ThreadWrapper: %p", me);
18741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
18751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    writer->threadFunc();
18761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return NULL;
18771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
18781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18791c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) {
18803856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk: %p", chunk.mTrack);
18811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Mutex::Autolock autolock(mLock);
18821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK_EQ(mDone, false);
18831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
18851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
18861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (chunk.mTrack == it->mTrack) {  // Found owner
18881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            it->mChunks.push_back(chunk);
18891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.signal();
18901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            return;
18911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
18921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
18931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
189443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK(!"Received a chunk for a unknown track");
18951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
18961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1897fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) {
1898a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("writeChunkToFile: %" PRId64 " from %s track",
189925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        chunk->mTimeStampUs, chunk->mTrack->getTrackType());
1900fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1901fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    int32_t isFirstSample = true;
1902fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    while (!chunk->mSamples.empty()) {
1903fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        List<MediaBuffer *>::iterator it = chunk->mSamples.begin();
1904fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
19059aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        off64_t offset = (chunk->mTrack->isAvc() || chunk->mTrack->isHevc())
190680f78b773f92048944a850efb7b60629643370cdPraveen Chavan                                ? addMultipleLengthPrefixedSamples_l(*it)
1907fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong                                : addSample_l(*it);
1908fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1909fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (isFirstSample) {
1910fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            chunk->mTrack->addChunkOffset(offset);
1911fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            isFirstSample = false;
19121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
19131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
19141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it)->release();
19151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it) = NULL;
1916fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        chunk->mSamples.erase(it);
19171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1918fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    chunk->mSamples.clear();
19191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
19201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1921fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() {
19223856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeAllChunks");
19231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    size_t outstandingChunks = 0;
192470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    Chunk chunk;
192570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    while (findChunkToWrite(&chunk)) {
1926e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong        writeChunkToFile(&chunk);
192770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        ++outstandingChunks;
19281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
192970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
193070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    sendSessionSummary();
193170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
19321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mChunkInfos.clear();
1933377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    ALOGD("%zu chunks are written in the last batch", outstandingChunks);
19341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
19351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1936fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) {
19373856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("findChunkToWrite");
19381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
19391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
19401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Track *track = NULL;
19411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
19421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
19431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (!it->mChunks.empty()) {
19441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            List<Chunk>::iterator chunkIt = it->mChunks.begin();
19451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (chunkIt->mTimeStampUs < minTimestampUs) {
19461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                minTimestampUs = chunkIt->mTimeStampUs;
19471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                track = it->mTrack;
19481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            }
19491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
19501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
19511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
19521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (track == NULL) {
19533856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Nothing to be written after all");
1954fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        return false;
19551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
19561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
19571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mIsFirstChunk) {
19581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsFirstChunk = false;
19591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1960fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
19611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
19621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
19631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it->mTrack == track) {
1964fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            *chunk = *(it->mChunks.begin());
1965fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            it->mChunks.erase(it->mChunks.begin());
1966fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            CHECK_EQ(chunk->mTrack, track);
196770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
196870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t interChunkTimeUs =
196970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                chunk->mTimeStampUs - it->mPrevChunkTimestampUs;
197070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            if (interChunkTimeUs > it->mPrevChunkTimestampUs) {
197170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs = interChunkTimeUs;
197270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            }
197370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
1974fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            return true;
19751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
19761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1977fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1978fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    return false;
19791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
19801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
19811c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() {
19823856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("threadFunc");
19831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1984a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0);
1985fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1986fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    Mutex::Autolock autoLock(mLock);
19871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mDone) {
1988fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        Chunk chunk;
1989fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        bool chunkFound = false;
1990fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1991fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) {
19921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.wait(mLock);
19931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
19941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1995de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // In real time recording mode, write without holding the lock in order
1996de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // to reduce the blocking time for media track threads.
1997de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // Otherwise, hold the lock until the existing chunks get written to the
1998de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // file.
1999fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (chunkFound) {
2000de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            if (mIsRealTimeRecording) {
2001de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui                mLock.unlock();
2002de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            }
2003fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            writeChunkToFile(&chunk);
2004de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            if (mIsRealTimeRecording) {
2005de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui                mLock.lock();
2006de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            }
2007fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        }
20081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
2009fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
2010fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    writeAllChunks();
20111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
20121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
20131c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() {
20143856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("startWriterThread");
20151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
20161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mDone = false;
20171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsFirstChunk = true;
2018e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    mDriftTimeUs = 0;
20191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<Track *>::iterator it = mTracks.begin();
20201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mTracks.end(); ++it) {
20211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        ChunkInfo info;
20221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        info.mTrack = *it;
202370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mPrevChunkTimestampUs = 0;
202470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mMaxInterChunkDurUs = 0;
20251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.push_back(info);
20261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
20271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
20281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_t attr;
20291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_init(&attr);
20301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
20311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_create(&mThread, &attr, ThreadWrapper, this);
20321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_destroy(&attr);
2033411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = true;
20341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
20351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
20361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
20371f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
203893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) {
2039a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (!mDone && mPaused) {
2040a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mPaused = false;
2041a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mResumed = true;
2042a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
2043a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
204425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
204593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t startTimeUs;
204619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
204719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        startTimeUs = 0;
204819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
204970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    mStartTimeRealUs = startTimeUs;
205019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
205113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t rotationDegrees;
205225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (mIsVideo && params && params->findInt32(kKeyRotation, &rotationDegrees)) {
205313f6284305e4b27395a23db7882d670bdb1bcae1James Dong        mRotation = rotationDegrees;
205413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
205513f6284305e4b27395a23db7882d670bdb1bcae1James Dong
205693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    initTrackingProgressStatus(params);
205793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
2058f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    sp<MetaData> meta = new MetaData;
2059de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) {
2060a472613aec322e25891abf5c77bf3f7e3c244920James Dong        /*
2061a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * This extra delay of accepting incoming audio/video signals
2062a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * helps to align a/v start time at the beginning of a recording
2063a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * session, and it also helps eliminate the "recording" sound for
2064a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * camcorder applications.
2065a472613aec322e25891abf5c77bf3f7e3c244920James Dong         *
206686b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * If client does not set the start time offset, we fall back to
206786b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * use the default initial delay value.
2068a472613aec322e25891abf5c77bf3f7e3c244920James Dong         */
206986b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
207086b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
207186b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
207286b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
207386b7f47aa7482424cf8fd248f1315311919be3b0James Dong        startTimeUs += startTimeOffsetUs;
2074a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Start time offset: %" PRId64 " us", startTimeOffsetUs);
2075a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
2076a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2077f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    meta->setInt64(kKeyTime, startTimeUs);
2078a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2079f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    status_t err = mSource->start(meta.get());
208025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
208125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
208225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
208325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
208420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
208520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
208620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
208720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
208820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
208920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
2090eaae38445a340c4857c1c5569475879a728e63b7James Dong    mStarted = true;
2091c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs = 0;
209225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
2093956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mEstimatedTrackSizeBytes = 0;
20941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mMdatSizeBytes = 0;
209543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mMaxChunkDurationUs = 0;
2096826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar    mLastDecodingTimeUs = -1;
209720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
209825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
209920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
210025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
210125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
210220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
210320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
210437187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() {
2105a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
210637187916a486504acaf83bea30147eb5fbf46ae5James Dong    return OK;
2107a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
2108a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2109fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::Track::stop(bool stopSource) {
2110fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGD("%s track stopping. %s source", getTrackType(), stopSource ? "Stop" : "Not Stop");
2111eaae38445a340c4857c1c5569475879a728e63b7James Dong    if (!mStarted) {
211229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Stop() called but track is not started");
2113eaae38445a340c4857c1c5569475879a728e63b7James Dong        return ERROR_END_OF_STREAM;
2114eaae38445a340c4857c1c5569475879a728e63b7James Dong    }
2115eaae38445a340c4857c1c5569475879a728e63b7James Dong
211620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
211737187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
211820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
211920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = true;
2120fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (stopSource) {
2121fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        ALOGD("%s track source stopping", getTrackType());
2122fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mSource->stop();
2123fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        ALOGD("%s track source stopped", getTrackType());
2124fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
212572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
212620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
212720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
2128377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy));
212937187916a486504acaf83bea30147eb5fbf46ae5James Dong
2130fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGD("%s track stopped. %s source", getTrackType(), stopSource ? "Stop" : "Not Stop");
213137187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
213220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
213320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
213425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
213525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
213625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
213725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
213820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
213920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
214020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
214120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
214237187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = track->threadEntry();
2143377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    return (void *)(uintptr_t)err;
214420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
214520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) {
21473856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("getNalUnitType: %d", byte);
21483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // nal_unit_type: 5-bit unsigned integer
21503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *type = (byte & 0x1F);
21513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
21523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet(
21543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
21553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21563856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseParamSet");
21573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    CHECK(type == kNalUnitTypeSeqParamSet ||
21583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong          type == kNalUnitTypePicParamSet);
21593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
216047d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar    const uint8_t *nextStartCode = findNextNalStartCode(data, length);
21613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *paramSetLen = nextStartCode - data;
21623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (*paramSetLen == 0) {
216329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Param set is malformed, since its length is 0");
21643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return NULL;
21653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
21663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    AVCParamSet paramSet(*paramSetLen, data);
21683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (type == kNalUnitTypeSeqParamSet) {
21693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (*paramSetLen < 4) {
217029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Seq parameter set malformed");
21713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return NULL;
21723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
21733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mSeqParamSets.empty()) {
21743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc = data[1];
21753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileCompatible = data[2];
21763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mLevelIdc = data[3];
21773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
21783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (mProfileIdc != data[1] ||
21793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mProfileCompatible != data[2] ||
21803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mLevelIdc != data[3]) {
218107b2fbfb40770f3be0f674596f2e51d257c6d2bdLajos Molnar                // COULD DO: set profile/level to the lowest required to support all SPSs
218229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Inconsistent profile/level found in seq parameter sets");
21833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return NULL;
21843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
21853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
21863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mSeqParamSets.push_back(paramSet);
21873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    } else {
21883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mPicParamSets.push_back(paramSet);
21893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
21903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return nextStartCode;
21913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
21923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData(
21943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
21953856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("copyAVCCodecSpecificData");
21963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 2 bytes for each of the parameter set length field
21983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // plus the 7 bytes for the header
21999aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return copyCodecSpecificData(data, size, 4 + 7);
22009aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
22019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyHEVCCodecSpecificData(
22039aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size) {
22049aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ALOGV("copyHEVCCodecSpecificData");
22059aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22069aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Min length of HEVC CSD is 23. (ISO/IEC 14496-15:2014 Chapter 8.3.3.1.2)
22079aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return copyCodecSpecificData(data, size, 23);
22089aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
22099aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22109aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyCodecSpecificData(
22119aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size, size_t minLength) {
22129aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (size < minLength) {
2213377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGE("Codec specific data length too short: %zu", size);
22143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return ERROR_MALFORMED;
22153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
22163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificData = malloc(size);
22189aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
22199aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
22209aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
22219aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
22229aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificDataSize = size;
22233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    memcpy(mCodecSpecificData, data, size);
22243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
22253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
22263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData(
22283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
22293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22303856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseAVCCodecSpecificData");
22313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data starts with a start code.
22323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // SPS and PPS are separated with start codes.
22333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Also, SPS must come before PPS
22343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t type = kNalUnitTypeSeqParamSet;
22353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotSps = false;
22363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotPps = false;
22373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *tmp = data;
22383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = data;
22393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = size;
22403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t paramSetLen = 0;
22413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = 0;
22423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
22433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        getNalUnitType(*(tmp + 4), &type);
22443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (type == kNalUnitTypeSeqParamSet) {
22453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (gotPps) {
224629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
22473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
22483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
22493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
22503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotSps = true;
22513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
22523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
22533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else if (type == kNalUnitTypePicParamSet) {
22543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
225529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
22563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
22573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
22583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotPps) {
22593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotPps = true;
22603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
22613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
22623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
226329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Only SPS and PPS Nal units are expected");
22643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
22653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
22663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nextStartCode == NULL) {
22683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
22693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
22703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Move on to find the next parameter set
22723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft -= nextStartCode - tmp;
22733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        tmp = nextStartCode;
22743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mCodecSpecificDataSize += (2 + paramSetLen);
22753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
22763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
22783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of seq parameter sets
22793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nSeqParamSets = mSeqParamSets.size();
22803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets == 0) {
228129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find sequence parameter set");
22823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
22833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
22843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets > 0x1F) {
2286377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets);
22873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
22883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
22893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
22903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
22923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of pic parameter sets
22933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nPicParamSets = mPicParamSets.size();
22943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets == 0) {
229529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find picture parameter set");
22963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
22973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
22983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets > 0xFF) {
2299377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets);
23003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
23013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
23023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
23031374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME:
23041374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above
23051374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0
23061374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0
23073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
23083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the profiles
23093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // These profiles requires additional parameter set extensions
23103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mProfileIdc == 100 || mProfileIdc == 110 ||
23113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc == 122 || mProfileIdc == 144) {
231229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
23133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return BAD_VALUE;
23143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
23153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
23161374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif
23173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
23183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
2319548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
232003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
232103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
2322548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
232303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
232429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Already have codec specific data");
232503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
232603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
232703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
23283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4) {
2329377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGE("Codec specific data length too short: %zu", size);
233003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
233103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
233203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
23333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data is in the form of AVCCodecSpecificData
23343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (memcmp("\x00\x00\x00\x01", data, 4)) {
23353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return copyAVCCodecSpecificData(data, size);
233603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
233703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
23383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (parseAVCCodecSpecificData(data, size) != OK) {
233903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
234003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
234103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
23423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // ISO 14496-15: AVC file format
23433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize += 7;  // 7 more bytes in the header
234403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
23459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
23469aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mCodecSpecificDataSize = 0;
23479aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
23489aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
23499aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
235003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
23513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = 1;                     // version
23523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[1] = mProfileIdc;           // profile indication
23533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[2] = mProfileCompatible;    // profile compatibility
23543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[3] = mLevelIdc;
235503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
23563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
2357b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mOwner->useNalLengthFour()) {
2358b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 3;  // length size == 4 bytes
2359b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
2360b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 1;  // length size == 2 bytes
2361b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
236203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
23633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 3-bit '111' followed by 5-bit numSequenceParameterSets
23643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nSequenceParamSets = mSeqParamSets.size();
23653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[5] = 0xe0 | nSequenceParamSets;
23663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 6;
23673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
23683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mSeqParamSets.end(); ++it) {
23693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit sequence parameter set length
23703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t seqParamSetLength = it->mLength;
23713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = seqParamSetLength >> 8;
23723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = seqParamSetLength & 0xff;
23733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
23743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // SPS NAL unit (sequence parameter length bytes)
23753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, seqParamSetLength);
23763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + seqParamSetLength);
23773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
23783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
23793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 8-bit nPictureParameterSets
23803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nPictureParamSets = mPicParamSets.size();
23813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = nPictureParamSets;
23823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 1;
23833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
23843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mPicParamSets.end(); ++it) {
23853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit picture parameter set length
23863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t picParamSetLength = it->mLength;
23873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = picParamSetLength >> 8;
23883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = picParamSetLength & 0xff;
23893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
23903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // PPS Nal unit (picture parameter set length bytes)
23913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, picParamSetLength);
23923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + picParamSetLength);
23933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
239403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
239503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
239603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
239703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
23989aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
23999aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::parseHEVCCodecSpecificData(
24009aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size, HevcParameterSets &paramSets) {
24019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ALOGV("parseHEVCCodecSpecificData");
24039aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const uint8_t *tmp = data;
24049aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const uint8_t *nextStartCode = data;
24059aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t bytesLeft = size;
24069aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
240747d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar        nextStartCode = findNextNalStartCode(tmp + 4, bytesLeft - 4);
24089aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        status_t err = paramSets.addNalUnit(tmp + 4, (nextStartCode - tmp) - 4);
24099aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (err != OK) {
24109aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
24119aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
24129aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24139aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        // Move on to find the next parameter set
24149aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        bytesLeft -= nextStartCode - tmp;
24159aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        tmp = nextStartCode;
24169aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
24179aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24189aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t csdSize = 23;
24199aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const size_t numNalUnits = paramSets.getNumNalUnits();
24209aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    for (size_t i = 0; i < ARRAY_SIZE(kMandatoryHevcNalUnitTypes); ++i) {
24219aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        int type = kMandatoryHevcNalUnitTypes[i];
24229aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        size_t numParamSets = paramSets.getNumNalUnitsOfType(type);
24239aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (numParamSets == 0) {
24249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            ALOGE("Cound not find NAL unit of type %d", type);
24259aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
24269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
24279aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
24289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    for (size_t i = 0; i < ARRAY_SIZE(kHevcNalUnitTypes); ++i) {
24299aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        int type = kHevcNalUnitTypes[i];
24309aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        size_t numParamSets = paramSets.getNumNalUnitsOfType(type);
24319aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (numParamSets > 0xffff) {
24329aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            ALOGE("Too many seq parameter sets (%zu) found", numParamSets);
24339aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
24349aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
24359aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        csdSize += 3;
24369aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        for (size_t j = 0; j < numNalUnits; ++j) {
24379aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            if (paramSets.getType(j) != type) {
24389aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                continue;
24399aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            }
24409aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            csdSize += 2 + paramSets.getSize(j);
24419aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
24429aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
24439aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificDataSize = csdSize;
24449aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return OK;
24459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
24469aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24479aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::makeHEVCCodecSpecificData(
24489aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size) {
24499aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24509aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData != NULL) {
24519aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Already have codec specific data");
24529aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
24539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
24549aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (size < 4) {
24569aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Codec specific data length too short: %zu", size);
24579aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
24589aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
24599aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24609aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Data is in the form of HEVCCodecSpecificData
24619aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (memcmp("\x00\x00\x00\x01", data, 4)) {
24629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return copyHEVCCodecSpecificData(data, size);
24639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
24649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    HevcParameterSets paramSets;
24669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (parseHEVCCodecSpecificData(data, size, paramSets) != OK) {
24673d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim        ALOGE("failed parsing codec specific data");
24689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
24699aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
24709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificData = malloc(mCodecSpecificDataSize);
24729aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
24739aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mCodecSpecificDataSize = 0;
24749aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
24759aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
24769aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
24779aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t err = paramSets.makeHvcc((uint8_t *)mCodecSpecificData,
24783d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim            &mCodecSpecificDataSize, mOwner->useNalLengthFour() ? 4 : 2);
24799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (err != OK) {
24803d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim        ALOGE("failed constructing HVCC atom");
24819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return err;
24829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
24839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return OK;
24859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
24869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
2487872a481558350634a3fd5cb67939de288af00ecbJames Dong/*
2488872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that
2489872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information
2490872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio
2491872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger
2492872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5,
2493872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined.
2494872a481558350634a3fd5cb67939de288af00ecbJames Dong */
2495872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) {
2496872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t driftTimeUs = 0;
2497872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) {
2498872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t prevDriftTimeUs = mOwner->getDriftTimeUs();
2499872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1;
2500872a481558350634a3fd5cb67939de288af00ecbJames Dong        mOwner->setDriftTimeUs(timeUs);
2501872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2502872a481558350634a3fd5cb67939de288af00ecbJames Dong}
2503872a481558350634a3fd5cb67939de288af00ecbJames Dong
250437187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() {
250530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
250613aec890216948b0c364f8f92792129d0335f506James Dong    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
250743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    const bool hasMultipleTracks = (mOwner->numTracks() > 1);
250813aec890216948b0c364f8f92792129d0335f506James Dong    int64_t chunkTimestampUs = 0;
250913aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nChunks = 0;
25107c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar    int32_t nActualFrames = 0;        // frames containing non-CSD data (non-0 length)
251113aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nZeroLengthFrames = 0;
2512965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastTimestampUs = 0;      // Previous sample time stamp
2513965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationUs = 0;       // Between the previous two samples
2514965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t currDurationTicks = 0;    // Timescale based ticks
2515965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationTicks = 0;    // Timescale based ticks
2516965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int32_t sampleCount = 1;          // Sample count in the current stts table entry
2517000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    uint32_t previousSampleSize = 0;  // Size of the previous sample
2518a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t previousPausedDurationUs = 0;
2519965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t timestampUs = 0;
2520000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t cttsOffsetTimeUs = 0;
2521000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t currCttsOffsetTimeTicks = 0;   // Timescale based ticks
2522000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t lastCttsOffsetTimeTicks = -1;  // Timescale based ticks
252343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    int32_t cttsSampleCount = 0;           // Sample count in the current ctts table entry
2524c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t lastSamplesPerChunk = 0;
2525e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2526a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    if (mIsAudio) {
2527a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
252825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else if (mIsVideo) {
2529a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
253025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else {
253125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        prctl(PR_SET_NAME, (unsigned long)"MetadataTrackEncoding", 0, 0, 0);
2532a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    }
2533de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
2534de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (mOwner->isRealTimeRecording()) {
2535de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
2536de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    }
2537985f838934510983d8a887461e98dca60a6e858fJames Dong
2538d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong    sp<MetaData> meta_data;
253920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
254093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t err = OK;
254120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
254225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    const char *trackName = getTrackType();
254393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    while (!mDone && (err = mSource->read(&buffer)) == OK) {
254420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
254520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
254620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
254713aec890216948b0c364f8f92792129d0335f506James Dong            ++nZeroLengthFrames;
254820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
254920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
255020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2551a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // If the codec specific data has not been received yet, delay pause.
2552a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // After the codec specific data is received, discard what we received
2553a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // when the track is to be paused.
2554a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused && !mResumed) {
2555a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer->release();
2556a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer = NULL;
2557a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            continue;
2558a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2559a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
256030ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
256130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
256203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
256303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
256403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
25657c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // if config format (at track addition) already had CSD, keep that
25667c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // UNLESS we have not received any frames yet.
25677c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // TODO: for now the entire CSD has to come in one frame for encoders, even though
25687c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // they need to be spread out for decoders.
25697c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            if (mGotAllCodecSpecificData && nActualFrames > 0) {
25707c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                ALOGI("ignoring additional CSD for video track after first frame");
25717c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            } else {
25727c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                mMeta = mSource->getFormat(); // get output format after format change
25737c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar
25747c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                if (mIsAvc) {
25757c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    status_t err = makeAVCCodecSpecificData(
25767c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            (const uint8_t *)buffer->data()
25777c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                                + buffer->range_offset(),
25787c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
25797c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    CHECK_EQ((status_t)OK, err);
25807c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                } else if (mIsHevc) {
25817c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    status_t err = makeHEVCCodecSpecificData(
25827c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            (const uint8_t *)buffer->data()
25837c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                                + buffer->range_offset(),
25847c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
25857c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    CHECK_EQ((status_t)OK, err);
25867c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                } else if (mIsMPEG4) {
25877c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    copyCodecSpecificData((const uint8_t *)buffer->data() + buffer->range_offset(),
25887c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
25897c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                }
259030ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
259130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
259230ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
259330ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
259430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
2595548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
259630ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
2597a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2598a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2599e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang        // Per-frame metadata sample's size must be smaller than max allowed.
2600e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang        if (!mIsVideo && !mIsAudio && buffer->range_length() >= kMaxMetadataSize) {
2601e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            ALOGW("Buffer size is %zu. Maximum metadata buffer size is %lld for %s track",
2602e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang                    buffer->range_length(), (long long)kMaxMetadataSize, trackName);
2603e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            buffer->release();
2604e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            mSource->stop();
2605e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            mIsMalformed = true;
2606e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            break;
2607e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang        }
2608e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang
26097c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar        ++nActualFrames;
26107c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar
2611d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // Make a deep copy of the MediaBuffer and Metadata and release
2612d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // the original as soon as we can
2613d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
2614d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
2615d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                buffer->range_length());
2616d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        copy->set_range(0, buffer->range_length());
2617d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data = new MetaData(*buffer->meta_data().get());
2618d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer->release();
2619d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer = NULL;
2620d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
26219aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (mIsAvc || mIsHevc) StripStartcode(copy);
2622e136c3bb38e88315bf8797a464ebf2c788296b22James Dong
2623b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        size_t sampleSize = copy->range_length();
26249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (mIsAvc || mIsHevc) {
2625b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            if (mOwner->useNalLengthFour()) {
2626b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 4;
2627b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            } else {
2628b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 2;
2629b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            }
2630b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        }
2631050b28a593350047845a45a14cc5026221ac1620James Dong
2632d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        // Max file size or duration handling
26331f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mMdatSizeBytes += sampleSize;
26341f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        updateTrackSizeEstimate();
26351f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
2636d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileSizeLimit()) {
2637fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            if (mOwner->switchFd() != OK) {
2638fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                ALOGW("Recorded file size exceeds limit %" PRId64 "bytes",
2639fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                        mOwner->mMaxFileSizeLimitBytes);
2640fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                mSource->stop();
2641fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                mOwner->notify(
2642fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                        MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
2643fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            } else {
2644fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                ALOGV("%s Current recorded file size exceeds limit %" PRId64 "bytes. Switching output",
2645fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                        getTrackType(), mOwner->mMaxFileSizeLimitBytes);
2646fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            }
2647d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            copy->release();
2648d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2649d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2650fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
2651d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileDurationLimit()) {
2652316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang            ALOGW("Recorded file duration exceeds limit %" PRId64 "microseconds",
2653316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang                    mOwner->mMaxFileDurationLimitUs);
2654d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
2655d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            copy->release();
2656d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            mSource->stop();
2657d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2658d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2659d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2660fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        if (mOwner->approachingFileSizeLimit()) {
2661fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mOwner->notifyApproachingLimit();
2662fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        }
2663050b28a593350047845a45a14cc5026221ac1620James Dong
2664d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        int32_t isSync = false;
2665d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
2666d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
2667d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
2668fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        // For video, skip the first several non-key frames until getting the first key frame.
2669fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        if (mIsVideo && !mGotStartKeyFrame && !isSync) {
2670fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            ALOGD("Video skip non-key frame");
2671fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            copy->release();
2672fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            continue;
2673fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        }
2674fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        if (mIsVideo && isSync) {
2675fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mGotStartKeyFrame = true;
2676fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        }
2677d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong////////////////////////////////////////////////////////////////////////////////
2678c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (mStszTableEntries->count() == 0) {
267970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mFirstSampleTimeRealUs = systemTime() / 1000;
2680f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimestampUs = timestampUs;
2681f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mOwner->setStartTimestampUs(mStartTimestampUs);
26828428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs = mStartTimestampUs;
26833c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        }
268448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
2685a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mResumed) {
26868428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
268711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) {
268811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
2689d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang                mSource->stop();
26909db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                mIsMalformed = true;
26919db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                break;
269211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
269311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
26948428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
269511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) {
269611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
2697d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang                mSource->stop();
26989db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                mIsMalformed = true;
26999db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                break;
270011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
270111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
27028428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs += pausedDurationUs - lastDurationUs;
2703a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mResumed = false;
2704a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2705a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2706a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        timestampUs -= previousPausedDurationUs;
270711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
270811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
2709d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            mSource->stop();
27109db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            mIsMalformed = true;
27119db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            break;
271211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        }
271311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
271425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        if (mIsVideo) {
2715965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            /*
2716965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Composition time: timestampUs
2717965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Decoding time: decodingTimeUs
2718000e18370baae60ffd9f25b509501dd8c26deabfJames Dong             * Composition time offset = composition time - decoding time
2719965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             */
2720965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            int64_t decodingTimeUs;
2721965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
2722965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            decodingTimeUs -= previousPausedDurationUs;
2723826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar
2724826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            // ensure non-negative, monotonic decoding time
2725826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            if (mLastDecodingTimeUs < 0) {
2726826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar                decodingTimeUs = std::max((int64_t)0, decodingTimeUs);
2727826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            } else {
2728826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar                // increase decoding time by at least 1 tick
2729826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar                decodingTimeUs = std::max(
2730826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar                        mLastDecodingTimeUs + divUp(1000000, mTimeScale), decodingTimeUs);
2731826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            }
2732826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar
2733826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            mLastDecodingTimeUs = decodingTimeUs;
2734000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            cttsOffsetTimeUs =
2735000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
273611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) {
273711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
2738d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang                mSource->stop();
27399db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                mIsMalformed = true;
27409db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                break;
274111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
274211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2743965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            timestampUs = decodingTimeUs;
2744a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGV("decoding time: %" PRId64 " and ctts offset time: %" PRId64,
2745000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                timestampUs, cttsOffsetTimeUs);
2746000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2747000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts box table if necessary
2748000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            currCttsOffsetTimeTicks =
2749000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL;
275011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) {
275111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
2752d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang                mSource->stop();
27539db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                mIsMalformed = true;
27549db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                break;
275511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
275611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2757c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 0) {
275843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // Force the first ctts table entry to have one single entry
275943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // so that we can do adjustment for the initial track start
276043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // time offset easily in writeCttsBox().
276143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
276243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                addOneCttsTableEntry(1, currCttsOffsetTimeTicks);
276343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                cttsSampleCount = 0;      // No sample in ctts box is pending
276443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            } else {
276543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) {
276643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
276743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
276843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    cttsSampleCount = 1;  // One sample in ctts box is pending
276943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                } else {
277043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    ++cttsSampleCount;
277143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                }
277243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            }
2773000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2774000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts time offset range
2775c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 0) {
2776000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2777000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2778000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            } else {
2779000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) {
2780000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2781000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) {
2782000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2783000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                }
2784000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            }
2785000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2786965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        }
2787872a481558350634a3fd5cb67939de288af00ecbJames Dong
2788de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        if (mOwner->isRealTimeRecording()) {
2789872a481558350634a3fd5cb67939de288af00ecbJames Dong            if (mIsAudio) {
2790872a481558350634a3fd5cb67939de288af00ecbJames Dong                updateDriftTime(meta_data);
2791e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
2792e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
2793872a481558350634a3fd5cb67939de288af00ecbJames Dong
279411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
279511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
2796d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            mSource->stop();
27979db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            mIsMalformed = true;
27989db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            break;
279911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        }
280011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2801a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("%s media time stamp: %" PRId64 " and previous paused duration %" PRId64,
280211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                trackName, timestampUs, previousPausedDurationUs);
2803c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong        if (timestampUs > mTrackDurationUs) {
2804c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong            mTrackDurationUs = timestampUs;
28053b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        }
28063b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber
28075a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // We need to use the time scale based ticks, rather than the
28085a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // timestamp itself to determine whether we have to use a new
28095a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // stts entry, since we may have rounding errors.
28105a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // The calculation is intended to reduce the accumulated
28115a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // rounding errors.
28125a217fba010e801c255503602bda4b86ac5a6ac9James Dong        currDurationTicks =
28135a217fba010e801c255503602bda4b86ac5a6ac9James Dong            ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
28145a217fba010e801c255503602bda4b86ac5a6ac9James Dong                (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
2815c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (currDurationTicks < 0ll) {
2816f85a83af8c6a98b46c394c32b90b09214a68f3e4Hangyu Kuang            ALOGE("do not support out of order frames (timestamp: %lld < last: %lld for %s track",
2817f85a83af8c6a98b46c394c32b90b09214a68f3e4Hangyu Kuang                    (long long)timestampUs, (long long)lastTimestampUs, trackName);
281811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
28190332fadec6e91c37fe39ab92b2c02922370bc853Hangyu Kuang            mSource->stop();
28209db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            mIsMalformed = true;
28219db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang            break;
28228c460498c028888c533ab442be12b6d4b669b965James Dong        }
28238c460498c028888c533ab442be12b6d4b669b965James Dong
282485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // if the duration is different for this sample, see if it is close enough to the previous
282585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // duration that we can fudge it and use the same value, to avoid filling the stts table
282685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // with lots of near-identical entries.
282785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // "close enough" here means that the current duration needs to be adjusted by less
282885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // than 0.1 milliseconds
282985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) {
283085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL
283185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                    + (mTimeScale / 2)) / mTimeScale;
283285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            if (deltaUs > -100 && deltaUs < 100) {
283385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                // use previous ticks, and adjust timestamp as if it was actually that number
283485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                // of ticks
283585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                currDurationTicks = lastDurationTicks;
283685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                timestampUs += deltaUs;
283785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            }
283885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        }
2839c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStszTableEntries->add(htonl(sampleSize));
2840c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (mStszTableEntries->count() > 2) {
2841c059860c73678a202bfa33062723e8f82fb779d9James Dong
2842a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // Force the first sample to have its own stts entry so that
2843a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // we can adjust its value later to maintain the A/V sync.
2844c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) {
284579761ab096f57c3027fad9556c2bc436672d614eJames Dong                addOneSttsTableEntry(sampleCount, lastDurationTicks);
2846be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                sampleCount = 1;
2847be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
2848be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                ++sampleCount;
2849be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
2850965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2851be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
2852be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        if (mSamplesHaveSameSize) {
2853c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) {
2854be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSamplesHaveSameSize = false;
2855be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
28568644c14618d30d9e57a69df40ed939986ebf02c4James Dong            previousSampleSize = sampleSize;
2857be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
2858a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("%s timestampUs/lastTimestampUs: %" PRId64 "/%" PRId64,
285911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                trackName, timestampUs, lastTimestampUs);
28608644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastDurationUs = timestampUs - lastTimestampUs;
2861c059860c73678a202bfa33062723e8f82fb779d9James Dong        lastDurationTicks = currDurationTicks;
28628644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastTimestampUs = timestampUs;
286320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2864d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        if (isSync != 0) {
2865c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            addOneStssTableEntry(mStszTableEntries->count());
2866d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        }
2867d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
286893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (mTrackingProgressStatus) {
286993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            if (mPreviousTrackTimeUs <= 0) {
287093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong                mPreviousTrackTimeUs = mStartTimestampUs;
287193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            }
2872faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong            trackProgressStatus(timestampUs);
287393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
287443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        if (!hasMultipleTracks) {
287580f78b773f92048944a850efb7b60629643370cdPraveen Chavan            off64_t offset = (mIsAvc || mIsHevc) ? mOwner->addMultipleLengthPrefixedSamples_l(copy)
287658ae9c530247668f8af36e30d228c716c226b3d4James Dong                                 : mOwner->addSample_l(copy);
2877c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2878c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t count = (mOwner->use32BitFileOffset()
2879c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        ? mStcoTableEntries->count()
2880c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        : mCo64TableEntries->count());
2881c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2882c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (count == 0) {
28831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                addChunkOffset(offset);
288458ae9c530247668f8af36e30d228c716c226b3d4James Dong            }
288558ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy->release();
288658ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy = NULL;
288758ae9c530247668f8af36e30d228c716c226b3d4James Dong            continue;
288858ae9c530247668f8af36e30d228c716c226b3d4James Dong        }
288913aec890216948b0c364f8f92792129d0335f506James Dong
289013aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.push_back(copy);
289113aec890216948b0c364f8f92792129d0335f506James Dong        if (interleaveDurationUs == 0) {
28921f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStscTableEntry(++nChunks, 1);
28931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            bufferChunk(timestampUs);
289413aec890216948b0c364f8f92792129d0335f506James Dong        } else {
289513aec890216948b0c364f8f92792129d0335f506James Dong            if (chunkTimestampUs == 0) {
289613aec890216948b0c364f8f92792129d0335f506James Dong                chunkTimestampUs = timestampUs;
289713aec890216948b0c364f8f92792129d0335f506James Dong            } else {
289843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                int64_t chunkDurationUs = timestampUs - chunkTimestampUs;
289943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                if (chunkDurationUs > interleaveDurationUs) {
290043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    if (chunkDurationUs > mMaxChunkDurationUs) {
290143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                        mMaxChunkDurationUs = chunkDurationUs;
290243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    }
290313aec890216948b0c364f8f92792129d0335f506James Dong                    ++nChunks;
290413aec890216948b0c364f8f92792129d0335f506James Dong                    if (nChunks == 1 ||  // First chunk
2905c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk != mChunkSamples.size()) {
2906c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk = mChunkSamples.size();
2907c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        addOneStscTableEntry(nChunks, lastSamplesPerChunk);
290813aec890216948b0c364f8f92792129d0335f506James Dong                    }
29091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                    bufferChunk(timestampUs);
291013aec890216948b0c364f8f92792129d0335f506James Dong                    chunkTimestampUs = timestampUs;
291113aec890216948b0c364f8f92792129d0335f506James Dong                }
291213aec890216948b0c364f8f92792129d0335f506James Dong            }
291313aec890216948b0c364f8f92792129d0335f506James Dong        }
291413aec890216948b0c364f8f92792129d0335f506James Dong
291520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
291625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
291745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (isTrackMalFormed()) {
2918690f546b0ee548dbfe997df36418e5302ec2d786James Dong        err = ERROR_MALFORMED;
2919f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    }
292045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
2921bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    mOwner->trackProgressStatus(mTrackId, -1, err);
2922be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
292313aec890216948b0c364f8f92792129d0335f506James Dong    // Last chunk
292443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (!hasMultipleTracks) {
2925c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        addOneStscTableEntry(1, mStszTableEntries->count());
292658ae9c530247668f8af36e30d228c716c226b3d4James Dong    } else if (!mChunkSamples.empty()) {
29271f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        addOneStscTableEntry(++nChunks, mChunkSamples.size());
29281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        bufferChunk(timestampUs);
292913aec890216948b0c364f8f92792129d0335f506James Dong    }
293013aec890216948b0c364f8f92792129d0335f506James Dong
2931be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // We don't really know how long the last frame lasts, since
2932be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // there is no frame time after it, just repeat the previous
2933be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // frame's duration.
2934c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() == 1) {
29358f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        lastDurationUs = 0;  // A single sample's duration
293679761ab096f57c3027fad9556c2bc436672d614eJames Dong        lastDurationTicks = 0;
2937be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    } else {
2938be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        ++sampleCount;  // Count for the last sample
2939be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    }
2940a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2941c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() <= 2) {
294279761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(1, lastDurationTicks);
2943a472613aec322e25891abf5c77bf3f7e3c244920James Dong        if (sampleCount - 1 > 0) {
294479761ab096f57c3027fad9556c2bc436672d614eJames Dong            addOneSttsTableEntry(sampleCount - 1, lastDurationTicks);
2945a472613aec322e25891abf5c77bf3f7e3c244920James Dong        }
2946a472613aec322e25891abf5c77bf3f7e3c244920James Dong    } else {
294779761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(sampleCount, lastDurationTicks);
2948a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
2949a472613aec322e25891abf5c77bf3f7e3c244920James Dong
295043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // The last ctts box may not have been written yet, and this
295143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // is to make sure that we write out the last ctts box.
295243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) {
295343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        if (cttsSampleCount > 0) {
295443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
295543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        }
295643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    }
295743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong
2958c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs += lastDurationUs;
295925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
296043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
296143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    sendTrackSummary(hasMultipleTracks);
296243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
2963df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
296411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            count, nZeroLengthFrames, mStszTableEntries->count(), trackName);
2965872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (mIsAudio) {
2966a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Audio track drift time: %" PRId64 " us", mOwner->getDriftTimeUs());
2967872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2968365a963142093a1cd8efdcea76b5f65096a5b115James Dong
296937187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err == ERROR_END_OF_STREAM) {
297037187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
297137187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
297237187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
2973365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
2974365a963142093a1cd8efdcea76b5f65096a5b115James Dong
297545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const {
29769db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang    if (mIsMalformed) {
29779db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang        return true;
29789db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang    }
29799db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang
2980c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() == 0) {                      // no samples written
298129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("The number of recorded samples is 0");
298245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
298345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
298445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
298525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (mIsVideo && mStssTableEntries->count() == 0) {  // no sync frames for video
298629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("There are no sync frames for video track");
298745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
298845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
298945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
299045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (OK != checkCodecSpecificData()) {         // no codec specific data
299145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
299245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
299345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
299445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    return false;
299545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong}
299645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
299743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) {
299807ec01904613a0bac32caaa8444b4690998faed7James Dong
299907ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send track summary only if test mode is enabled.
300007ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
300107ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
300207ec01904613a0bac32caaa8444b4690998faed7James Dong    }
300307ec01904613a0bac32caaa8444b4690998faed7James Dong
300443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int trackNum = (mTrackId << 28);
300543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
300643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
300743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE,
300825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang                    mIsAudio ? 0: 1);
300943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
301043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
301143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS,
301243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mTrackDurationUs / 1000);
301343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
301443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
301543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES,
3016c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    mStszTableEntries->count());
301743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
301886b7f47aa7482424cf8fd248f1315311919be3b0James Dong    {
301986b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // The system delay time excluding the requested initial delay that
302086b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // is used to eliminate the recording sound.
302186b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
302286b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
302386b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
302486b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
302586b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t initialDelayUs =
302686b7f47aa7482424cf8fd248f1315311919be3b0James Dong            mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs;
302786b7f47aa7482424cf8fd248f1315311919be3b0James Dong
302886b7f47aa7482424cf8fd248f1315311919be3b0James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
302970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS,
303070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    (initialDelayUs) / 1000);
303186b7f47aa7482424cf8fd248f1315311919be3b0James Dong    }
303270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
303307ec01904613a0bac32caaa8444b4690998faed7James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
303407ec01904613a0bac32caaa8444b4690998faed7James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES,
303507ec01904613a0bac32caaa8444b4690998faed7James Dong                    mMdatSizeBytes / 1024);
303607ec01904613a0bac32caaa8444b4690998faed7James Dong
303743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (hasMultipleTracks) {
303843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
303943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS,
304043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mMaxChunkDurationUs / 1000);
304170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
304270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
304370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        if (mStartTimestampUs != moovStartTimeUs) {
304470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
304570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
304670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS,
304770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    startTimeOffsetUs / 1000);
304870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        }
304943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    }
305043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong}
305143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
3052faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
3053a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("trackProgressStatus: %" PRId64 " us", timeUs);
3054c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
3055215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    if (mTrackEveryTimeDurationUs > 0 &&
3056215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
3057a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("Fire time tracking progress status at %" PRId64 " us", timeUs);
3058bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err);
305993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        mPreviousTrackTimeUs = timeUs;
306093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
306193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
306293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
3063faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus(
3064bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        size_t trackId, int64_t timeUs, status_t err) {
3065faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    Mutex::Autolock lock(mLock);
3066bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t trackNum = (trackId << 28);
3067faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
3068faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Error notification
3069faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Do not consider ERROR_END_OF_STREAM an error
3070faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (err != OK && err != ERROR_END_OF_STREAM) {
3071bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
3072bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL,
3073faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
3074faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
3075faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
3076faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
3077faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (timeUs == -1) {
3078faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send completion notification
3079bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
3080bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS,
3081faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
3082faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    } else {
3083faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send progress status
3084bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
3085bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME,
3086faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               timeUs / 1000);
3087faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
3088faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong}
3089faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
3090d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) {
3091a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("setDriftTimeUs: %" PRId64 " us", driftTimeUs);
3092e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
3093d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    mDriftTimeUs = driftTimeUs;
3094e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
3095e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
3096e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() {
3097a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("getDriftTimeUs: %" PRId64 " us", mDriftTimeUs);
3098e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
3099e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    return mDriftTimeUs;
3100e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
3101e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
3102de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghuibool MPEG4Writer::isRealTimeRecording() const {
3103de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    return mIsRealTimeRecording;
3104de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui}
3105de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
3106b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() {
3107b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    return mUse4ByteNalLength;
3108b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong}
3109b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
31101c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
31113856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk");
31121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
31131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Chunk chunk(this, timestampUs, mChunkSamples);
31141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mOwner->bufferChunk(chunk);
311513aec890216948b0c364f8f92792129d0335f506James Dong    mChunkSamples.clear();
311620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
311720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31183b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
3119c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    return mTrackDurationUs;
312020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
312120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3122d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
3123d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return mEstimatedTrackSizeBytes;
3124d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
3125d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
3126690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const {
3127690f546b0ee548dbfe997df36418e5302ec2d786James Dong    const char *mime;
3128690f546b0ee548dbfe997df36418e5302ec2d786James Dong    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
3129690f546b0ee548dbfe997df36418e5302ec2d786James Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
3130690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
31319aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime) ||
31329aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        !strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
3133690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (!mCodecSpecificData ||
3134690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize <= 0) {
313529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Missing codec specific data");
3136690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
3137690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
3138690f546b0ee548dbfe997df36418e5302ec2d786James Dong    } else {
3139690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (mCodecSpecificData ||
3140690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize > 0) {
314129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Unexepected codec specific data found");
3142690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
3143690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
3144690f546b0ee548dbfe997df36418e5302ec2d786James Dong    }
3145690f546b0ee548dbfe997df36418e5302ec2d786James Dong    return OK;
3146690f546b0ee548dbfe997df36418e5302ec2d786James Dong}
3147690f546b0ee548dbfe997df36418e5302ec2d786James Dong
314825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangconst char *MPEG4Writer::Track::getTrackType() const {
314925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    return mIsAudio ? "Audio" : (mIsVideo ? "Video" : "Metadata");
315025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang}
31518f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
315225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) {
3153efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
3154b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("trak");
3155b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeTkhdBox(now);
3156b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("mdia");
3157b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeMdhdBox(now);
3158b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeHdlrBox();
3159b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->beginBox("minf");
3160b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                if (mIsAudio) {
3161b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeSmhdBox();
316225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang                } else if (mIsVideo) {
3163b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeVmhdBox();
316425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang                } else {
316525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang                    writeNmhdBox();
3166b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                }
3167b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeDinfBox();
3168b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeStblBox(use32BitOffset);
3169b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->endBox();  // minf
3170b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->endBox();  // mdia
3171b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // trak
3172b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3173b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3174b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) {
3175b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stbl");
3176b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsd");
3177b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);               // version=0, flags=0
3178b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);               // entry count
3179b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
3180b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAudioFourCCBox();
318125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else if (mIsVideo) {
3182b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeVideoFourCCBox();
318325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else {
318425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        writeMetadataFourCCBox();
3185b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3186b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsd
3187b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeSttsBox();
318825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (mIsVideo) {
318925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        writeCttsBox();
3190b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeStssBox();
3191b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3192b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStszBox();
3193b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStscBox();
3194b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStcoBox(use32BitOffset);
3195b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stbl
3196b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3197b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
319825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeMetadataFourCCBox() {
319925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    const char *mime;
320025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    bool success = mMeta->findCString(kKeyMIMEType, &mime);
320125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    CHECK(success);
320225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    const char *fourcc = getFourCCForMime(mime);
320325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (fourcc == NULL) {
320425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        ALOGE("Unknown mime type '%s'.", mime);
320525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        TRESPASS();
320625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    }
320725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->beginBox(fourcc);    // TextMetaDataSampleEntry
320825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->writeCString(mime);  // metadata mime_format
320925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->endBox(); // mett
321025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang}
321125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang
3212b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() {
3213b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
3214b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
3215b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
32168b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    const char *fourcc = getFourCCForMime(mime);
32178b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (fourcc == NULL) {
321829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
321925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        TRESPASS();
3220b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3221b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
32228b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    mOwner->beginBox(fourcc);        // video format
3223b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3224b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3225b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // data ref index
3226b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
3227b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3228b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
3229b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
3230b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
3231b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3232b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t width, height;
3233b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeyWidth, &width);
3234b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = success && mMeta->findInt32(kKeyHeight, &height);
3235b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
3236b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3237b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(width);
3238b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(height);
3239b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // horiz resolution
3240b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // vert resolution
3241b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3242b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // frame count
3243c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo    mOwner->writeInt8(0);            // compressor string length
3244c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo    mOwner->write("                               ", 31);
3245b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x18);        // depth
3246b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(-1);          // predefined
3247b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3248b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
3249b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4vEsdsBox();
3250b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
3251b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeD263Box();
3252b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
3253b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAvccBox();
32549aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
32559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        writeHvccBox();
3256b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3257b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3258b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writePaspBox();
325958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    writeColrBox();
3260b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // mp4v, s263 or avc1
3261b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3262b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
326358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnarvoid MPEG4Writer::Track::writeColrBox() {
326458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    ColorAspects aspects;
326558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    memset(&aspects, 0, sizeof(aspects));
326658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    // TRICKY: using | instead of || because we want to execute all findInt32-s
326758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    if (mMeta->findInt32(kKeyColorPrimaries, (int32_t*)&aspects.mPrimaries)
326858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyTransferFunction, (int32_t*)&aspects.mTransfer)
326958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyColorMatrix, (int32_t*)&aspects.mMatrixCoeffs)
327058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyColorRange, (int32_t*)&aspects.mRange)) {
327158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        int32_t primaries, transfer, coeffs;
327258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        bool fullRange;
327358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        ColorUtils::convertCodecColorAspectsToIsoAspects(
327458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar                aspects, &primaries, &transfer, &coeffs, &fullRange);
327558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->beginBox("colr");
327658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeFourcc("nclx");
327758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(primaries);
327858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(transfer);
327958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(coeffs);
3280fffb0c8fbe16ac948619b85e1eea9e65a9daa0c9Pirama Arumuga Nainar        mOwner->writeInt8(int8_t(fullRange ? 0x80 : 0x0));
328158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->endBox(); // colr
328258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    }
328358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar}
328458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
3285b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() {
3286b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
3287b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
3288b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
32898b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    const char *fourcc = getFourCCForMime(mime);
32908b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (fourcc == NULL) {
329129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
329225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        TRESPASS();
3293b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3294b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3295b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(fourcc);        // audio format
3296b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3297b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3298b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x1);         // data ref index
3299b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3300b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3301b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t nChannels;
3302b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
3303b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(nChannels);   // channel count
3304b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(16);          // sample size
3305b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
3306b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3307b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3308b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t samplerate;
3309b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeySampleRate, &samplerate);
3310b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
3311b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(samplerate << 16);
3312b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
3313b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4aEsdsBox();
3314b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
3315b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong               !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
3316b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeDamrBox();
3317b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3318b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3319b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3320b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3321b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() {
3322b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
3323b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
332443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mCodecSpecificDataSize, 0);
3325b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3326b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Make sure all sizes encode to a single byte.
332743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_LT(mCodecSpecificDataSize + 23, 128);
3328b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3329b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);     // version=0, flags=0
3330b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);   // ES_DescrTag
3331b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
3332b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);// ES_ID
3333b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x00);
3334b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3335b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
3336b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
3337b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
3338b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x15);   // streamType AudioStream
3339b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3340b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x03);  // XXX
334146f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt8(0x00);   // buffer size 24-bit (0x300)
334246f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar
334396bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t avgBitrate = 0;
334446f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyBitRate, &avgBitrate);
334596bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t maxBitrate = 0;
334646f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate);
334746f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(maxBitrate);
334846f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(avgBitrate);
3349b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3350b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
3351b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
3352b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3353b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3354b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
3355b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
3356b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
3357b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
3358b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3359b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
3360b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3361b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
3362b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3363b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3364b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() {
3365b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
336643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mCodecSpecificDataSize, 0);
3367bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan
3368bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan    // Make sure all sizes encode to a single byte.
3369bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan    CHECK_LT(23 + mCodecSpecificDataSize, 128);
3370bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan
3371b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
3372b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3373b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);    // version=0, flags=0
3374b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3375b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);  // ES_DescrTag
3376b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
3377b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);  // ES_ID
3378b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x1f);
3379b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3380b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
3381b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
3382b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
3383b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x11);  // streamType VisualStream
3384b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3385b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData[] = {
338646f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar        0x01, 0x77, 0x00, // buffer size 96000 bytes
3387b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3388b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData, sizeof(kData));
3389b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
339096bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t avgBitrate = 0;
339146f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyBitRate, &avgBitrate);
339296bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t maxBitrate = 0;
339346f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate);
339446f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(maxBitrate);
339546f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(avgBitrate);
339646f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar
3397b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
3398b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3399b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
3400b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3401b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3402b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
3403b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
3404b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
3405b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
3406b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3407b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
3408b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3409b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
3410b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3411b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3412efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeTkhdBox(uint32_t now) {
3413b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("tkhd");
3414b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Flags = 7 to indicate that the track is enabled, and
3415b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // part of the presentation
3416b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x07);          // version=0, flags=7
3417b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
3418b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
3419219f195159f93d627af2b243732e3f9020511a46James Dong    mOwner->writeInt32(mTrackId);      // track id starts with 1
3420b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
34218f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t trakDurationUs = getDurationUs();
3422b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mvhdTimeScale = mOwner->getTimeScale();
3423b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t tkhdDuration =
3424b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
3425b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
3426b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3427b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3428b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // layer
3429b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // alternate group
3430b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
3431b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // reserved
3432b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3433b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCompositionMatrix(mRotation);       // matrix
343420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
343525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (!mIsVideo) {
3436b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
3437b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
3438b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
3439b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        int32_t width, height;
3440b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        bool success = mMeta->findInt32(kKeyWidth, &width);
3441b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        success = success && mMeta->findInt32(kKeyHeight, &height);
3442b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(success);
3443b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3444b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
3445b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
3446b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3447b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // tkhd
3448b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3449b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3450b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() {
3451b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("vmhd");
3452b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x01);        // version=0, flags=1
3453b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // graphics mode
3454b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // opcolor
3455b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
3456b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
3457b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3458b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3459b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3460b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() {
3461b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("smhd");
3462b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // version=0, flags=0
3463b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // balance
3464b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3465b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3466b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3467b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
346825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeNmhdBox() {
346925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->beginBox("nmhd");
347025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->writeInt32(0);           // version=0, flags=0
347125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->endBox();
347225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang}
347325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang
3474b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() {
3475b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("hdlr");
3476b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
3477b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // component type: should be mhlr
347825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->writeFourcc(mIsAudio ? "soun" : (mIsVideo ? "vide" : "meta"));  // component subtype
3479b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3480b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3481b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3482b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Removing "r" for the name string just makes the string 4 byte aligned
348325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->writeCString(mIsAudio ? "SoundHandle": (mIsVideo ? "VideoHandle" : "MetadHandle"));
3484b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3485b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3486b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3487efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeMdhdBox(uint32_t now) {
3488b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t trakDurationUs = getDurationUs();
3489b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("mdhd");
3490b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
3491b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
3492b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
3493b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mTimeScale);    // media timescale
3494b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
3495b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mdhdDuration);  // use media timescale
3496b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Language follows the three letter standard ISO-639-2/T
3497b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 'e', 'n', 'g' for "English", for instance.
3498b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Each character is packed as the difference between its ASCII value and 0x60.
3499b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // For "English", these are 00101, 01110, 00111.
3500b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // XXX: Where is the padding bit located: 0x15C7?
3501decc50efede28c5d73137c30d1a95d72dd405555David Yeh    const char *lang = NULL;
3502decc50efede28c5d73137c30d1a95d72dd405555David Yeh    int16_t langCode = 0;
3503decc50efede28c5d73137c30d1a95d72dd405555David Yeh    if (mMeta->findCString(kKeyMediaLanguage, &lang) && lang && strnlen(lang, 3) > 2) {
3504decc50efede28c5d73137c30d1a95d72dd405555David Yeh        langCode = ((lang[0] & 0x1f) << 10) | ((lang[1] & 0x1f) << 5) | (lang[2] & 0x1f);
3505decc50efede28c5d73137c30d1a95d72dd405555David Yeh    }
3506decc50efede28c5d73137c30d1a95d72dd405555David Yeh    mOwner->writeInt16(langCode);      // language code
3507b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // predefined
3508b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3509b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3510b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3511b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() {
3512b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 3gpp2 Spec AMRSampleEntry fields
3513b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("damr");
3514b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString("   ");  // vendor: 4 bytes
3515b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // decoder version
3516b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x83FF);   // mode set: all enabled
3517b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // mode change period
3518b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(1);         // frames per sample
3519b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3520b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3521b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3522b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() {
3523b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // The table index here refers to the sample description index
3524b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // in the sample table entries.
3525b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("url ");
3526b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
3527b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // url
3528b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3529b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3530b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() {
3531b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dref");
3532b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3533b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // entry count (either url or urn)
3534b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeUrlBox();
3535b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dref
3536b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3537b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3538b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() {
3539b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dinf");
3540b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeDrefBox();
3541b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dinf
3542b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3543b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3544b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() {
3545b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
354643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(mCodecSpecificDataSize, 5);
3547b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3548b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Patch avcc's lengthSize field to match the number
3549b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // of bytes we use to indicate the size of a nal unit.
3550b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
3551b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
3552b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("avcC");
3553b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3554b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // avcC
3555b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3556b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
35579aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
35589aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimvoid MPEG4Writer::Track::writeHvccBox() {
35599aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    CHECK(mCodecSpecificData);
35609aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    CHECK_GE(mCodecSpecificDataSize, 5);
35619aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
35629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Patch avcc's lengthSize field to match the number
35639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // of bytes we use to indicate the size of a nal unit.
35649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
35659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ptr[21] = (ptr[21] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
35669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->beginBox("hvcC");
35679aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
35689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->endBox();  // hvcC
35699aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
35709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
3571b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() {
3572b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("d263");
3573b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // vendor
3574b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // decoder version
3575b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(10);  // level: 10
3576b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // profile: 0
3577b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // d263
3578b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3579b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3580b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square
3581b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() {
3582b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("pasp");
3583b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // hspacing
3584b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // vspacing
3585b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // pasp
3586b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3587b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3588000e18370baae60ffd9f25b509501dd8c26deabfJames Dongint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const {
3589a472613aec322e25891abf5c77bf3f7e3c244920James Dong    int64_t trackStartTimeOffsetUs = 0;
3590b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
3591b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mStartTimestampUs != moovStartTimeUs) {
359243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_GT(mStartTimestampUs, moovStartTimeUs);
3593b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
3594b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3595000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    return (trackStartTimeOffsetUs *  mTimeScale + 500000LL) / 1000000LL;
3596000e18370baae60ffd9f25b509501dd8c26deabfJames Dong}
3597000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
3598000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() {
3599000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->beginBox("stts");
3600000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3601c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t duration;
3602c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    CHECK(mSttsTableEntries->get(duration, 1));
3603c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    duration = htonl(duration);  // Back to host byte order
3604c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1);
3605c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->write(mOwner);
3606b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stts
3607b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
360820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3609965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() {
3610000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    // There is no B frame at all
3611000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) {
3612000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        return;
3613000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    }
3614000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
3615965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    // Do not write ctts box when there is no need to have it.
3616c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mCttsTableEntries->count() == 0) {
3617965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
3618965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
3619965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3620a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("ctts box has %d entries with range [%" PRId64 ", %" PRId64 "]",
3621c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs);
3622965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3623965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->beginBox("ctts");
3624000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3625c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    uint32_t delta = mMinCttsOffsetTimeUs - getStartTimeOffsetScaledTime();
3626c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    mCttsTableEntries->adjustEntries([delta](size_t /* ix */, uint32_t (&value)[2]) {
3627c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        // entries are <count, ctts> pairs; adjust only ctts
3628c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        uint32_t duration = htonl(value[1]); // back to host byte order
3629c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        value[1] = htonl(duration - delta);
3630c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    });
3631c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->write(mOwner);
3632965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->endBox();  // ctts
3633965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
3634965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3635b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() {
3636b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stss");
3637b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3638c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->write(mOwner);
3639b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stss
3640b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
364125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
3642b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() {
3643b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsz");
3644b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3645c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mOwner->writeInt32(0);
3646c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries->write(mOwner);
3647b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsz
3648b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
364920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3650b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() {
3651b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsc");
3652b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3653c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries->write(mOwner);
3654b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsc
3655b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
365620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3657b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) {
3658b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(use32BitOffset? "stco": "co64");
3659b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3660c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (use32BitOffset) {
3661c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->write(mOwner);
3662c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
3663c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->write(mOwner);
3664b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3665b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stco or co64
366620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
366720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
366807b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() {
366907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("udta");
367007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeGeoDataBox();
367107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
367207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
367307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
3674e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeHdlr() {
3675e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("hdlr");
3676e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Version, Flags
3677e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Predefined
3678e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeFourcc("mdta");
3679e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[0]
3680e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[1]
3681e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[2]
3682e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt8(0);  // Name (empty)
3683e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3684e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3685e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3686e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeKeys() {
3687e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3688e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3689e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("keys");
3690e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0);     // Version, Flags
3691e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(count); // Entry_count
3692e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    for (size_t i = 0; i < count; i++) {
3693e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        AMessage::Type type;
3694e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        const char *key = mMetaKeys->getEntryNameAt(i, &type);
3695e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        size_t n = strlen(key);
3696e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writeInt32(n + 8);
3697e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writeFourcc("mdta");
3698e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        write(key, n); // write without the \0
3699e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3700e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3701e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3702e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3703e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeIlst() {
3704e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3705e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3706e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("ilst");
3707e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    for (size_t i = 0; i < count; i++) {
3708e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        beginBox(i + 1); // key id (1-based)
3709e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        beginBox("data");
3710e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        AMessage::Type type;
3711e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        const char *key = mMetaKeys->getEntryNameAt(i, &type);
3712e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        switch (type) {
37137c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            case AMessage::kTypeString:
37147c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            {
37157c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                AString val;
37167c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                CHECK(mMetaKeys->findString(key, &val));
37177c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(1); // type = UTF8
37187c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0); // default country/language
37197c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                write(val.c_str(), strlen(val.c_str())); // write without \0
37207c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                break;
37217c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            }
37227c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
3723e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            case AMessage::kTypeFloat:
3724e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3725e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                float val;
3726e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                CHECK(mMetaKeys->findFloat(key, &val));
37277c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(23); // type = float32
37287c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3729e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(*reinterpret_cast<int32_t *>(&val));
3730e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3731e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3732e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3733e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            case AMessage::kTypeInt32:
3734e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3735e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                int32_t val;
3736e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                CHECK(mMetaKeys->findInt32(key, &val));
37377c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(67); // type = signed int32
37387c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3739e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(val);
3740e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3741e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3742e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3743e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            default:
3744e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3745e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                ALOGW("Unsupported key type, writing 0 instead");
37467c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(77); // type = unsigned int32
37477c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3748e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(0);
3749e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3750e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3751e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        }
3752e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        endBox(); // data
3753e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        endBox(); // key id
3754e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3755e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox(); // ilst
3756e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3757e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3758e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeMetaBox() {
3759e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3760e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    if (count == 0) {
3761e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        return;
3762e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3763e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3764e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("meta");
3765e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeHdlr();
3766e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeKeys();
3767e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeIlst();
3768e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3769e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3770e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
377107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
377207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
377307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
377407b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() {
377507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("\xA9xyz");
377607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    /*
377707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * For historical reasons, any user data start
377807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * with "\0xA9", must be followed by its assoicated
377907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * language code.
3780432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x0012: text string length
3781432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x15c7: lang (locale) code: en
378207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     */
378307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt32(0x001215c7);
378407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLatitude(mLatitudex10000);
378507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLongitude(mLongitudex10000);
378607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt8(0x2F);
378707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
378807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
378907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
379020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
3791