MPEG4Writer.cpp revision decc50efede28c5d73137c30d1a95d72dd405555
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
3343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong#include <media/stagefright/foundation/ADebug.h>
34e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang#include <media/stagefright/foundation/AMessage.h>
35826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar#include <media/stagefright/foundation/AUtils.h>
3658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar#include <media/stagefright/foundation/ColorUtils.h>
3720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h>
3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h>
3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
4018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
4103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#include <media/stagefright/MediaErrors.h>
4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h>
4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h>
44d599cd4573b5a2d5914c5040e0565ef866749b77James Dong#include <media/mediarecorder.h>
4507ec01904613a0bac32caaa8444b4690998faed7James Dong#include <cutils/properties.h>
4620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber#include "include/ESDS.h"
489aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim#include "include/HevcUtils.h"
4980f78b773f92048944a850efb7b60629643370cdPraveen Chavan#include "include/avc_utils.h"
50dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn
51dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#ifndef __predict_false
52dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#define __predict_false(exp) __builtin_expect((exp) != 0, 0)
53dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#endif
54dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn
5511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih#define WARN_UNLESS(condition, message, ...) \
56dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn( (__predict_false(condition)) ? false : ({ \
5711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih    ALOGW("Condition %s failed "  message, #condition, ##__VA_ARGS__); \
5811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih    true; \
5911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih}))
6011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
6120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
6220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6377e8ae9967a078770416619e99ddb5b010def312James Dongstatic const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024;
641f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachadstatic const int64_t kMax32BitFileSize = 0x00ffffffffLL; // 2^32-1 : max FAT32
651f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad                                                         // filesystem file size
661f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad                                                         // used by most SD cards
673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypeSeqParamSet = 0x07;
683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypePicParamSet = 0x08;
6970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongstatic const int64_t kInitialDelayTimeUs     = 700000LL;
705b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong
717c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Version[]    = "com.android.version";
723b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnar#ifdef SHOW_MODEL_BUILD
733b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnarstatic const char kMetaKey_Model[]      = "com.android.model";
747c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Build[]      = "com.android.build";
753b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnar#endif
767c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_CaptureFps[] = "com.android.capture.fps";
774dbff11975e737482537e1636051690188f3fbc4Praveen Chavanstatic const char kMetaKey_TemporalLayerCount[] = "com.android.video.temporal_layers_count";
787c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatic const uint8_t kMandatoryHevcNalUnitTypes[3] = {
809aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeVps,
819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeSps,
829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypePps,
839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim};
849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatic const uint8_t kHevcNalUnitTypes[5] = {
859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeVps,
869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeSps,
879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypePps,
889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypePrefixSei,
899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeSuffixSei,
909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim};
917c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang/* uncomment to include model and build in meta */
927c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang//#define SHOW_MODEL_BUILD 1
937c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
9420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track {
9520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
96b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen    Track(MPEG4Writer *owner, const sp<IMediaSource> &source, size_t trackId);
978f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
9820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ~Track();
9920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t start(MetaData *params);
10137187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t stop();
10237187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t pause();
10325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool reachedEOS();
10420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1053b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    int64_t getDurationUs() const;
106d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t getEstimatedTrackSizeBytes() const;
107b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeTrackHeader(bool use32BitOffset = true);
1081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void bufferChunk(int64_t timestampUs);
1091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAvc() const { return mIsAvc; }
1109aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    bool isHevc() const { return mIsHevc; }
1111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAudio() const { return mIsAudio; }
1121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isMPEG4() const { return mIsMPEG4; }
113c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    void addChunkOffset(off64_t offset);
11470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int32_t getTrackId() const { return mTrackId; }
115dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    status_t dump(int fd, const Vector<String16>& args) const;
1168b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    static const char *getFourCCForMime(const char *mime);
11720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
119000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    enum {
120000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        kMaxCttsOffsetTimeUs = 1000000LL,  // 1 second
1218c460498c028888c533ab442be12b6d4b669b965James Dong        kSampleArraySize = 1000,
122000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    };
123000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
124c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    // A helper class to handle faster write box with table entries
125c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    template<class TYPE>
126c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    struct ListTableEntries {
127c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        ListTableEntries(uint32_t elementCapacity, uint32_t entryCapacity)
128c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            : mElementCapacity(elementCapacity),
129c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mEntryCapacity(entryCapacity),
130c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mTotalNumTableEntries(0),
131c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mNumValuesInCurrEntry(0),
132c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCurrTableEntriesElement(NULL) {
133c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_GT(mElementCapacity, 0);
134c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_GT(mEntryCapacity, 0);
1352177f21c1ae5bf5cb8c1113a1adbe1fd7db34206Wei Jia            // Ensure no integer overflow on allocation in add().
1362177f21c1ae5bf5cb8c1113a1adbe1fd7db34206Wei Jia            CHECK_LT(mEntryCapacity, UINT32_MAX / mElementCapacity);
137c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
138c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
139c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Free the allocated memory.
140c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        ~ListTableEntries() {
141c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (!mTableEntryList.empty()) {
142c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                typename List<TYPE *>::iterator it = mTableEntryList.begin();
143c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                delete[] (*it);
144c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.erase(it);
145c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
146c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
147c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
148c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Replace the value at the given position by the given value.
149c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // There must be an existing value at the given position.
150c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order
151c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
152c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void set(const TYPE& value, uint32_t pos) {
15325f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong            CHECK_LT(pos, mTotalNumTableEntries * mEntryCapacity);
154c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
155c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            typename List<TYPE *>::iterator it = mTableEntryList.begin();
156c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity));
157c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (it != mTableEntryList.end() && iterations > 0) {
158c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++it;
159c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                --iterations;
160c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
161c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK(it != mTableEntryList.end());
162c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_EQ(iterations, 0);
163c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
164c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            (*it)[(pos % (mElementCapacity * mEntryCapacity))] = value;
165c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
166c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Get the value at the given position by the given value.
168c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value the retrieved value at the position in network byte order.
169c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
170c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @return true if a value is found.
171c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        bool get(TYPE& value, uint32_t pos) const {
17225f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong            if (pos >= mTotalNumTableEntries * mEntryCapacity) {
173c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                return false;
174c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
176c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            typename List<TYPE *>::iterator it = mTableEntryList.begin();
177c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity));
178c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (it != mTableEntryList.end() && iterations > 0) {
179c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++it;
180c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                --iterations;
181c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
182c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK(it != mTableEntryList.end());
183c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_EQ(iterations, 0);
184c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            value = (*it)[(pos % (mElementCapacity * mEntryCapacity))];
186c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            return true;
187c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
188c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
189c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Store a single value.
190c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order.
191c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void add(const TYPE& value) {
192c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_LT(mNumValuesInCurrEntry, mElementCapacity);
193c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries % mElementCapacity;
194c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nValues  = mNumValuesInCurrEntry % mEntryCapacity;
195c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (nEntries == 0 && nValues == 0) {
196c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mCurrTableEntriesElement = new TYPE[mEntryCapacity * mElementCapacity];
197c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                CHECK(mCurrTableEntriesElement != NULL);
198c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.push_back(mCurrTableEntriesElement);
199c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
200c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
201c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t pos = nEntries * mEntryCapacity + nValues;
202c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCurrTableEntriesElement[pos] = value;
203c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
204c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            ++mNumValuesInCurrEntry;
205c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if ((mNumValuesInCurrEntry % mEntryCapacity) == 0) {
206c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++mTotalNumTableEntries;
207c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mNumValuesInCurrEntry = 0;
208c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
209c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
210c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
211c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Write out the table entries:
212c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 1. the number of entries goes first
213c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 2. followed by the values in the table enties in order
214c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg writer the writer to actual write to the storage
215c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void write(MPEG4Writer *writer) const {
216c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_EQ(mNumValuesInCurrEntry % mEntryCapacity, 0);
217c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries;
218c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            writer->writeInt32(nEntries);
219c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            for (typename List<TYPE *>::iterator it = mTableEntryList.begin();
220c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                it != mTableEntryList.end(); ++it) {
221c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                CHECK_GT(nEntries, 0);
222c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                if (nEntries >= mElementCapacity) {
223c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    writer->write(*it, sizeof(TYPE) * mEntryCapacity, mElementCapacity);
224c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    nEntries -= mElementCapacity;
225c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                } else {
226c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    writer->write(*it, sizeof(TYPE) * mEntryCapacity, nEntries);
227c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    break;
228c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                }
229c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
230c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
231c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
232c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Return the number of entries in the table.
233c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t count() const { return mTotalNumTableEntries; }
234c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
235c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    private:
236c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mElementCapacity;  // # entries in an element
237c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mEntryCapacity;    // # of values in each entry
238c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mTotalNumTableEntries;
239c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mNumValuesInCurrEntry;  // up to mEntryCapacity
240c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        TYPE             *mCurrTableEntriesElement;
241c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mutable List<TYPE *>     mTableEntryList;
242c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
243c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries);
244c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    };
245c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
246c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
247c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
24820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Writer *mOwner;
24920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mMeta;
250b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen    sp<IMediaSource> mSource;
25120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    volatile bool mDone;
252a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mPaused;
253a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mResumed;
254eaae38445a340c4857c1c5569475879a728e63b7James Dong    volatile bool mStarted;
2551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAvc;
2569aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    bool mIsHevc;
2571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAudio;
2581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsMPEG4;
259bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t mTrackId;
260c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    int64_t mTrackDurationUs;
26143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int64_t mMaxChunkDurationUs;
262826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar    int64_t mLastDecodingTimeUs;
263e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
264d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t mEstimatedTrackSizeBytes;
2651f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t mMdatSizeBytes;
2668f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mTimeScale;
26720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_t mThread;
26920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
270be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
27113aec890216948b0c364f8f92792129d0335f506James Dong    List<MediaBuffer *> mChunkSamples;
2721f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
273c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    bool                mSamplesHaveSameSize;
274c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStszTableEntries;
275be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
276c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStcoTableEntries;
277c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<off64_t> *mCo64TableEntries;
278c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStscTableEntries;
279c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStssTableEntries;
280c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mSttsTableEntries;
281c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mCttsTableEntries;
282965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
283000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMinCttsOffsetTimeUs;
284000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMaxCttsOffsetTimeUs;
285965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Sequence parameter set or picture parameter set
2873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    struct AVCParamSet {
2883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        AVCParamSet(uint16_t length, const uint8_t *data)
2893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            : mLength(length), mData(data) {}
2903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
2913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t mLength;
2923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *mData;
2933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    };
2943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mSeqParamSets;
2953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mPicParamSets;
2963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileIdc;
2973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileCompatible;
2983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mLevelIdc;
2993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
30020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *mCodecSpecificData;
30120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t mCodecSpecificDataSize;
302548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    bool mGotAllCodecSpecificData;
30393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    bool mTrackingProgressStatus;
30420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool mReachedEOS;
3063c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    int64_t mStartTimestampUs;
30770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mStartTimeRealUs;
30870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mFirstSampleTimeRealUs;
30993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mPreviousTrackTimeUs;
31093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mTrackEveryTimeDurationUs;
31125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
312872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Update the audio track's drift information.
313872a481558350634a3fd5cb67939de288af00ecbJames Dong    void updateDriftTime(const sp<MetaData>& meta);
314872a481558350634a3fd5cb67939de288af00ecbJames Dong
315000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int32_t getStartTimeOffsetScaledTime() const;
316000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
31720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static void *ThreadWrapper(void *me);
31837187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t threadEntry();
31920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *parseParamSet(
3213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen);
3223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
3239aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t copyCodecSpecificData(const uint8_t *data, size_t size, size_t minLength = 0);
3249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
325b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size);
326b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size);
327b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size);
328215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong
3299aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t makeHEVCCodecSpecificData(const uint8_t *data, size_t size);
3309aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t copyHEVCCodecSpecificData(const uint8_t *data, size_t size);
3319aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t parseHEVCCodecSpecificData(
3329aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            const uint8_t *data, size_t size, HevcParameterSets &paramSets);
3339aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
334215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    // Track authoring progress status
335faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    void trackProgressStatus(int64_t timeUs, status_t err = OK);
33693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    void initTrackingProgressStatus(MetaData *params);
33703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
33819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    void getCodecSpecificDataFromInputFormatIfPossible();
33919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
340c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Determine the track time scale
341c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If it is an audio track, try to use the sampling rate as
342c059860c73678a202bfa33062723e8f82fb779d9James Dong    // the time scale; however, if user chooses the overwrite
343c059860c73678a202bfa33062723e8f82fb779d9James Dong    // value, the user-supplied time scale will be used.
344c059860c73678a202bfa33062723e8f82fb779d9James Dong    void setTimeScale();
345c059860c73678a202bfa33062723e8f82fb779d9James Dong
346690f546b0ee548dbfe997df36418e5302ec2d786James Dong    // Simple validation on the codec specific data
347690f546b0ee548dbfe997df36418e5302ec2d786James Dong    status_t checkCodecSpecificData() const;
34813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t mRotation;
349690f546b0ee548dbfe997df36418e5302ec2d786James Dong
3501f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void updateTrackSizeEstimate();
3511f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStscTableEntry(size_t chunkId, size_t sampleId);
3521f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStssTableEntry(size_t sampleId);
35379761ab096f57c3027fad9556c2bc436672d614eJames Dong
35479761ab096f57c3027fad9556c2bc436672d614eJames Dong    // Duration is time scale based
35579761ab096f57c3027fad9556c2bc436672d614eJames Dong    void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
356965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
35745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
35845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    bool isTrackMalFormed() const;
35943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    void sendTrackSummary(bool hasMultipleTracks);
3601f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
361b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Write the boxes
362b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStcoBox(bool use32BitOffset);
363b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStscBox();
364b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStszBox();
365b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStssBox();
366b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSttsBox();
367965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void writeCttsBox();
368b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeD263Box();
369b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writePaspBox();
370b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAvccBox();
3719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    void writeHvccBox();
372b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeUrlBox();
373b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDrefBox();
374b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDinfBox();
375b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDamrBox();
376efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeMdhdBox(uint32_t now);
377b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSmhdBox();
378b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVmhdBox();
379b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeHdlrBox();
380efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeTkhdBox(uint32_t now);
38158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    void writeColrBox();
382b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4aEsdsBox();
383b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4vEsdsBox();
384b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAudioFourCCBox();
385b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVideoFourCCBox();
386b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStblBox(bool use32BitOffset);
387b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
38820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track(const Track &);
38920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track &operator=(const Track &);
39020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
39120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
39230ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd)
393674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    : mFd(dup(fd)),
394674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong      mInitCheck(mFd < 0? NO_INIT: OK),
395de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui      mIsRealTimeRecording(true),
396b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong      mUse4ByteNalLength(true),
3971acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
398a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong      mIsFileSizeLimitExplicitlyRequested(false),
399a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
400a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
401411ba422e3635d534928ffd81abf54f4f291c739James Dong      mWriterThreadStarted(false),
40230ab66297501757d745b9ae10da61adcd891f497Andreas Huber      mOffset(0),
40313aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
404e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mMoovBoxBuffer(NULL),
405e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mMoovBoxBufferOffset(0),
406e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mWriteMoovBoxToMemory(false),
407e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mFreeBoxOffset(0),
408e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mStreamableFile(false),
4097837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
4107c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang      mMoovExtraSize(0),
41107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mInterleaveDurationUs(1000000),
412e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mTimeScale(-1),
413e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mStartTimestampUs(-1ll),
41407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLatitudex10000(0),
41507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLongitudex10000(0),
41686b7f47aa7482424cf8fd248f1315311919be3b0James Dong      mAreGeoTagsAvailable(false),
417ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar      mStartTimeOffsetMs(-1),
418ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar      mMetaKeys(new AMessage()) {
4197c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    addDeviceMeta();
4202aa74dc097fe860abc84769abf2b6e0962718471Robert Shih
4212aa74dc097fe860abc84769abf2b6e0962718471Robert Shih    // Verify mFd is seekable
4222aa74dc097fe860abc84769abf2b6e0962718471Robert Shih    off64_t off = lseek64(mFd, 0, SEEK_SET);
4232aa74dc097fe860abc84769abf2b6e0962718471Robert Shih    if (off < 0) {
4242aa74dc097fe860abc84769abf2b6e0962718471Robert Shih        ALOGE("cannot seek mFd: %s (%d)", strerror(errno), errno);
4252aa74dc097fe860abc84769abf2b6e0962718471Robert Shih        release();
4262aa74dc097fe860abc84769abf2b6e0962718471Robert Shih    }
42730ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
42830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
42920111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
4308bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong    reset();
43120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4321f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    while (!mTracks.empty()) {
4331f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        List<Track *>::iterator it = mTracks.begin();
43420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
4351f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        (*it) = NULL;
4361f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mTracks.erase(it);
43720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
43820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
43920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
44020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
441dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump(
442dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) {
443dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
444dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
445dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
446dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "   MPEG4Writer %p\n", this);
447dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
448dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     mStarted: %s\n", mStarted? "true": "false");
449dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
450dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
451dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    for (List<Track *>::iterator it = mTracks.begin();
452dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong         it != mTracks.end(); ++it) {
453dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        (*it)->dump(fd, args);
454dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    }
455dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
456dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
457dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
458dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump(
45984333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        int fd, const Vector<String16>& /* args */) const {
460dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
461dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
462dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
463dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     %s track\n", mIsAudio? "Audio": "Video");
464dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
465dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "       reached EOS: %s\n",
466dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong            mReachedEOS? "true": "false");
467dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
468c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    snprintf(buffer, SIZE, "       frames encoded : %d\n", mStszTableEntries->count());
46913210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
470377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    snprintf(buffer, SIZE, "       duration encoded : %" PRId64 " us\n", mTrackDurationUs);
47113210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
472dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
473dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
474dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
475dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
4768b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan// static
4778b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavanconst char *MPEG4Writer::Track::getFourCCForMime(const char *mime) {
4788b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (mime == NULL) {
4798b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        return NULL;
4808b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    }
4818b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (!strncasecmp(mime, "audio/", 6)) {
4828b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
4838b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "samr";
4848b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
4858b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "sawb";
4868b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
4878b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "mp4a";
4888b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        }
4898b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    } else if (!strncasecmp(mime, "video/", 6)) {
4908b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
4918b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "mp4v";
4928b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
4938b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "s263";
4948b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
4958b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "avc1";
4969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
4979aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return "hvc1";
4988b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        }
4998b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    } else {
5008b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        ALOGE("Track (%s) other than video or audio is not supported", mime);
5018b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    }
5028b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    return NULL;
5038b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan}
5048b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan
505b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissenstatus_t MPEG4Writer::addSource(const sp<IMediaSource> &source) {
506bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    Mutex::Autolock l(mLock);
507bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    if (mStarted) {
50829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Attempt to add source AFTER recording is started");
509bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        return UNKNOWN_ERROR;
510bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    }
511acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
512acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // At most 2 tracks can be supported.
513acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    if (mTracks.size() >= 2) {
514a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGE("Too many tracks (%zu) to add", mTracks.size());
515acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return ERROR_UNSUPPORTED;
516acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
517acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
518acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    CHECK(source.get() != NULL);
519acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
520acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    const char *mime;
521acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    source->getFormat()->findCString(kKeyMIMEType, &mime);
522acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    bool isAudio = !strncasecmp(mime, "audio/", 6);
5238b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (Track::getFourCCForMime(mime) == NULL) {
5248b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        ALOGE("Unsupported mime '%s'", mime);
525acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return ERROR_UNSUPPORTED;
526acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
527acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
528acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // At this point, we know the track to be added is either
529acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // video or audio. Thus, we only need to check whether it
530acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // is an audio track or not (if it is not, then it must be
531acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // a video track).
532acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
533acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // No more than one video or one audio track is supported.
534acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    for (List<Track*>::iterator it = mTracks.begin();
535acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong         it != mTracks.end(); ++it) {
536acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        if ((*it)->isAudio() == isAudio) {
537acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong            ALOGE("%s track already exists", isAudio? "Audio": "Video");
538acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong            return ERROR_UNSUPPORTED;
539acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        }
540acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
541acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
542acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // This is the first track of either audio or video.
543acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // Go ahead to add the track.
544219f195159f93d627af2b243732e3f9020511a46James Dong    Track *track = new Track(this, source, 1 + mTracks.size());
54520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
5462dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
5472dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
54820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
54920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
55093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) {
551acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    if (mTracks.empty()) {
552acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        ALOGE("No source added");
553acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return INVALID_OPERATION;
554acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
555acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
556a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
557a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
55893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        status_t err = (*it)->start(params);
559a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
560a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (err != OK) {
561a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            for (List<Track *>::iterator it2 = mTracks.begin();
562a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                 it2 != it; ++it2) {
563a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                (*it2)->stop();
564a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            }
565a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
566a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            return err;
567a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
568a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
569a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
570a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
571a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
5727c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangvoid MPEG4Writer::addDeviceMeta() {
5737c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // add device info and estimate space in 'moov'
5747c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    char val[PROPERTY_VALUE_MAX];
5757c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    size_t n;
5767c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // meta size is estimated by adding up the following:
5777c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // - meta header structures, which occur only once (total 66 bytes)
5787c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // - size for each key, which consists of a fixed header (32 bytes),
5797c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    //   plus key length and data length.
5807c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += 66;
5817c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.build.version.release", val, NULL)
5827c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
5837c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Version, val, n + 1);
5847c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Version) + n + 32;
5857c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
5867c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#ifdef SHOW_MODEL_BUILD
5877c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.product.model", val, NULL)
5887c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
5897c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Model, val, n + 1);
5907c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Model) + n + 32;
5917c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
5927c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.build.display.id", val, NULL)
5937c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
5947c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Build, val, n + 1);
5957c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Build) + n + 32;
5967c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
5977c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#endif
5987c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang}
5997c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
6002dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
6012dec2b5be2056c6d9428897dc672185872d30d17James Dong    // This implementation is highly experimental/heurisitic.
6022dec2b5be2056c6d9428897dc672185872d30d17James Dong    //
6032dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Statistical analysis shows that metadata usually accounts
6042dec2b5be2056c6d9428897dc672185872d30d17James Dong    // for a small portion of the total file size, usually < 0.6%.
6052dec2b5be2056c6d9428897dc672185872d30d17James Dong
60678a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2,
6072dec2b5be2056c6d9428897dc672185872d30d17James Dong    // where 1MB is the common file size limit for MMS application.
60878a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MAX _MOOV_BOX_SIZE value is based on about 3
6092dec2b5be2056c6d9428897dc672185872d30d17James Dong    // minute video recording with a bit rate about 3 Mbps, because
6102dec2b5be2056c6d9428897dc672185872d30d17James Dong    // statistics also show that most of the video captured are going
6112dec2b5be2056c6d9428897dc672185872d30d17James Dong    // to be less than 3 minutes.
6122dec2b5be2056c6d9428897dc672185872d30d17James Dong
6132dec2b5be2056c6d9428897dc672185872d30d17James Dong    // If the estimation is wrong, we will pay the price of wasting
6142dec2b5be2056c6d9428897dc672185872d30d17James Dong    // some reserved space. This should not happen so often statistically.
6152dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int32_t factor = mUse32BitOffset? 1: 2;
61678a1a286f736888ae7af8860b2c424af0d978848James Dong    static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024;  // 3 KB
6172dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
6182dec2b5be2056c6d9428897dc672185872d30d17James Dong    int64_t size = MIN_MOOV_BOX_SIZE;
6192dec2b5be2056c6d9428897dc672185872d30d17James Dong
62078a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file size limit is set
621a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
62278a1a286f736888ae7af8860b2c424af0d978848James Dong        size = mMaxFileSizeLimitBytes * 6 / 1000;
62378a1a286f736888ae7af8860b2c424af0d978848James Dong    }
62478a1a286f736888ae7af8860b2c424af0d978848James Dong
62578a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file duration limit is set
62678a1a286f736888ae7af8860b2c424af0d978848James Dong    if (mMaxFileDurationLimitUs != 0) {
62778a1a286f736888ae7af8860b2c424af0d978848James Dong        if (bitRate > 0) {
62878a1a286f736888ae7af8860b2c424af0d978848James Dong            int64_t size2 =
6290ca31521644b9396829850f7400d23f9b107cc64Johan Redestig                ((mMaxFileDurationLimitUs / 1000) * bitRate * 6) / 8000000;
63078a1a286f736888ae7af8860b2c424af0d978848James Dong            if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
63178a1a286f736888ae7af8860b2c424af0d978848James Dong                // When both file size and duration limits are set,
63278a1a286f736888ae7af8860b2c424af0d978848James Dong                // we use the smaller limit of the two.
63378a1a286f736888ae7af8860b2c424af0d978848James Dong                if (size > size2) {
63478a1a286f736888ae7af8860b2c424af0d978848James Dong                    size = size2;
63578a1a286f736888ae7af8860b2c424af0d978848James Dong                }
63678a1a286f736888ae7af8860b2c424af0d978848James Dong            } else {
63778a1a286f736888ae7af8860b2c424af0d978848James Dong                // Only max file duration limit is set
63878a1a286f736888ae7af8860b2c424af0d978848James Dong                size = size2;
63978a1a286f736888ae7af8860b2c424af0d978848James Dong            }
6402dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
6412dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
64278a1a286f736888ae7af8860b2c424af0d978848James Dong
6432dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size < MIN_MOOV_BOX_SIZE) {
6442dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MIN_MOOV_BOX_SIZE;
6452dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
6462dec2b5be2056c6d9428897dc672185872d30d17James Dong
6472dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Any long duration recording will be probably end up with
6482dec2b5be2056c6d9428897dc672185872d30d17James Dong    // non-streamable mp4 file.
6492dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size > MAX_MOOV_BOX_SIZE) {
6502dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MAX_MOOV_BOX_SIZE;
6512dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
6522dec2b5be2056c6d9428897dc672185872d30d17James Dong
6537c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // Account for the extra stuff (Geo, meta keys, etc.)
6547c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    size += mMoovExtraSize;
6557c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
656a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGI("limits: %" PRId64 "/%" PRId64 " bytes/us, bit rate: %d bps and the"
657a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn         " estimated moov size %" PRId64 " bytes",
6582dec2b5be2056c6d9428897dc672185872d30d17James Dong         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
6592dec2b5be2056c6d9428897dc672185872d30d17James Dong    return factor * size;
6602dec2b5be2056c6d9428897dc672185872d30d17James Dong}
6612dec2b5be2056c6d9428897dc672185872d30d17James Dong
6622dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) {
663674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
66425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
66520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
66620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
667a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    /*
668a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * Check mMaxFileSizeLimitBytes at the beginning
669a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * since mMaxFileSizeLimitBytes may be implicitly
670a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * changed later for 32-bit file offset even if
671a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * user does not ask to set it explicitly.
672a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     */
673a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0) {
674a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong        mIsFileSizeLimitExplicitlyRequested = true;
675a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    }
676a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong
6772dec2b5be2056c6d9428897dc672185872d30d17James Dong    int32_t use64BitOffset;
6782dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (param &&
6792dec2b5be2056c6d9428897dc672185872d30d17James Dong        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
6802dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64BitOffset) {
6812dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
6822dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
6832dec2b5be2056c6d9428897dc672185872d30d17James Dong
6841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    if (mUse32BitOffset) {
6851f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // Implicit 32 bit file size limit
6861f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes == 0) {
6871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
6881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
6891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
6901f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // If file size is set to be larger than the 32 bit file
6911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // size limit, treat it as an error.
6921f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
693a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGW("32-bit file size limit (%" PRId64 " bytes) too big. "
694a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                 "It is changed to %" PRId64 " bytes",
695d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                mMaxFileSizeLimitBytes, kMax32BitFileSize);
696d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
6971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
6981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    }
6991f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
700b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    int32_t use2ByteNalLength;
701b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (param &&
702b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) &&
703b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        use2ByteNalLength) {
704b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mUse4ByteNalLength = false;
7052dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
7062dec2b5be2056c6d9428897dc672185872d30d17James Dong
707de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    int32_t isRealTimeRecording;
708de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (param && param->findInt32(kKeyRealTimeRecording, &isRealTimeRecording)) {
709de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        mIsRealTimeRecording = isRealTimeRecording;
710de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    }
711de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
712065d1aff96818df54456053f1574aec8a234d0deJames Dong    mStartTimestampUs = -1;
71393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
714a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mStarted) {
715a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused) {
716a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mPaused = false;
71793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return startTracks(param);
718a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
719a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
720a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
721a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
7228f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (!param ||
7238f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
7248f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mTimeScale = 1000;
7258f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
72643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
7273856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("movie time scale: %d", mTimeScale);
7288f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
72977e8ae9967a078770416619e99ddb5b010def312James Dong    /*
73077e8ae9967a078770416619e99ddb5b010def312James Dong     * When the requested file size limit is small, the priority
73177e8ae9967a078770416619e99ddb5b010def312James Dong     * is to meet the file size limit requirement, rather than
7327b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to make the file streamable. mStreamableFile does not tell
7337b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * whether the actual recorded file is streamable or not.
73477e8ae9967a078770416619e99ddb5b010def312James Dong     */
73577e8ae9967a078770416619e99ddb5b010def312James Dong    mStreamableFile =
73677e8ae9967a078770416619e99ddb5b010def312James Dong        (mMaxFileSizeLimitBytes != 0 &&
73777e8ae9967a078770416619e99ddb5b010def312James Dong         mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes);
73877e8ae9967a078770416619e99ddb5b010def312James Dong
7397b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    /*
7407b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mWriteMoovBoxToMemory is true if the amount of data in moov box is
7417b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * smaller than the reserved free space at the beginning of a file, AND
7427b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * when the content of moov box is constructed. Note that video/audio
7437b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * frame data is always written to the file but not in the memory.
7447b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7457b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * Before stop()/reset() is called, mWriteMoovBoxToMemory is always
7467b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * false. When reset() is called at the end of a recording session,
7477b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * Moov box needs to be constructed.
7487b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7497b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 1) Right before a moov box is constructed, mWriteMoovBoxToMemory
7507b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to set to mStreamableFile so that if
7517b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * the file is intended to be streamable, it is set to true;
7527b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * otherwise, it is set to false. When the value is set to false,
7537b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * all the content of the moov box is written immediately to
7547b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * the end of the file. When the value is set to true, all the
7557b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * content of the moov box is written to an in-memory cache,
7567b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mMoovBoxBuffer, util the following condition happens. Note
7577b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * that the size of the in-memory cache is the same as the
7587b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * reserved free space at the beginning of the file.
7597b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7607b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 2) While the data of the moov box is written to an in-memory
7617b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * cache, the data size is checked against the reserved space.
7627b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * If the data size surpasses the reserved space, subsequent moov
7637b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * data could no longer be hold in the in-memory cache. This also
7647b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * indicates that the reserved space was too small. At this point,
7657b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * _all_ moov data must be written to the end of the file.
7667b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mWriteMoovBoxToMemory must be set to false to direct the write
7677b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to the file.
7687b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7697b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 3) If the data size in moov box is smaller than the reserved
7707b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * space after moov box is completely constructed, the in-memory
7717b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * cache copy of the moov box is written to the reserved free
7727b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * space. Thus, immediately after the moov is completedly
7737b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * constructed, mWriteMoovBoxToMemory is always set to false.
7747b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     */
7757b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    mWriteMoovBoxToMemory = false;
7767837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = NULL;
7777837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
7787837c17063a4c50bc856ba59418516fdab731de7James Dong
779b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeFtypBox(param);
78020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7817837c17063a4c50bc856ba59418516fdab731de7James Dong    mFreeBoxOffset = mOffset;
78220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7837837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mEstimatedMoovBoxSize == 0) {
7842dec2b5be2056c6d9428897dc672185872d30d17James Dong        int32_t bitRate = -1;
7852dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (param) {
7862dec2b5be2056c6d9428897dc672185872d30d17James Dong            param->findInt32(kKeyBitRate, &bitRate);
7872dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
7882dec2b5be2056c6d9428897dc672185872d30d17James Dong        mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
7897837c17063a4c50bc856ba59418516fdab731de7James Dong    }
79043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(mEstimatedMoovBoxSize, 8);
79177e8ae9967a078770416619e99ddb5b010def312James Dong    if (mStreamableFile) {
79277e8ae9967a078770416619e99ddb5b010def312James Dong        // Reserve a 'free' box only for streamable file
79377e8ae9967a078770416619e99ddb5b010def312James Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
79477e8ae9967a078770416619e99ddb5b010def312James Dong        writeInt32(mEstimatedMoovBoxSize);
79577e8ae9967a078770416619e99ddb5b010def312James Dong        write("free", 4);
79677e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
79777e8ae9967a078770416619e99ddb5b010def312James Dong    } else {
79877e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mOffset;
79977e8ae9967a078770416619e99ddb5b010def312James Dong    }
8007837c17063a4c50bc856ba59418516fdab731de7James Dong
8017837c17063a4c50bc856ba59418516fdab731de7James Dong    mOffset = mMdatOffset;
802c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mMdatOffset, SEEK_SET);
8031acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
8041acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("????mdat", 8);
8051acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
8061acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("\x00\x00\x00\x01mdat????????", 16);
8071acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
8081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    status_t err = startWriterThread();
8101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (err != OK) {
8111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return err;
8121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    err = startTracks(param);
815a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (err != OK) {
816a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return err;
81720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
8181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
819a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = true;
82025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
82120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
82220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8231f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const {
8241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    return mUse32BitOffset;
8251f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
8261f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
82737187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() {
828674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
82937187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
830a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
831a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
83237187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
833a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
834a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
83537187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->pause();
83637187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (status != OK) {
83737187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
83837187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
839a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
84037187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
841a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
842a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
8431c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() {
844b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Stopping writer thread");
845411ba422e3635d534928ffd81abf54f4f291c739James Dong    if (!mWriterThreadStarted) {
846411ba422e3635d534928ffd81abf54f4f291c739James Dong        return;
847411ba422e3635d534928ffd81abf54f4f291c739James Dong    }
8481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
8501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
8511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mDone = true;
8531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkReadyCondition.signal();
8541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void *dummy;
8571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_join(mThread, &dummy);
858411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = false;
859b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Writer thread stopped");
8601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
8611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
86213f6284305e4b27395a23db7882d670bdb1bcae1James Dong/*
86313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix:
86413f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a  b  u |
86513f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c  d  v |
86613f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x  y  w |
86713f6284305e4b27395a23db7882d670bdb1bcae1James Dong *
86813f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following
86913f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w},
87013f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while
87113f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format.
87213f6284305e4b27395a23db7882d670bdb1bcae1James Dong */
87313f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) {
8743856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeCompositionMatrix");
87513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t a = 0x00010000;
87613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t b = 0;
87713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t c = 0;
87813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t d = 0x00010000;
87913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    switch (degrees) {
88013f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 0:
88113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
88213f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 90:
88313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
88413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0x00010000;
88513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0xFFFF0000;
88613f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
88713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
88813f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 180:
88913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0xFFFF0000;
89013f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0xFFFF0000;
89113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
89213f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 270:
89313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
89413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0xFFFF0000;
89513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0x00010000;
89613f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
89713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
89813f6284305e4b27395a23db7882d670bdb1bcae1James Dong        default:
89913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            CHECK(!"Should never reach this unknown rotation");
90013f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
90113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
90213f6284305e4b27395a23db7882d670bdb1bcae1James Dong
90313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(a);           // a
90413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(b);           // b
90513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // u
90613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(c);           // c
90713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(d);           // d
90813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // v
90913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // x
91013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // y
91113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0x40000000);  // w
91213f6284305e4b27395a23db7882d670bdb1bcae1James Dong}
91313f6284305e4b27395a23db7882d670bdb1bcae1James Dong
914411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() {
915411ba422e3635d534928ffd81abf54f4f291c739James Dong    close(mFd);
916411ba422e3635d534928ffd81abf54f4f291c739James Dong    mFd = -1;
917411ba422e3635d534928ffd81abf54f4f291c739James Dong    mInitCheck = NO_INIT;
918411ba422e3635d534928ffd81abf54f4f291c739James Dong    mStarted = false;
9194c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary    free(mMoovBoxBuffer);
9204c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary    mMoovBoxBuffer = NULL;
921411ba422e3635d534928ffd81abf54f4f291c739James Dong}
92213f6284305e4b27395a23db7882d670bdb1bcae1James Dong
9238bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dongstatus_t MPEG4Writer::reset() {
924674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
92537187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
926411ba422e3635d534928ffd81abf54f4f291c739James Dong    } else {
927411ba422e3635d534928ffd81abf54f4f291c739James Dong        if (!mWriterThreadStarted ||
928411ba422e3635d534928ffd81abf54f4f291c739James Dong            !mStarted) {
929411ba422e3635d534928ffd81abf54f4f291c739James Dong            if (mWriterThreadStarted) {
930411ba422e3635d534928ffd81abf54f4f291c739James Dong                stopWriterThread();
931411ba422e3635d534928ffd81abf54f4f291c739James Dong            }
932411ba422e3635d534928ffd81abf54f4f291c739James Dong            release();
933411ba422e3635d534928ffd81abf54f4f291c739James Dong            return OK;
934411ba422e3635d534928ffd81abf54f4f291c739James Dong        }
93520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
93620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
93737187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
9388f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t maxDurationUs = 0;
93965b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    int64_t minDurationUs = 0x7fffffffffffffffLL;
94020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
94120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
94237187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->stop();
94337187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK) {
94437187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
94537187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
94620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9478f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int64_t durationUs = (*it)->getDurationUs();
9488f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (durationUs > maxDurationUs) {
9498f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            maxDurationUs = durationUs;
95020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
95165b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        if (durationUs < minDurationUs) {
95265b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs = durationUs;
95365b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        }
95465b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    }
95565b3d76025c71d755b0fb3b6ead90255f25417edJames Dong
95665b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    if (mTracks.size() > 1) {
957a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGD("Duration from tracks range is [%" PRId64 ", %" PRId64 "] us",
95865b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs, maxDurationUs);
95920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
96020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    stopWriterThread();
9627837c17063a4c50bc856ba59418516fdab731de7James Dong
96337187916a486504acaf83bea30147eb5fbf46ae5James Dong    // Do not write out movie header on error.
96437187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err != OK) {
965411ba422e3635d534928ffd81abf54f4f291c739James Dong        release();
96637187916a486504acaf83bea30147eb5fbf46ae5James Dong        return err;
96737187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
96837187916a486504acaf83bea30147eb5fbf46ae5James Dong
96920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
9701acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
971c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset, SEEK_SET);
9721f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad        uint32_t size = htonl(static_cast<uint32_t>(mOffset - mMdatOffset));
973c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 4);
9741acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
975c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset + 8, SEEK_SET);
9761f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad        uint64_t size = mOffset - mMdatOffset;
9771acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        size = hton64(size);
978c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 8);
9791acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
980c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mOffset, SEEK_SET);
98120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9827b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // Construct moov box now
9837837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
9847b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    mWriteMoovBoxToMemory = mStreamableFile;
9857b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mWriteMoovBoxToMemory) {
9867b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // There is no need to allocate in-memory cache
9877b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // for moov box if the file is not streamable.
9887b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
9897b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
9907b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        CHECK(mMoovBoxBuffer != NULL);
9917b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    }
992b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMoovBox(maxDurationUs);
99320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9947b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // mWriteMoovBoxToMemory could be set to false in
9957b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // MPEG4Writer::write() method
9967b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mWriteMoovBoxToMemory) {
9977b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        mWriteMoovBoxToMemory = false;
9987b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // Content of the moov box is saved in the cache, and the in-memory
9997b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // moov box needs to be written to the file in a single shot.
10007b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
100143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize);
10027837c17063a4c50bc856ba59418516fdab731de7James Dong
10037837c17063a4c50bc856ba59418516fdab731de7James Dong        // Moov box
1004c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
10057837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset = mFreeBoxOffset;
1006674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset);
10077837c17063a4c50bc856ba59418516fdab731de7James Dong
10087837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free box
1009c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
10107837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
10117837c17063a4c50bc856ba59418516fdab731de7James Dong        write("free", 4);
10127b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    } else {
10137b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        ALOGI("The mp4 file will not be streamable.");
10147b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    }
10157837c17063a4c50bc856ba59418516fdab731de7James Dong
10167b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // Free in-memory cache for moov box
10177b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mMoovBoxBuffer != NULL) {
10187837c17063a4c50bc856ba59418516fdab731de7James Dong        free(mMoovBoxBuffer);
10197837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBuffer = NULL;
10207837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBufferOffset = 0;
10217837c17063a4c50bc856ba59418516fdab731de7James Dong    }
10227837c17063a4c50bc856ba59418516fdab731de7James Dong
10230c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
102420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1025411ba422e3635d534928ffd81abf54f4f291c739James Dong    release();
102637187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
102720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
102820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1029efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonuint32_t MPEG4Writer::getMpeg4Time() {
1030b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    time_t now = time(NULL);
1031efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // MP4 file uses time counting seconds since midnight, Jan. 1, 1904
1032efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // while time function returns Unix epoch values which starts
1033efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // at 1970-01-01. Lets add the number of seconds between them
10342b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    static const uint32_t delta = (66 * 365 + 17) * (24 * 60 * 60);
10352b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    if (now < 0 || uint32_t(now) > UINT32_MAX - delta) {
10362b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen        return 0;
10372b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    }
10382b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    uint32_t mpeg4Time = uint32_t(now) + delta;
1039efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    return mpeg4Time;
1040efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson}
1041efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson
1042efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) {
1043efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
1044b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("mvhd");
1045b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // version=0, flags=0
1046b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // creation time
1047b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // modification time
1048b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTimeScale);    // mvhd timescale
1049b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6;
1050b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(duration);
1051b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0x10000);       // rate: 1.0
1052b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0x100);         // volume
1053b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0);             // reserved
1054b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
1055b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
1056b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeCompositionMatrix(0); // matrix
1057b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1058b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1059b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1060b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1061b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1062b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1063b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTracks.size() + 1);  // nextTrackID
1064b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // mvhd
1065b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1066b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1067b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) {
1068b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("moov");
1069b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMvhdBox(durationUs);
107007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (mAreGeoTagsAvailable) {
107107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        writeUdtaBox();
107207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
1073e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeMetaBox();
1074b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t id = 1;
1075b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    for (List<Track *>::iterator it = mTracks.begin();
1076b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        it != mTracks.end(); ++it, ++id) {
1077b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (*it)->writeTrackHeader(mUse32BitOffset);
1078b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
1079b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // moov
1080b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1081b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
10822cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) {
1083b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("ftyp");
1084b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1085b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t fileType;
1086b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (param && param->findInt32(kKeyFileType, &fileType) &&
1087b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fileType != OUTPUT_FORMAT_MPEG_4) {
1088b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("3gp4");
10898284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeInt32(0);
10908284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("isom");
10918284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("3gp4");
1092b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
10938284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("mp42");
10948284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeInt32(0);
1095b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("isom");
10968284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("mp42");
1097b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
1098b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1099b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();
1100b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1101b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
110207ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() {
110307ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5)
110407ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5"
110507ec01904613a0bac32caaa8444b4690998faed7James Dong#endif
110607ec01904613a0bac32caaa8444b4690998faed7James Dong
110707ec01904613a0bac32caaa8444b4690998faed7James Dong    // Test mode is enabled only if rw.media.record.test system
110807ec01904613a0bac32caaa8444b4690998faed7James Dong    // property is enabled.
110907ec01904613a0bac32caaa8444b4690998faed7James Dong    char value[PROPERTY_VALUE_MAX];
111007ec01904613a0bac32caaa8444b4690998faed7James Dong    if (property_get("rw.media.record.test", value, NULL) &&
111107ec01904613a0bac32caaa8444b4690998faed7James Dong        (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) {
111207ec01904613a0bac32caaa8444b4690998faed7James Dong        return true;
111307ec01904613a0bac32caaa8444b4690998faed7James Dong    }
111407ec01904613a0bac32caaa8444b4690998faed7James Dong    return false;
111507ec01904613a0bac32caaa8444b4690998faed7James Dong}
111607ec01904613a0bac32caaa8444b4690998faed7James Dong
111770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() {
111807ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send session summary only if test mode is enabled
111907ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
112007ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
112107ec01904613a0bac32caaa8444b4690998faed7James Dong    }
112207ec01904613a0bac32caaa8444b4690998faed7James Dong
112370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
112470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong         it != mChunkInfos.end(); ++it) {
112570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int trackNum = it->mTrack->getTrackId() << 28;
112670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
112770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS,
112870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs);
112970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    }
113070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong}
113170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
113213aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
113313aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
113413aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
113513aec890216948b0c364f8f92792129d0335f506James Dong}
113613aec890216948b0c364f8f92792129d0335f506James Dong
113713aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() {
113813aec890216948b0c364f8f92792129d0335f506James Dong    mLock.lock();
113913aec890216948b0c364f8f92792129d0335f506James Dong}
114013aec890216948b0c364f8f92792129d0335f506James Dong
114113aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() {
114213aec890216948b0c364f8f92792129d0335f506James Dong    mLock.unlock();
114313aec890216948b0c364f8f92792129d0335f506James Dong}
114420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1145c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
1146c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
114720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1148c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    ::write(mFd,
1149c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          (const uint8_t *)buffer->data() + buffer->range_offset(),
1150c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          buffer->range_length());
115120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
115220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
115320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
115420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
115520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
115620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
115703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
115803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
115903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
116003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
116103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
116203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
116303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
116403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
116503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
116603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
116703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
116803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
116903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
117003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
117180f78b773f92048944a850efb7b60629643370cdPraveen Chavanoff64_t MPEG4Writer::addMultipleLengthPrefixedSamples_l(MediaBuffer *buffer) {
117280f78b773f92048944a850efb7b60629643370cdPraveen Chavan    off64_t old_offset = mOffset;
117380f78b773f92048944a850efb7b60629643370cdPraveen Chavan
117480f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const size_t kExtensionNALSearchRange = 64; // bytes to look for non-VCL NALUs
117580f78b773f92048944a850efb7b60629643370cdPraveen Chavan
117680f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *dataStart = (const uint8_t *)buffer->data() + buffer->range_offset();
117780f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *currentNalStart = dataStart;
117880f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *nextNalStart;
117980f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *data = dataStart;
118080f78b773f92048944a850efb7b60629643370cdPraveen Chavan    size_t nextNalSize;
118180f78b773f92048944a850efb7b60629643370cdPraveen Chavan    size_t searchSize = buffer->range_length() > kExtensionNALSearchRange ?
118280f78b773f92048944a850efb7b60629643370cdPraveen Chavan                   kExtensionNALSearchRange : buffer->range_length();
118380f78b773f92048944a850efb7b60629643370cdPraveen Chavan
118480f78b773f92048944a850efb7b60629643370cdPraveen Chavan    while (getNextNALUnit(&data, &searchSize, &nextNalStart,
118580f78b773f92048944a850efb7b60629643370cdPraveen Chavan            &nextNalSize, true) == OK) {
118610cc12c4eec9ff974edb72f9140b05762fa50907Lajos Molnar        size_t currentNalSize = nextNalStart - currentNalStart - 4 /* strip start-code */;
118780f78b773f92048944a850efb7b60629643370cdPraveen Chavan        MediaBuffer *nalBuf = new MediaBuffer((void *)currentNalStart, currentNalSize);
118880f78b773f92048944a850efb7b60629643370cdPraveen Chavan        addLengthPrefixedSample_l(nalBuf);
118980f78b773f92048944a850efb7b60629643370cdPraveen Chavan        nalBuf->release();
119080f78b773f92048944a850efb7b60629643370cdPraveen Chavan
119180f78b773f92048944a850efb7b60629643370cdPraveen Chavan        currentNalStart = nextNalStart;
119280f78b773f92048944a850efb7b60629643370cdPraveen Chavan    }
119380f78b773f92048944a850efb7b60629643370cdPraveen Chavan
119480f78b773f92048944a850efb7b60629643370cdPraveen Chavan    size_t currentNalOffset = currentNalStart - dataStart;
119580f78b773f92048944a850efb7b60629643370cdPraveen Chavan    buffer->set_range(buffer->range_offset() + currentNalOffset,
119680f78b773f92048944a850efb7b60629643370cdPraveen Chavan            buffer->range_length() - currentNalOffset);
119780f78b773f92048944a850efb7b60629643370cdPraveen Chavan    addLengthPrefixedSample_l(buffer);
119880f78b773f92048944a850efb7b60629643370cdPraveen Chavan
119980f78b773f92048944a850efb7b60629643370cdPraveen Chavan    return old_offset;
120080f78b773f92048944a850efb7b60629643370cdPraveen Chavan}
120180f78b773f92048944a850efb7b60629643370cdPraveen Chavan
1202c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
1203c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
120430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
120530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
120603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1207b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mUse4ByteNalLength) {
1208b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 24;
1209c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1210b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 16) & 0xff;
1211c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1212b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 8) & 0xff;
1213c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1214b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
1215c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1216c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong
1217c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd,
1218c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              (const uint8_t *)buffer->data() + buffer->range_offset(),
1219c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              length);
1220b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
1221b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 4;
1222b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
122343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_LT(length, 65536);
122430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1225b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 8;
1226c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1227b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
1228c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1229c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length);
1230b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 2;
1231b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
123230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
123330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
123430ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
123530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
12367837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write(
1237674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        const void *ptr, size_t size, size_t nmemb) {
12387837c17063a4c50bc856ba59418516fdab731de7James Dong
12397837c17063a4c50bc856ba59418516fdab731de7James Dong    const size_t bytes = size * nmemb;
12407837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
12417b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
1242c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
12431acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        if (moovBoxSize > mEstimatedMoovBoxSize) {
12447b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // The reserved moov box at the beginning of the file
12457b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // is not big enough. Moov box should be written to
12467b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // the end of the file from now on, but not to the
12477b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // in-memory cache.
12487b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
12497b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // We write partial moov box that is in the memory to
12507b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // the file first.
1251c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            for (List<off64_t>::iterator it = mBoxes.begin();
12527837c17063a4c50bc856ba59418516fdab731de7James Dong                 it != mBoxes.end(); ++it) {
12537837c17063a4c50bc856ba59418516fdab731de7James Dong                (*it) += mOffset;
12547837c17063a4c50bc856ba59418516fdab731de7James Dong            }
1255674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            lseek64(mFd, mOffset, SEEK_SET);
1256674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset);
12577b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            ::write(mFd, ptr, bytes);
12587837c17063a4c50bc856ba59418516fdab731de7James Dong            mOffset += (bytes + mMoovBoxBufferOffset);
12597b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
12607b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // All subsequent moov box content will be written
12617b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // to the end of the file.
12627837c17063a4c50bc856ba59418516fdab731de7James Dong            mWriteMoovBoxToMemory = false;
12637837c17063a4c50bc856ba59418516fdab731de7James Dong        } else {
12647837c17063a4c50bc856ba59418516fdab731de7James Dong            memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
12657837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset += bytes;
12667837c17063a4c50bc856ba59418516fdab731de7James Dong        }
12677837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1268674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        ::write(mFd, ptr, size * nmemb);
12697837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset += bytes;
12707837c17063a4c50bc856ba59418516fdab731de7James Dong    }
12717837c17063a4c50bc856ba59418516fdab731de7James Dong    return bytes;
12727837c17063a4c50bc856ba59418516fdab731de7James Dong}
12737837c17063a4c50bc856ba59418516fdab731de7James Dong
1274e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::beginBox(uint32_t id) {
1275e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    mBoxes.push_back(mWriteMoovBoxToMemory?
1276e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            mMoovBoxBufferOffset: mOffset);
1277e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
1278e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0);
1279e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(id);
1280e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
1281e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
128220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
12830c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(fourcc), 4);
128420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12857837c17063a4c50bc856ba59418516fdab731de7James Dong    mBoxes.push_back(mWriteMoovBoxToMemory?
12867837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset: mOffset);
128720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
128820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
128920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
129020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
129120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
129220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
12930c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
129420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1295c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = *--mBoxes.end();
129620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
129720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12987837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
12997837c17063a4c50bc856ba59418516fdab731de7James Dong       int32_t x = htonl(mMoovBoxBufferOffset - offset);
13007837c17063a4c50bc856ba59418516fdab731de7James Dong       memcpy(mMoovBoxBuffer + offset, &x, 4);
13017837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1302c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, offset, SEEK_SET);
13037837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mOffset - offset);
13047837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset -= 4;
1305c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
13067837c17063a4c50bc856ba59418516fdab731de7James Dong    }
130720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
130820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
130920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
1310674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 1);
131120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
131220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
131320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
131420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
1315674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 2);
131620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
131720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
131820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
131920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
1320674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 4);
132120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
132220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
132320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
132420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
1325674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 8);
132620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
132720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
132820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
132920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
1330674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, n + 1);
133120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
133220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
133320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
13340c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(s), 4);
1335674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, 4);
133620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
133720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
133807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
133907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format
134007b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) {
134107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
134207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
134307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
134407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
134507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[9];
134607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
134707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
134807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%c%.2d.", sign, wholePart);
134907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
135007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%+.2d.", wholePart);
135107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
135207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
135307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
135407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
135507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
135607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
135707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
135807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[4], 5, "%.4d", fractionalPart);
135907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
136007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
136107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 8);
136207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
136307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
136407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format
136507b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) {
136607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
136707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
136807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
136907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
137007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[10];
137107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
137207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
137307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%c%.3d.", sign, wholePart);
137407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
137507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%+.3d.", wholePart);
137607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
137707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
137807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
137907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
138007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
138107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
138207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
138307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[5], 5, "%.4d", fractionalPart);
138407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
138507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
138607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 9);
138707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
138807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
138907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
139007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
139107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and
139207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000.
139307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and
139407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180]
139507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
139607b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) {
139707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Is latitude or longitude out of range?
139807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (latitudex10000 < -900000 || latitudex10000 > 900000 ||
139907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        longitudex10000 < -1800000 || longitudex10000 > 1800000) {
140007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        return BAD_VALUE;
140107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
140207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
140307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLatitudex10000 = latitudex10000;
140407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLongitudex10000 = longitudex10000;
140507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mAreGeoTagsAvailable = true;
14067c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += 30;
140707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    return OK;
140807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
140907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
1410e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangstatus_t MPEG4Writer::setCaptureRate(float captureFps) {
1411e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    if (captureFps <= 0.0f) {
1412e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        return BAD_VALUE;
1413e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
1414e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
14157c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMetaKeys->setFloat(kMetaKey_CaptureFps, captureFps);
14167c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += sizeof(kMetaKey_CaptureFps) + 4 + 32;
14177c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
1418e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    return OK;
1419e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
1420e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
14214dbff11975e737482537e1636051690188f3fbc4Praveen Chavanstatus_t MPEG4Writer::setTemporalLayerCount(uint32_t layerCount) {
14224dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    if (layerCount > 9) {
14234dbff11975e737482537e1636051690188f3fbc4Praveen Chavan        return BAD_VALUE;
14244dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    }
14254dbff11975e737482537e1636051690188f3fbc4Praveen Chavan
14264dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    if (layerCount > 0) {
14274dbff11975e737482537e1636051690188f3fbc4Praveen Chavan        mMetaKeys->setInt32(kMetaKey_TemporalLayerCount, layerCount);
14284dbff11975e737482537e1636051690188f3fbc4Praveen Chavan        mMoovExtraSize += sizeof(kMetaKey_TemporalLayerCount) + 4 + 32;
14294dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    }
14304dbff11975e737482537e1636051690188f3fbc4Praveen Chavan
14314dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    return OK;
14324dbff11975e737482537e1636051690188f3fbc4Praveen Chavan}
14334dbff11975e737482537e1636051690188f3fbc4Praveen Chavan
143420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
1435674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(data, 1, size);
143620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
143720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
143878a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const {
143978a1a286f736888ae7af8860b2c424af0d978848James Dong    return mStreamableFile;
144078a1a286f736888ae7af8860b2c424af0d978848James Dong}
144178a1a286f736888ae7af8860b2c424af0d978848James Dong
1442d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() {
1443d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1444d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeLimitBytes == 0) {
1445d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1446d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1447d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1448956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
1449d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1450d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1451d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
1452d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
14531f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
145477e8ae9967a078770416619e99ddb5b010def312James Dong    if (!mStreamableFile) {
145577e8ae9967a078770416619e99ddb5b010def312James Dong        // Add 1024 bytes as error tolerance
145677e8ae9967a078770416619e99ddb5b010def312James Dong        return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes;
145777e8ae9967a078770416619e99ddb5b010def312James Dong    }
1458acd234bba9f048971d66890009eeff9a8db94be3James Dong    // Be conservative in the estimate: do not exceed 95% of
1459acd234bba9f048971d66890009eeff9a8db94be3James Dong    // the target file limit. For small target file size limit, though,
1460acd234bba9f048971d66890009eeff9a8db94be3James Dong    // this will not help.
1461acd234bba9f048971d66890009eeff9a8db94be3James Dong    return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100);
1462d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1463d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1464d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() {
1465d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1466d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationLimitUs == 0) {
1467d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1468d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1469d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1470d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1471d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1472d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
1473d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            return true;
1474d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1475d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1476d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return false;
1477d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1478d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
147925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
148025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
148125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
148225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
148325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
148425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
148525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
148625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
148725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
148825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
148925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
149025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
149125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
1492f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
1493a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGI("setStartTimestampUs: %" PRId64, timeUs);
149443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(timeUs, 0ll);
14953c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
1496065d1aff96818df54456053f1574aec8a234d0deJames Dong    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
1497f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimestampUs = timeUs;
1498a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Earliest track starting time: %" PRId64, mStartTimestampUs);
14993c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    }
15003c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
15013c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
1502f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() {
15033c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
15043c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    return mStartTimestampUs;
15053c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
15063c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
150758ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() {
150858ae9c530247668f8af36e30d228c716c226b3d4James Dong    Mutex::Autolock autolock(mLock);
150958ae9c530247668f8af36e30d228c716c226b3d4James Dong    return mTracks.size();
151058ae9c530247668f8af36e30d228c716c226b3d4James Dong}
151158ae9c530247668f8af36e30d228c716c226b3d4James Dong
151220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
151320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
151420111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
1515b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen        MPEG4Writer *owner, const sp<IMediaSource> &source, size_t trackId)
151620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
151725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
151820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
151920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
1520a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
1521a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mResumed(false),
1522eaae38445a340c4857c1c5569475879a728e63b7James Dong      mStarted(false),
1523bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong      mTrackId(trackId),
1524c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong      mTrackDurationUs(0),
1525956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mEstimatedTrackSizeBytes(0),
1526be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong      mSamplesHaveSameSize(true),
1527c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStszTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1528c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStcoTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1529c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mCo64TableEntries(new ListTableEntries<off64_t>(1000, 1)),
1530c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStscTableEntries(new ListTableEntries<uint32_t>(1000, 3)),
1531c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStssTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1532c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mSttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)),
1533c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mCttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)),
153420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
153525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
1536548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
153713f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mReachedEOS(false),
153813f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mRotation(0) {
153919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    getCodecSpecificDataFromInputFormatIfPossible();
15408f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
15411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    const char *mime;
15421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMeta->findCString(kKeyMIMEType, &mime);
15431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
15449aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mIsHevc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC);
15451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAudio = !strncasecmp(mime, "audio/", 6);
15461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
15471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
15481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1549b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar    // store temporal layer count
1550b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar    if (!mIsAudio) {
1551b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar        int32_t count;
1552b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar        if (mMeta->findInt32(kKeyTemporalLayerCount, &count) && count > 1) {
1553b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar            mOwner->setTemporalLayerCount(count);
1554b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar        }
1555b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar    }
1556b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar
1557c059860c73678a202bfa33062723e8f82fb779d9James Dong    setTimeScale();
1558c059860c73678a202bfa33062723e8f82fb779d9James Dong}
1559c059860c73678a202bfa33062723e8f82fb779d9James Dong
15601f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() {
15611f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1562c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t stcoBoxCount = (mOwner->use32BitFileOffset()
1563c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                            ? mStcoTableEntries->count()
1564c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                            : mCo64TableEntries->count());
1565c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    int64_t stcoBoxSizeBytes = stcoBoxCount * 4;
1566c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4);
15671f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
156878a1a286f736888ae7af8860b2c424af0d978848James Dong    mEstimatedTrackSizeBytes = mMdatSizeBytes;  // media data size
156978a1a286f736888ae7af8860b2c424af0d978848James Dong    if (!mOwner->isFileStreamable()) {
157078a1a286f736888ae7af8860b2c424af0d978848James Dong        // Reserved free space is not large enough to hold
157178a1a286f736888ae7af8860b2c424af0d978848James Dong        // all meta data and thus wasted.
1572c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 +  // stsc box size
1573c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mStssTableEntries->count() * 4 +   // stss box size
1574c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mSttsTableEntries->count() * 8 +   // stts box size
1575c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mCttsTableEntries->count() * 8 +   // ctts box size
157678a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stcoBoxSizeBytes +           // stco box size
157778a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stszBoxSizeBytes;            // stsz box size
157878a1a286f736888ae7af8860b2c424af0d978848James Dong    }
15791f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
15801f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
15811f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry(
15821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        size_t chunkId, size_t sampleId) {
15831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1584c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(chunkId));
1585c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(sampleId));
1586c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(1));
15871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
15881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
15891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) {
1590c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->add(htonl(sampleId));
15911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
15921f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
15931f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry(
159479761ab096f57c3027fad9556c2bc436672d614eJames Dong        size_t sampleCount, int32_t duration) {
15951f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
15965a217fba010e801c255503602bda4b86ac5a6ac9James Dong    if (duration == 0) {
1597377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGW("0-duration samples found: %zu", sampleCount);
15985a217fba010e801c255503602bda4b86ac5a6ac9James Dong    }
1599c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(sampleCount));
1600c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(duration));
16011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
16021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1603965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry(
1604965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        size_t sampleCount, int32_t duration) {
1605965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1606965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if (mIsAudio) {
1607965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
1608965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
1609c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(sampleCount));
1610c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(duration));
1611965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
1612965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1613c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) {
1614c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mOwner->use32BitFileOffset()) {
1615c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t value = offset;
1616c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->add(htonl(value));
1617c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
1618c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->add(hton64(offset));
1619c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    }
16201f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
16211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1622c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() {
16233856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setTimeScale");
1624c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Default time scale
1625c059860c73678a202bfa33062723e8f82fb779d9James Dong    mTimeScale = 90000;
1626c059860c73678a202bfa33062723e8f82fb779d9James Dong
1627c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mIsAudio) {
1628c059860c73678a202bfa33062723e8f82fb779d9James Dong        // Use the sampling rate as the default time scale for audio track.
1629c059860c73678a202bfa33062723e8f82fb779d9James Dong        int32_t sampleRate;
1630c059860c73678a202bfa33062723e8f82fb779d9James Dong        bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
1631c059860c73678a202bfa33062723e8f82fb779d9James Dong        CHECK(success);
1632c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = sampleRate;
1633c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1634c059860c73678a202bfa33062723e8f82fb779d9James Dong
1635c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If someone would like to overwrite the timescale, use user-supplied value.
1636c059860c73678a202bfa33062723e8f82fb779d9James Dong    int32_t timeScale;
1637c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
1638c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = timeScale;
1639c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1640c059860c73678a202bfa33062723e8f82fb779d9James Dong
164143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
164219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber}
164319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
164419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
164519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    const char *mime;
164619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
164719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
16489aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    uint32_t type;
16499aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const void *data = NULL;
16509aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t size = 0;
165119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
16529aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mMeta->findData(kKeyAVCC, &type, &data, &size);
16539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
16549aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mMeta->findData(kKeyHVCC, &type, &data, &size);
165519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
165619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
165719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
165819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            ESDS esds(data, size);
16599aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            if (esds.getCodecSpecificInfo(&data, &size) != OK) {
16609aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                data = NULL;
16619aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                size = 0;
166219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            }
166319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
166419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
16659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (data != NULL && copyCodecSpecificData((uint8_t *)data, size) == OK) {
16669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mGotAllCodecSpecificData = true;
16679aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
166820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
166920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
167020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
167120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
167220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1673c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStszTableEntries;
1674c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStcoTableEntries;
1675c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCo64TableEntries;
1676c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStscTableEntries;
1677c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mSttsTableEntries;
1678c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStssTableEntries;
1679c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCttsTableEntries;
1680c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
1681c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries = NULL;
1682c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStcoTableEntries = NULL;
1683c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCo64TableEntries = NULL;
1684c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries = NULL;
1685c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries = NULL;
1686c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries = NULL;
1687c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries = NULL;
1688c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
168920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
169020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
169120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
169220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
169320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
169420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
169593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
16963856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("initTrackingProgressStatus");
169793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mPreviousTrackTimeUs = -1;
169893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackingProgressStatus = false;
169993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
170093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    {
170193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeUs;
170293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
1703a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGV("Receive request to track progress status for every %" PRId64 " us", timeUs);
170493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackEveryTimeDurationUs = timeUs;
170593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackingProgressStatus = true;
170693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
170793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
170893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
170993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
17101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static
17111c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) {
17123856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("ThreadWrapper: %p", me);
17131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
17141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    writer->threadFunc();
17151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return NULL;
17161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
17171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17181c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) {
17193856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk: %p", chunk.mTrack);
17201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Mutex::Autolock autolock(mLock);
17211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK_EQ(mDone, false);
17221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
17241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
17251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (chunk.mTrack == it->mTrack) {  // Found owner
17271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            it->mChunks.push_back(chunk);
17281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.signal();
17291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            return;
17301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
17311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
17321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
173343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK(!"Received a chunk for a unknown track");
17341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
17351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1736fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) {
1737a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("writeChunkToFile: %" PRId64 " from %s track",
17385410afcbb0af5d29d9f710a1c2978c500f9792dcPannag Sanketi        chunk->mTimeStampUs, chunk->mTrack->isAudio()? "audio": "video");
1739fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1740fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    int32_t isFirstSample = true;
1741fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    while (!chunk->mSamples.empty()) {
1742fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        List<MediaBuffer *>::iterator it = chunk->mSamples.begin();
1743fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
17449aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        off64_t offset = (chunk->mTrack->isAvc() || chunk->mTrack->isHevc())
174580f78b773f92048944a850efb7b60629643370cdPraveen Chavan                                ? addMultipleLengthPrefixedSamples_l(*it)
1746fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong                                : addSample_l(*it);
1747fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1748fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (isFirstSample) {
1749fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            chunk->mTrack->addChunkOffset(offset);
1750fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            isFirstSample = false;
17511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
17521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it)->release();
17541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it) = NULL;
1755fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        chunk->mSamples.erase(it);
17561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1757fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    chunk->mSamples.clear();
17581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
17591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1760fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() {
17613856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeAllChunks");
17621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    size_t outstandingChunks = 0;
176370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    Chunk chunk;
176470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    while (findChunkToWrite(&chunk)) {
1765e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong        writeChunkToFile(&chunk);
176670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        ++outstandingChunks;
17671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
176870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
176970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    sendSessionSummary();
177070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
17711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mChunkInfos.clear();
1772377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    ALOGD("%zu chunks are written in the last batch", outstandingChunks);
17731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
17741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1775fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) {
17763856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("findChunkToWrite");
17771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
17791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Track *track = NULL;
17801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
17811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
17821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (!it->mChunks.empty()) {
17831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            List<Chunk>::iterator chunkIt = it->mChunks.begin();
17841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (chunkIt->mTimeStampUs < minTimestampUs) {
17851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                minTimestampUs = chunkIt->mTimeStampUs;
17861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                track = it->mTrack;
17871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            }
17881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
17891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
17901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (track == NULL) {
17923856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Nothing to be written after all");
1793fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        return false;
17941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
17951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mIsFirstChunk) {
17971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsFirstChunk = false;
17981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1799fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
18001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
18011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
18021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it->mTrack == track) {
1803fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            *chunk = *(it->mChunks.begin());
1804fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            it->mChunks.erase(it->mChunks.begin());
1805fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            CHECK_EQ(chunk->mTrack, track);
180670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
180770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t interChunkTimeUs =
180870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                chunk->mTimeStampUs - it->mPrevChunkTimestampUs;
180970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            if (interChunkTimeUs > it->mPrevChunkTimestampUs) {
181070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs = interChunkTimeUs;
181170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            }
181270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
1813fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            return true;
18141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
18151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1816fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1817fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    return false;
18181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
18191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18201c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() {
18213856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("threadFunc");
18221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1823a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0);
1824fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1825fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    Mutex::Autolock autoLock(mLock);
18261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mDone) {
1827fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        Chunk chunk;
1828fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        bool chunkFound = false;
1829fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1830fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) {
18311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.wait(mLock);
18321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
18331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1834de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // In real time recording mode, write without holding the lock in order
1835de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // to reduce the blocking time for media track threads.
1836de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // Otherwise, hold the lock until the existing chunks get written to the
1837de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // file.
1838fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (chunkFound) {
1839de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            if (mIsRealTimeRecording) {
1840de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui                mLock.unlock();
1841de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            }
1842fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            writeChunkToFile(&chunk);
1843de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            if (mIsRealTimeRecording) {
1844de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui                mLock.lock();
1845de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            }
1846fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        }
18471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1848fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1849fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    writeAllChunks();
18501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
18511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18521c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() {
18533856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("startWriterThread");
18541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mDone = false;
18561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsFirstChunk = true;
1857e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    mDriftTimeUs = 0;
18581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<Track *>::iterator it = mTracks.begin();
18591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mTracks.end(); ++it) {
18601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        ChunkInfo info;
18611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        info.mTrack = *it;
186270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mPrevChunkTimestampUs = 0;
186370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mMaxInterChunkDurUs = 0;
18641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.push_back(info);
18651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
18661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_t attr;
18681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_init(&attr);
18691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
18701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_create(&mThread, &attr, ThreadWrapper, this);
18711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_destroy(&attr);
1872411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = true;
18731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
18741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
18751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18761f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
187793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) {
1878a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (!mDone && mPaused) {
1879a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mPaused = false;
1880a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mResumed = true;
1881a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
1882a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
188325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
188493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t startTimeUs;
188519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
188619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        startTimeUs = 0;
188719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
188870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    mStartTimeRealUs = startTimeUs;
188919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
189013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t rotationDegrees;
189113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) {
189213f6284305e4b27395a23db7882d670bdb1bcae1James Dong        mRotation = rotationDegrees;
189313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
189413f6284305e4b27395a23db7882d670bdb1bcae1James Dong
189593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    initTrackingProgressStatus(params);
189693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
1897f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    sp<MetaData> meta = new MetaData;
1898de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) {
1899a472613aec322e25891abf5c77bf3f7e3c244920James Dong        /*
1900a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * This extra delay of accepting incoming audio/video signals
1901a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * helps to align a/v start time at the beginning of a recording
1902a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * session, and it also helps eliminate the "recording" sound for
1903a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * camcorder applications.
1904a472613aec322e25891abf5c77bf3f7e3c244920James Dong         *
190586b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * If client does not set the start time offset, we fall back to
190686b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * use the default initial delay value.
1907a472613aec322e25891abf5c77bf3f7e3c244920James Dong         */
190886b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
190986b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
191086b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
191186b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
191286b7f47aa7482424cf8fd248f1315311919be3b0James Dong        startTimeUs += startTimeOffsetUs;
1913a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Start time offset: %" PRId64 " us", startTimeOffsetUs);
1914a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
1915a472613aec322e25891abf5c77bf3f7e3c244920James Dong
1916f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    meta->setInt64(kKeyTime, startTimeUs);
1917a472613aec322e25891abf5c77bf3f7e3c244920James Dong
1918f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    status_t err = mSource->start(meta.get());
191925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
192025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
192125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
192225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
192320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
192420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
192520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
192620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
192720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
192820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
1929eaae38445a340c4857c1c5569475879a728e63b7James Dong    mStarted = true;
1930c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs = 0;
193125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
1932956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mEstimatedTrackSizeBytes = 0;
19331f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mMdatSizeBytes = 0;
193443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mMaxChunkDurationUs = 0;
1935826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar    mLastDecodingTimeUs = -1;
193620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
193725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
193820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
193925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
194025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
194120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
194220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
194337187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() {
1944a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
194537187916a486504acaf83bea30147eb5fbf46ae5James Dong    return OK;
1946a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
1947a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
194837187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() {
194972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGD("%s track stopping", mIsAudio? "Audio": "Video");
1950eaae38445a340c4857c1c5569475879a728e63b7James Dong    if (!mStarted) {
195129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Stop() called but track is not started");
1952eaae38445a340c4857c1c5569475879a728e63b7James Dong        return ERROR_END_OF_STREAM;
1953eaae38445a340c4857c1c5569475879a728e63b7James Dong    }
1954eaae38445a340c4857c1c5569475879a728e63b7James Dong
195520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
195637187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
195720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
195820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = true;
195920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
196072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGD("%s track source stopping", mIsAudio? "Audio": "Video");
196172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mSource->stop();
196272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGD("%s track source stopped", mIsAudio? "Audio": "Video");
196372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
196420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
196520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
1966377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy));
196737187916a486504acaf83bea30147eb5fbf46ae5James Dong
1968b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("%s track stopped", mIsAudio? "Audio": "Video");
196937187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
197020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
197120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
197225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
197325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
197425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
197525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
197620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
197720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
197820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
197920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
198037187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = track->threadEntry();
1981377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    return (void *)(uintptr_t)err;
198220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
198320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
19843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) {
19853856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("getNalUnitType: %d", byte);
19863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // nal_unit_type: 5-bit unsigned integer
19883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *type = (byte & 0x1F);
19893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
19903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet(
19923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
19933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19943856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseParamSet");
19953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    CHECK(type == kNalUnitTypeSeqParamSet ||
19963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong          type == kNalUnitTypePicParamSet);
19973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
199847d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar    const uint8_t *nextStartCode = findNextNalStartCode(data, length);
19993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *paramSetLen = nextStartCode - data;
20003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (*paramSetLen == 0) {
200129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Param set is malformed, since its length is 0");
20023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return NULL;
20033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
20043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    AVCParamSet paramSet(*paramSetLen, data);
20063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (type == kNalUnitTypeSeqParamSet) {
20073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (*paramSetLen < 4) {
200829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Seq parameter set malformed");
20093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return NULL;
20103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mSeqParamSets.empty()) {
20123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc = data[1];
20133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileCompatible = data[2];
20143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mLevelIdc = data[3];
20153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
20163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (mProfileIdc != data[1] ||
20173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mProfileCompatible != data[2] ||
20183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mLevelIdc != data[3]) {
201907b2fbfb40770f3be0f674596f2e51d257c6d2bdLajos Molnar                // COULD DO: set profile/level to the lowest required to support all SPSs
202029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Inconsistent profile/level found in seq parameter sets");
20213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return NULL;
20223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
20233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mSeqParamSets.push_back(paramSet);
20253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    } else {
20263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mPicParamSets.push_back(paramSet);
20273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
20283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return nextStartCode;
20293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
20303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData(
20323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
20333856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("copyAVCCodecSpecificData");
20343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 2 bytes for each of the parameter set length field
20363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // plus the 7 bytes for the header
20379aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return copyCodecSpecificData(data, size, 4 + 7);
20389aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
20399aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
20409aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyHEVCCodecSpecificData(
20419aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size) {
20429aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ALOGV("copyHEVCCodecSpecificData");
20439aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
20449aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Min length of HEVC CSD is 23. (ISO/IEC 14496-15:2014 Chapter 8.3.3.1.2)
20459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return copyCodecSpecificData(data, size, 23);
20469aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
20479aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
20489aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyCodecSpecificData(
20499aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size, size_t minLength) {
20509aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (size < minLength) {
2051377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGE("Codec specific data length too short: %zu", size);
20523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return ERROR_MALFORMED;
20533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
20543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificData = malloc(size);
20569aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
20579aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
20589aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
20599aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
20609aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificDataSize = size;
20613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    memcpy(mCodecSpecificData, data, size);
20623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
20633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
20643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData(
20663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
20673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20683856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseAVCCodecSpecificData");
20693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data starts with a start code.
20703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // SPS and PPS are separated with start codes.
20713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Also, SPS must come before PPS
20723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t type = kNalUnitTypeSeqParamSet;
20733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotSps = false;
20743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotPps = false;
20753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *tmp = data;
20763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = data;
20773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = size;
20783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t paramSetLen = 0;
20793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = 0;
20803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
20813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        getNalUnitType(*(tmp + 4), &type);
20823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (type == kNalUnitTypeSeqParamSet) {
20833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (gotPps) {
208429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
20853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
20863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
20873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
20883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotSps = true;
20893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
20903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
20913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else if (type == kNalUnitTypePicParamSet) {
20923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
209329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
20943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
20953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
20963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotPps) {
20973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotPps = true;
20983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
20993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
21003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
210129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Only SPS and PPS Nal units are expected");
21023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
21033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
21043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nextStartCode == NULL) {
21063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
21073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
21083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Move on to find the next parameter set
21103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft -= nextStartCode - tmp;
21113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        tmp = nextStartCode;
21123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mCodecSpecificDataSize += (2 + paramSetLen);
21133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
21143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
21163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of seq parameter sets
21173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nSeqParamSets = mSeqParamSets.size();
21183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets == 0) {
211929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find sequence parameter set");
21203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
21213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
21223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets > 0x1F) {
2124377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets);
21253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
21263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
21273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
21283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
21303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of pic parameter sets
21313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nPicParamSets = mPicParamSets.size();
21323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets == 0) {
213329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find picture parameter set");
21343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
21353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
21363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets > 0xFF) {
2137377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets);
21383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
21393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
21403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
21411374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME:
21421374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above
21431374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0
21441374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0
21453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
21463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the profiles
21473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // These profiles requires additional parameter set extensions
21483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mProfileIdc == 100 || mProfileIdc == 110 ||
21493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc == 122 || mProfileIdc == 144) {
215029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
21513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return BAD_VALUE;
21523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
21533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
21541374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif
21553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
21563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
2157548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
215803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
215903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
2160548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
216103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
216229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Already have codec specific data");
216303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
216403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
216503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
21663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4) {
2167377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGE("Codec specific data length too short: %zu", size);
216803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
216903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
217003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
21713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data is in the form of AVCCodecSpecificData
21723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (memcmp("\x00\x00\x00\x01", data, 4)) {
21733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return copyAVCCodecSpecificData(data, size);
217403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
217503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
21763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (parseAVCCodecSpecificData(data, size) != OK) {
217703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
217803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
217903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
21803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // ISO 14496-15: AVC file format
21813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize += 7;  // 7 more bytes in the header
218203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
21839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
21849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mCodecSpecificDataSize = 0;
21859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
21869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
21879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
218803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
21893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = 1;                     // version
21903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[1] = mProfileIdc;           // profile indication
21913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[2] = mProfileCompatible;    // profile compatibility
21923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[3] = mLevelIdc;
219303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
21943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
2195b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mOwner->useNalLengthFour()) {
2196b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 3;  // length size == 4 bytes
2197b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
2198b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 1;  // length size == 2 bytes
2199b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
220003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
22013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 3-bit '111' followed by 5-bit numSequenceParameterSets
22023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nSequenceParamSets = mSeqParamSets.size();
22033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[5] = 0xe0 | nSequenceParamSets;
22043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 6;
22053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
22063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mSeqParamSets.end(); ++it) {
22073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit sequence parameter set length
22083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t seqParamSetLength = it->mLength;
22093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = seqParamSetLength >> 8;
22103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = seqParamSetLength & 0xff;
22113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // SPS NAL unit (sequence parameter length bytes)
22133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, seqParamSetLength);
22143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + seqParamSetLength);
22153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
22163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 8-bit nPictureParameterSets
22183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nPictureParamSets = mPicParamSets.size();
22193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = nPictureParamSets;
22203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 1;
22213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
22223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mPicParamSets.end(); ++it) {
22233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit picture parameter set length
22243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t picParamSetLength = it->mLength;
22253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = picParamSetLength >> 8;
22263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = picParamSetLength & 0xff;
22273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // PPS Nal unit (picture parameter set length bytes)
22293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, picParamSetLength);
22303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + picParamSetLength);
22313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
223203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
223303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
223403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
223503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
22369aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22379aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::parseHEVCCodecSpecificData(
22389aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size, HevcParameterSets &paramSets) {
22399aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22409aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ALOGV("parseHEVCCodecSpecificData");
22419aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const uint8_t *tmp = data;
22429aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const uint8_t *nextStartCode = data;
22439aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t bytesLeft = size;
22449aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
224547d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar        nextStartCode = findNextNalStartCode(tmp + 4, bytesLeft - 4);
22469aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        status_t err = paramSets.addNalUnit(tmp + 4, (nextStartCode - tmp) - 4);
22479aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (err != OK) {
22489aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
22499aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
22509aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22519aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        // Move on to find the next parameter set
22529aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        bytesLeft -= nextStartCode - tmp;
22539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        tmp = nextStartCode;
22549aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
22559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22569aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t csdSize = 23;
22579aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const size_t numNalUnits = paramSets.getNumNalUnits();
22589aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    for (size_t i = 0; i < ARRAY_SIZE(kMandatoryHevcNalUnitTypes); ++i) {
22599aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        int type = kMandatoryHevcNalUnitTypes[i];
22609aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        size_t numParamSets = paramSets.getNumNalUnitsOfType(type);
22619aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (numParamSets == 0) {
22629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            ALOGE("Cound not find NAL unit of type %d", type);
22639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
22649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
22659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
22669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    for (size_t i = 0; i < ARRAY_SIZE(kHevcNalUnitTypes); ++i) {
22679aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        int type = kHevcNalUnitTypes[i];
22689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        size_t numParamSets = paramSets.getNumNalUnitsOfType(type);
22699aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (numParamSets > 0xffff) {
22709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            ALOGE("Too many seq parameter sets (%zu) found", numParamSets);
22719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
22729aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
22739aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        csdSize += 3;
22749aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        for (size_t j = 0; j < numNalUnits; ++j) {
22759aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            if (paramSets.getType(j) != type) {
22769aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                continue;
22779aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            }
22789aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            csdSize += 2 + paramSets.getSize(j);
22799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
22809aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
22819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificDataSize = csdSize;
22829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return OK;
22839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
22849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::makeHEVCCodecSpecificData(
22869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size) {
22879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData != NULL) {
22899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Already have codec specific data");
22909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
22919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
22929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (size < 4) {
22949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Codec specific data length too short: %zu", size);
22959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
22969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
22979aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22989aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Data is in the form of HEVCCodecSpecificData
22999aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (memcmp("\x00\x00\x00\x01", data, 4)) {
23009aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return copyHEVCCodecSpecificData(data, size);
23019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
23029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
23039aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    HevcParameterSets paramSets;
23049aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (parseHEVCCodecSpecificData(data, size, paramSets) != OK) {
23053d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim        ALOGE("failed parsing codec specific data");
23069aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
23079aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
23089aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
23099aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificData = malloc(mCodecSpecificDataSize);
23109aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
23119aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mCodecSpecificDataSize = 0;
23129aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
23139aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
23149aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
23159aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t err = paramSets.makeHvcc((uint8_t *)mCodecSpecificData,
23163d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim            &mCodecSpecificDataSize, mOwner->useNalLengthFour() ? 4 : 2);
23179aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (err != OK) {
23183d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim        ALOGE("failed constructing HVCC atom");
23199aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return err;
23209aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
23219aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
23229aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return OK;
23239aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
23249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
2325872a481558350634a3fd5cb67939de288af00ecbJames Dong/*
2326872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that
2327872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information
2328872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio
2329872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger
2330872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5,
2331872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined.
2332872a481558350634a3fd5cb67939de288af00ecbJames Dong */
2333872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) {
2334872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t driftTimeUs = 0;
2335872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) {
2336872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t prevDriftTimeUs = mOwner->getDriftTimeUs();
2337872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1;
2338872a481558350634a3fd5cb67939de288af00ecbJames Dong        mOwner->setDriftTimeUs(timeUs);
2339872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2340872a481558350634a3fd5cb67939de288af00ecbJames Dong}
2341872a481558350634a3fd5cb67939de288af00ecbJames Dong
234237187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() {
234330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
234413aec890216948b0c364f8f92792129d0335f506James Dong    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
234543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    const bool hasMultipleTracks = (mOwner->numTracks() > 1);
234613aec890216948b0c364f8f92792129d0335f506James Dong    int64_t chunkTimestampUs = 0;
234713aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nChunks = 0;
23487c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar    int32_t nActualFrames = 0;        // frames containing non-CSD data (non-0 length)
234913aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nZeroLengthFrames = 0;
2350965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastTimestampUs = 0;      // Previous sample time stamp
2351965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationUs = 0;       // Between the previous two samples
2352965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t currDurationTicks = 0;    // Timescale based ticks
2353965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationTicks = 0;    // Timescale based ticks
2354965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int32_t sampleCount = 1;          // Sample count in the current stts table entry
2355000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    uint32_t previousSampleSize = 0;  // Size of the previous sample
2356a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t previousPausedDurationUs = 0;
2357965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t timestampUs = 0;
2358000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t cttsOffsetTimeUs = 0;
2359000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t currCttsOffsetTimeTicks = 0;   // Timescale based ticks
2360000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t lastCttsOffsetTimeTicks = -1;  // Timescale based ticks
236143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    int32_t cttsSampleCount = 0;           // Sample count in the current ctts table entry
2362c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t lastSamplesPerChunk = 0;
2363e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2364a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    if (mIsAudio) {
2365a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
2366a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    } else {
2367a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
2368a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    }
2369de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
2370de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (mOwner->isRealTimeRecording()) {
2371de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
2372de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    }
2373985f838934510983d8a887461e98dca60a6e858fJames Dong
2374d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong    sp<MetaData> meta_data;
237520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
237693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t err = OK;
237720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
237811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih    const char *trackName = mIsAudio ? "Audio" : "Video";
237993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    while (!mDone && (err = mSource->read(&buffer)) == OK) {
238020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
238120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
238220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
238313aec890216948b0c364f8f92792129d0335f506James Dong            ++nZeroLengthFrames;
238420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
238520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
238620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2387a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // If the codec specific data has not been received yet, delay pause.
2388a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // After the codec specific data is received, discard what we received
2389a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // when the track is to be paused.
2390a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused && !mResumed) {
2391a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer->release();
2392a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer = NULL;
2393a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            continue;
2394a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2395a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
239630ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
239730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
239803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
239903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
240003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
24017c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // if config format (at track addition) already had CSD, keep that
24027c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // UNLESS we have not received any frames yet.
24037c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // TODO: for now the entire CSD has to come in one frame for encoders, even though
24047c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // they need to be spread out for decoders.
24057c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            if (mGotAllCodecSpecificData && nActualFrames > 0) {
24067c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                ALOGI("ignoring additional CSD for video track after first frame");
24077c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            } else {
24087c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                mMeta = mSource->getFormat(); // get output format after format change
24097c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar
24107c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                if (mIsAvc) {
24117c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    status_t err = makeAVCCodecSpecificData(
24127c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            (const uint8_t *)buffer->data()
24137c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                                + buffer->range_offset(),
24147c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
24157c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    CHECK_EQ((status_t)OK, err);
24167c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                } else if (mIsHevc) {
24177c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    status_t err = makeHEVCCodecSpecificData(
24187c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            (const uint8_t *)buffer->data()
24197c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                                + buffer->range_offset(),
24207c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
24217c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    CHECK_EQ((status_t)OK, err);
24227c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                } else if (mIsMPEG4) {
24237c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    copyCodecSpecificData((const uint8_t *)buffer->data() + buffer->range_offset(),
24247c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
24257c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                }
242630ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
242730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
242830ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
242930ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
243030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
2431548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
243230ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
2433a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2434a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
24357c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar        ++nActualFrames;
24367c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar
2437d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // Make a deep copy of the MediaBuffer and Metadata and release
2438d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // the original as soon as we can
2439d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
2440d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
2441d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                buffer->range_length());
2442d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        copy->set_range(0, buffer->range_length());
2443d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data = new MetaData(*buffer->meta_data().get());
2444d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer->release();
2445d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer = NULL;
2446d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
24479aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (mIsAvc || mIsHevc) StripStartcode(copy);
2448e136c3bb38e88315bf8797a464ebf2c788296b22James Dong
2449b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        size_t sampleSize = copy->range_length();
24509aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (mIsAvc || mIsHevc) {
2451b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            if (mOwner->useNalLengthFour()) {
2452b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 4;
2453b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            } else {
2454b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 2;
2455b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            }
2456b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        }
2457050b28a593350047845a45a14cc5026221ac1620James Dong
2458d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        // Max file size or duration handling
24591f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mMdatSizeBytes += sampleSize;
24601f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        updateTrackSizeEstimate();
24611f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
2462d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileSizeLimit()) {
2463316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang            ALOGW("Recorded file size exceeds limit %" PRId64 "bytes",
2464316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang                    mOwner->mMaxFileSizeLimitBytes);
2465d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
2466d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2467d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2468d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileDurationLimit()) {
2469316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang            ALOGW("Recorded file duration exceeds limit %" PRId64 "microseconds",
2470316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang                    mOwner->mMaxFileDurationLimitUs);
2471d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
2472d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2473d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2474d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2475050b28a593350047845a45a14cc5026221ac1620James Dong
2476d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        int32_t isSync = false;
2477d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
2478d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
2479d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
2480d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong////////////////////////////////////////////////////////////////////////////////
2481c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (mStszTableEntries->count() == 0) {
248270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mFirstSampleTimeRealUs = systemTime() / 1000;
2483f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimestampUs = timestampUs;
2484f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mOwner->setStartTimestampUs(mStartTimestampUs);
24858428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs = mStartTimestampUs;
24863c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        }
248748c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
2488a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mResumed) {
24898428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
249011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) {
249111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
249211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                return ERROR_MALFORMED;
249311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
249411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
24958428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
249611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) {
249711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
249811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                return ERROR_MALFORMED;
249911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
250011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
25018428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs += pausedDurationUs - lastDurationUs;
2502a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mResumed = false;
2503a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2504a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2505a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        timestampUs -= previousPausedDurationUs;
250611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
250711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
250811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            return ERROR_MALFORMED;
250911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        }
251011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2511000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        if (!mIsAudio) {
2512965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            /*
2513965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Composition time: timestampUs
2514965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Decoding time: decodingTimeUs
2515000e18370baae60ffd9f25b509501dd8c26deabfJames Dong             * Composition time offset = composition time - decoding time
2516965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             */
2517965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            int64_t decodingTimeUs;
2518965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
2519965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            decodingTimeUs -= previousPausedDurationUs;
2520826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar
2521826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            // ensure non-negative, monotonic decoding time
2522826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            if (mLastDecodingTimeUs < 0) {
2523826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar                decodingTimeUs = std::max((int64_t)0, decodingTimeUs);
2524826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            } else {
2525826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar                // increase decoding time by at least 1 tick
2526826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar                decodingTimeUs = std::max(
2527826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar                        mLastDecodingTimeUs + divUp(1000000, mTimeScale), decodingTimeUs);
2528826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            }
2529826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar
2530826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            mLastDecodingTimeUs = decodingTimeUs;
2531000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            cttsOffsetTimeUs =
2532000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
253311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) {
253411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
253511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                return ERROR_MALFORMED;
253611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
253711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2538965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            timestampUs = decodingTimeUs;
2539a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGV("decoding time: %" PRId64 " and ctts offset time: %" PRId64,
2540000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                timestampUs, cttsOffsetTimeUs);
2541000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2542000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts box table if necessary
2543000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            currCttsOffsetTimeTicks =
2544000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL;
254511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) {
254611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
254711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                return ERROR_MALFORMED;
254811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
254911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2550c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 0) {
255143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // Force the first ctts table entry to have one single entry
255243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // so that we can do adjustment for the initial track start
255343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // time offset easily in writeCttsBox().
255443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
255543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                addOneCttsTableEntry(1, currCttsOffsetTimeTicks);
255643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                cttsSampleCount = 0;      // No sample in ctts box is pending
255743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            } else {
255843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) {
255943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
256043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
256143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    cttsSampleCount = 1;  // One sample in ctts box is pending
256243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                } else {
256343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    ++cttsSampleCount;
256443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                }
256543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            }
2566000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2567000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts time offset range
2568c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 0) {
2569000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2570000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2571000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            } else {
2572000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) {
2573000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2574000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) {
2575000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2576000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                }
2577000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            }
2578000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2579965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        }
2580872a481558350634a3fd5cb67939de288af00ecbJames Dong
2581de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        if (mOwner->isRealTimeRecording()) {
2582872a481558350634a3fd5cb67939de288af00ecbJames Dong            if (mIsAudio) {
2583872a481558350634a3fd5cb67939de288af00ecbJames Dong                updateDriftTime(meta_data);
2584e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
2585e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
2586872a481558350634a3fd5cb67939de288af00ecbJames Dong
258711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
258811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
258911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            return ERROR_MALFORMED;
259011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        }
259111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2592a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("%s media time stamp: %" PRId64 " and previous paused duration %" PRId64,
259311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                trackName, timestampUs, previousPausedDurationUs);
2594c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong        if (timestampUs > mTrackDurationUs) {
2595c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong            mTrackDurationUs = timestampUs;
25963b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        }
25973b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber
25985a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // We need to use the time scale based ticks, rather than the
25995a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // timestamp itself to determine whether we have to use a new
26005a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // stts entry, since we may have rounding errors.
26015a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // The calculation is intended to reduce the accumulated
26025a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // rounding errors.
26035a217fba010e801c255503602bda4b86ac5a6ac9James Dong        currDurationTicks =
26045a217fba010e801c255503602bda4b86ac5a6ac9James Dong            ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
26055a217fba010e801c255503602bda4b86ac5a6ac9James Dong                (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
2606c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (currDurationTicks < 0ll) {
2607f85a83af8c6a98b46c394c32b90b09214a68f3e4Hangyu Kuang            ALOGE("do not support out of order frames (timestamp: %lld < last: %lld for %s track",
2608f85a83af8c6a98b46c394c32b90b09214a68f3e4Hangyu Kuang                    (long long)timestampUs, (long long)lastTimestampUs, trackName);
260911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
26100332fadec6e91c37fe39ab92b2c02922370bc853Hangyu Kuang            mSource->stop();
2611c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            return UNKNOWN_ERROR;
26128c460498c028888c533ab442be12b6d4b669b965James Dong        }
26138c460498c028888c533ab442be12b6d4b669b965James Dong
261485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // if the duration is different for this sample, see if it is close enough to the previous
261585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // duration that we can fudge it and use the same value, to avoid filling the stts table
261685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // with lots of near-identical entries.
261785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // "close enough" here means that the current duration needs to be adjusted by less
261885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // than 0.1 milliseconds
261985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) {
262085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL
262185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                    + (mTimeScale / 2)) / mTimeScale;
262285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            if (deltaUs > -100 && deltaUs < 100) {
262385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                // use previous ticks, and adjust timestamp as if it was actually that number
262485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                // of ticks
262585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                currDurationTicks = lastDurationTicks;
262685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                timestampUs += deltaUs;
262785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            }
262885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        }
262985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen
2630c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStszTableEntries->add(htonl(sampleSize));
2631c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (mStszTableEntries->count() > 2) {
2632c059860c73678a202bfa33062723e8f82fb779d9James Dong
2633a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // Force the first sample to have its own stts entry so that
2634a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // we can adjust its value later to maintain the A/V sync.
2635c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) {
263679761ab096f57c3027fad9556c2bc436672d614eJames Dong                addOneSttsTableEntry(sampleCount, lastDurationTicks);
2637be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                sampleCount = 1;
2638be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
2639be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                ++sampleCount;
2640be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
2641965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2642be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
2643be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        if (mSamplesHaveSameSize) {
2644c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) {
2645be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSamplesHaveSameSize = false;
2646be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
26478644c14618d30d9e57a69df40ed939986ebf02c4James Dong            previousSampleSize = sampleSize;
2648be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
2649a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("%s timestampUs/lastTimestampUs: %" PRId64 "/%" PRId64,
265011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                trackName, timestampUs, lastTimestampUs);
26518644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastDurationUs = timestampUs - lastTimestampUs;
2652c059860c73678a202bfa33062723e8f82fb779d9James Dong        lastDurationTicks = currDurationTicks;
26538644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastTimestampUs = timestampUs;
265420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2655d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        if (isSync != 0) {
2656c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            addOneStssTableEntry(mStszTableEntries->count());
2657d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        }
2658d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
265993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (mTrackingProgressStatus) {
266093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            if (mPreviousTrackTimeUs <= 0) {
266193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong                mPreviousTrackTimeUs = mStartTimestampUs;
266293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            }
2663faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong            trackProgressStatus(timestampUs);
266493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
266543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        if (!hasMultipleTracks) {
266680f78b773f92048944a850efb7b60629643370cdPraveen Chavan            off64_t offset = (mIsAvc || mIsHevc) ? mOwner->addMultipleLengthPrefixedSamples_l(copy)
266758ae9c530247668f8af36e30d228c716c226b3d4James Dong                                 : mOwner->addSample_l(copy);
2668c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2669c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t count = (mOwner->use32BitFileOffset()
2670c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        ? mStcoTableEntries->count()
2671c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        : mCo64TableEntries->count());
2672c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2673c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (count == 0) {
26741f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                addChunkOffset(offset);
267558ae9c530247668f8af36e30d228c716c226b3d4James Dong            }
267658ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy->release();
267758ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy = NULL;
267858ae9c530247668f8af36e30d228c716c226b3d4James Dong            continue;
267958ae9c530247668f8af36e30d228c716c226b3d4James Dong        }
268013aec890216948b0c364f8f92792129d0335f506James Dong
268113aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.push_back(copy);
268213aec890216948b0c364f8f92792129d0335f506James Dong        if (interleaveDurationUs == 0) {
26831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStscTableEntry(++nChunks, 1);
26841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            bufferChunk(timestampUs);
268513aec890216948b0c364f8f92792129d0335f506James Dong        } else {
268613aec890216948b0c364f8f92792129d0335f506James Dong            if (chunkTimestampUs == 0) {
268713aec890216948b0c364f8f92792129d0335f506James Dong                chunkTimestampUs = timestampUs;
268813aec890216948b0c364f8f92792129d0335f506James Dong            } else {
268943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                int64_t chunkDurationUs = timestampUs - chunkTimestampUs;
269043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                if (chunkDurationUs > interleaveDurationUs) {
269143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    if (chunkDurationUs > mMaxChunkDurationUs) {
269243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                        mMaxChunkDurationUs = chunkDurationUs;
269343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    }
269413aec890216948b0c364f8f92792129d0335f506James Dong                    ++nChunks;
269513aec890216948b0c364f8f92792129d0335f506James Dong                    if (nChunks == 1 ||  // First chunk
2696c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk != mChunkSamples.size()) {
2697c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk = mChunkSamples.size();
2698c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        addOneStscTableEntry(nChunks, lastSamplesPerChunk);
269913aec890216948b0c364f8f92792129d0335f506James Dong                    }
27001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                    bufferChunk(timestampUs);
270113aec890216948b0c364f8f92792129d0335f506James Dong                    chunkTimestampUs = timestampUs;
270213aec890216948b0c364f8f92792129d0335f506James Dong                }
270313aec890216948b0c364f8f92792129d0335f506James Dong            }
270413aec890216948b0c364f8f92792129d0335f506James Dong        }
270513aec890216948b0c364f8f92792129d0335f506James Dong
270620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
270725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
270845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (isTrackMalFormed()) {
2709690f546b0ee548dbfe997df36418e5302ec2d786James Dong        err = ERROR_MALFORMED;
2710f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    }
271145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
2712bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    mOwner->trackProgressStatus(mTrackId, -1, err);
2713be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
271413aec890216948b0c364f8f92792129d0335f506James Dong    // Last chunk
271543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (!hasMultipleTracks) {
2716c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        addOneStscTableEntry(1, mStszTableEntries->count());
271758ae9c530247668f8af36e30d228c716c226b3d4James Dong    } else if (!mChunkSamples.empty()) {
27181f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        addOneStscTableEntry(++nChunks, mChunkSamples.size());
27191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        bufferChunk(timestampUs);
272013aec890216948b0c364f8f92792129d0335f506James Dong    }
272113aec890216948b0c364f8f92792129d0335f506James Dong
2722be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // We don't really know how long the last frame lasts, since
2723be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // there is no frame time after it, just repeat the previous
2724be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // frame's duration.
2725c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() == 1) {
27268f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        lastDurationUs = 0;  // A single sample's duration
272779761ab096f57c3027fad9556c2bc436672d614eJames Dong        lastDurationTicks = 0;
2728be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    } else {
2729be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        ++sampleCount;  // Count for the last sample
2730be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    }
2731a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2732c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() <= 2) {
273379761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(1, lastDurationTicks);
2734a472613aec322e25891abf5c77bf3f7e3c244920James Dong        if (sampleCount - 1 > 0) {
273579761ab096f57c3027fad9556c2bc436672d614eJames Dong            addOneSttsTableEntry(sampleCount - 1, lastDurationTicks);
2736a472613aec322e25891abf5c77bf3f7e3c244920James Dong        }
2737a472613aec322e25891abf5c77bf3f7e3c244920James Dong    } else {
273879761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(sampleCount, lastDurationTicks);
2739a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
2740a472613aec322e25891abf5c77bf3f7e3c244920James Dong
274143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // The last ctts box may not have been written yet, and this
274243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // is to make sure that we write out the last ctts box.
274343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) {
274443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        if (cttsSampleCount > 0) {
274543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
274643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        }
274743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    }
274843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong
2749c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs += lastDurationUs;
275025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
275143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
275243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    sendTrackSummary(hasMultipleTracks);
275343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
2754df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
275511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            count, nZeroLengthFrames, mStszTableEntries->count(), trackName);
2756872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (mIsAudio) {
2757a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Audio track drift time: %" PRId64 " us", mOwner->getDriftTimeUs());
2758872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2759365a963142093a1cd8efdcea76b5f65096a5b115James Dong
276037187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err == ERROR_END_OF_STREAM) {
276137187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
276237187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
276337187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
2764365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
2765365a963142093a1cd8efdcea76b5f65096a5b115James Dong
276645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const {
2767c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() == 0) {                      // no samples written
276829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("The number of recorded samples is 0");
276945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
277045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
277145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
2772c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (!mIsAudio && mStssTableEntries->count() == 0) {  // no sync frames for video
277329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("There are no sync frames for video track");
277445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
277545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
277645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
277745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (OK != checkCodecSpecificData()) {         // no codec specific data
277845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
277945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
278045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
278145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    return false;
278245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong}
278345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
278443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) {
278507ec01904613a0bac32caaa8444b4690998faed7James Dong
278607ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send track summary only if test mode is enabled.
278707ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
278807ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
278907ec01904613a0bac32caaa8444b4690998faed7James Dong    }
279007ec01904613a0bac32caaa8444b4690998faed7James Dong
279143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int trackNum = (mTrackId << 28);
279243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
279343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
279443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE,
279543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mIsAudio? 0: 1);
279643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
279743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
279843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS,
279943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mTrackDurationUs / 1000);
280043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
280143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
280243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES,
2803c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    mStszTableEntries->count());
280443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
280586b7f47aa7482424cf8fd248f1315311919be3b0James Dong    {
280686b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // The system delay time excluding the requested initial delay that
280786b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // is used to eliminate the recording sound.
280886b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
280986b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
281086b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
281186b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
281286b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t initialDelayUs =
281386b7f47aa7482424cf8fd248f1315311919be3b0James Dong            mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs;
281486b7f47aa7482424cf8fd248f1315311919be3b0James Dong
281586b7f47aa7482424cf8fd248f1315311919be3b0James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
281670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS,
281770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    (initialDelayUs) / 1000);
281886b7f47aa7482424cf8fd248f1315311919be3b0James Dong    }
281970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
282007ec01904613a0bac32caaa8444b4690998faed7James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
282107ec01904613a0bac32caaa8444b4690998faed7James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES,
282207ec01904613a0bac32caaa8444b4690998faed7James Dong                    mMdatSizeBytes / 1024);
282307ec01904613a0bac32caaa8444b4690998faed7James Dong
282443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (hasMultipleTracks) {
282543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
282643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS,
282743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mMaxChunkDurationUs / 1000);
282870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
282970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
283070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        if (mStartTimestampUs != moovStartTimeUs) {
283170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
283270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
283370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS,
283470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    startTimeOffsetUs / 1000);
283570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        }
283643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    }
283743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong}
283843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
2839faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
2840a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("trackProgressStatus: %" PRId64 " us", timeUs);
2841c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2842215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    if (mTrackEveryTimeDurationUs > 0 &&
2843215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
2844a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("Fire time tracking progress status at %" PRId64 " us", timeUs);
2845bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err);
284693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        mPreviousTrackTimeUs = timeUs;
284793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
284893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
284993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
2850faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus(
2851bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        size_t trackId, int64_t timeUs, status_t err) {
2852faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    Mutex::Autolock lock(mLock);
2853bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t trackNum = (trackId << 28);
2854faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2855faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Error notification
2856faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Do not consider ERROR_END_OF_STREAM an error
2857faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (err != OK && err != ERROR_END_OF_STREAM) {
2858bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
2859bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL,
2860faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2861faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
2862faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2863faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2864faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (timeUs == -1) {
2865faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send completion notification
2866bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2867bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS,
2868faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2869faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    } else {
2870faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send progress status
2871bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2872bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME,
2873faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               timeUs / 1000);
2874faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2875faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong}
2876faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2877d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) {
2878a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("setDriftTimeUs: %" PRId64 " us", driftTimeUs);
2879e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2880d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    mDriftTimeUs = driftTimeUs;
2881e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2882e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2883e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() {
2884a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("getDriftTimeUs: %" PRId64 " us", mDriftTimeUs);
2885e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2886e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    return mDriftTimeUs;
2887e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2888e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2889de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghuibool MPEG4Writer::isRealTimeRecording() const {
2890de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    return mIsRealTimeRecording;
2891de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui}
2892de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
2893b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() {
2894b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    return mUse4ByteNalLength;
2895b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong}
2896b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
28971c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
28983856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk");
28991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
29001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Chunk chunk(this, timestampUs, mChunkSamples);
29011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mOwner->bufferChunk(chunk);
290213aec890216948b0c364f8f92792129d0335f506James Dong    mChunkSamples.clear();
290320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
290420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29053b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
2906c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    return mTrackDurationUs;
290720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
290820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2909d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
2910d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return mEstimatedTrackSizeBytes;
2911d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
2912d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2913690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const {
2914690f546b0ee548dbfe997df36418e5302ec2d786James Dong    const char *mime;
2915690f546b0ee548dbfe997df36418e5302ec2d786James Dong    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
2916690f546b0ee548dbfe997df36418e5302ec2d786James Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
2917690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
29189aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime) ||
29199aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        !strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
2920690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (!mCodecSpecificData ||
2921690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize <= 0) {
292229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Missing codec specific data");
2923690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2924690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2925690f546b0ee548dbfe997df36418e5302ec2d786James Dong    } else {
2926690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (mCodecSpecificData ||
2927690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize > 0) {
292829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Unexepected codec specific data found");
2929690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2930690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2931690f546b0ee548dbfe997df36418e5302ec2d786James Dong    }
2932690f546b0ee548dbfe997df36418e5302ec2d786James Dong    return OK;
2933690f546b0ee548dbfe997df36418e5302ec2d786James Dong}
2934690f546b0ee548dbfe997df36418e5302ec2d786James Dong
2935b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) {
293620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29373856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("%s track time scale: %d",
29381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsAudio? "Audio": "Video", mTimeScale);
29398f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
2940efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
2941b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("trak");
2942b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeTkhdBox(now);
2943b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("mdia");
2944b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeMdhdBox(now);
2945b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeHdlrBox();
2946b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->beginBox("minf");
2947b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                if (mIsAudio) {
2948b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeSmhdBox();
2949b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                } else {
2950b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeVmhdBox();
2951b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                }
2952b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeDinfBox();
2953b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeStblBox(use32BitOffset);
2954b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->endBox();  // minf
2955b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->endBox();  // mdia
2956b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // trak
2957b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2958b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2959b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) {
2960b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stbl");
2961b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsd");
2962b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);               // version=0, flags=0
2963b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);               // entry count
2964b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
2965b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAudioFourCCBox();
2966b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
2967b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeVideoFourCCBox();
2968b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2969b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsd
2970b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeSttsBox();
2971965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    writeCttsBox();
2972b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!mIsAudio) {
2973b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeStssBox();
2974b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2975b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStszBox();
2976b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStscBox();
2977b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStcoBox(use32BitOffset);
2978b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stbl
2979b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2980b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2981b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() {
2982b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
2983b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
2984b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
29858b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    const char *fourcc = getFourCCForMime(mime);
29868b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (fourcc == NULL) {
298729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
2988b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(!"should not be here, unknown mime type.");
2989b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2990b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
29918b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    mOwner->beginBox(fourcc);        // video format
2992b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2993b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2994b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // data ref index
2995b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
2996b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2997b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2998b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2999b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
3000b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3001b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t width, height;
3002b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeyWidth, &width);
3003b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = success && mMeta->findInt32(kKeyHeight, &height);
3004b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
3005b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3006b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(width);
3007b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(height);
3008b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // horiz resolution
3009b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // vert resolution
3010b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3011b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // frame count
3012c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo    mOwner->writeInt8(0);            // compressor string length
3013c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo    mOwner->write("                               ", 31);
3014b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x18);        // depth
3015b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(-1);          // predefined
3016b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
301743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_LT(23 + mCodecSpecificDataSize, 128);
3018b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3019b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
3020b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4vEsdsBox();
3021b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
3022b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeD263Box();
3023b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
3024b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAvccBox();
30259aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
30269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        writeHvccBox();
3027b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3028b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3029b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writePaspBox();
303058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    writeColrBox();
3031b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // mp4v, s263 or avc1
3032b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3033b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
303458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnarvoid MPEG4Writer::Track::writeColrBox() {
303558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    ColorAspects aspects;
303658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    memset(&aspects, 0, sizeof(aspects));
303758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    // TRICKY: using | instead of || because we want to execute all findInt32-s
303858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    if (mMeta->findInt32(kKeyColorPrimaries, (int32_t*)&aspects.mPrimaries)
303958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyTransferFunction, (int32_t*)&aspects.mTransfer)
304058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyColorMatrix, (int32_t*)&aspects.mMatrixCoeffs)
304158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyColorRange, (int32_t*)&aspects.mRange)) {
304258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        int32_t primaries, transfer, coeffs;
304358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        bool fullRange;
304458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        ColorUtils::convertCodecColorAspectsToIsoAspects(
304558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar                aspects, &primaries, &transfer, &coeffs, &fullRange);
304658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->beginBox("colr");
304758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeFourcc("nclx");
304858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(primaries);
304958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(transfer);
305058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(coeffs);
305158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt8(fullRange ? 128 : 0);
305258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->endBox(); // colr
305358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    }
305458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar}
305558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
3056b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() {
3057b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
3058b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
3059b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
30608b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    const char *fourcc = getFourCCForMime(mime);
30618b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (fourcc == NULL) {
306229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
3063b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(!"should not be here, unknown mime type.");
3064b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3065b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3066b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(fourcc);        // audio format
3067b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3068b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3069b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x1);         // data ref index
3070b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3071b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3072b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t nChannels;
3073b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
3074b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(nChannels);   // channel count
3075b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(16);          // sample size
3076b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
3077b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3078b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3079b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t samplerate;
3080b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeySampleRate, &samplerate);
3081b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
3082b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(samplerate << 16);
3083b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
3084b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4aEsdsBox();
3085b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
3086b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong               !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
3087b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeDamrBox();
3088b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3089b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3090b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3091b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3092b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() {
3093b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
3094b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
309543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mCodecSpecificDataSize, 0);
3096b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3097b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Make sure all sizes encode to a single byte.
309843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_LT(mCodecSpecificDataSize + 23, 128);
3099b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3100b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);     // version=0, flags=0
3101b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);   // ES_DescrTag
3102b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
3103b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);// ES_ID
3104b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x00);
3105b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3106b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
3107b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
3108b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
3109b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x15);   // streamType AudioStream
3110b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3111b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x03);  // XXX
311246f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt8(0x00);   // buffer size 24-bit (0x300)
311346f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar
311496bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t avgBitrate = 0;
311546f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyBitRate, &avgBitrate);
311696bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t maxBitrate = 0;
311746f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate);
311846f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(maxBitrate);
311946f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(avgBitrate);
3120b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3121b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
3122b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
3123b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3124b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3125b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
3126b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
3127b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
3128b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
3129b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3130b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
3131b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3132b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
3133b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3134b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3135b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() {
3136b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
313743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mCodecSpecificDataSize, 0);
3138b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
3139b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3140b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);    // version=0, flags=0
3141b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3142b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);  // ES_DescrTag
3143b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
3144b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);  // ES_ID
3145b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x1f);
3146b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3147b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
3148b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
3149b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
3150b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x11);  // streamType VisualStream
3151b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3152b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData[] = {
315346f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar        0x01, 0x77, 0x00, // buffer size 96000 bytes
3154b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3155b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData, sizeof(kData));
3156b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
315796bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t avgBitrate = 0;
315846f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyBitRate, &avgBitrate);
315996bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t maxBitrate = 0;
316046f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate);
316146f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(maxBitrate);
316246f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(avgBitrate);
316346f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar
3164b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
3165b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3166b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
3167b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3168b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3169b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
3170b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
3171b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
3172b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
3173b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3174b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
3175b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3176b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
3177b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3178b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3179efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeTkhdBox(uint32_t now) {
3180b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("tkhd");
3181b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Flags = 7 to indicate that the track is enabled, and
3182b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // part of the presentation
3183b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x07);          // version=0, flags=7
3184b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
3185b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
3186219f195159f93d627af2b243732e3f9020511a46James Dong    mOwner->writeInt32(mTrackId);      // track id starts with 1
3187b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
31888f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t trakDurationUs = getDurationUs();
3189b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mvhdTimeScale = mOwner->getTimeScale();
3190b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t tkhdDuration =
3191b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
3192b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
3193b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3194b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3195b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // layer
3196b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // alternate group
3197b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
3198b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // reserved
3199b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3200b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCompositionMatrix(mRotation);       // matrix
320120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3202b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
3203b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
3204b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
3205b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
3206b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        int32_t width, height;
3207b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        bool success = mMeta->findInt32(kKeyWidth, &width);
3208b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        success = success && mMeta->findInt32(kKeyHeight, &height);
3209b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(success);
3210b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3211b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
3212b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
3213b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3214b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // tkhd
3215b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3216b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3217b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() {
3218b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("vmhd");
3219b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x01);        // version=0, flags=1
3220b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // graphics mode
3221b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // opcolor
3222b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
3223b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
3224b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3225b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3226b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3227b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() {
3228b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("smhd");
3229b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // version=0, flags=0
3230b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // balance
3231b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3232b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3233b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3234b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3235b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() {
3236b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("hdlr");
3237b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
3238b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // component type: should be mhlr
3239b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeFourcc(mIsAudio ? "soun" : "vide");  // component subtype
3240b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3241b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3242b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3243b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Removing "r" for the name string just makes the string 4 byte aligned
3244b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle");  // name
3245b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3246b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3247b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3248efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeMdhdBox(uint32_t now) {
3249b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t trakDurationUs = getDurationUs();
3250b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("mdhd");
3251b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
3252b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
3253b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
3254b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mTimeScale);    // media timescale
3255b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
3256b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mdhdDuration);  // use media timescale
3257b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Language follows the three letter standard ISO-639-2/T
3258b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 'e', 'n', 'g' for "English", for instance.
3259b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Each character is packed as the difference between its ASCII value and 0x60.
3260b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // For "English", these are 00101, 01110, 00111.
3261b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // XXX: Where is the padding bit located: 0x15C7?
3262decc50efede28c5d73137c30d1a95d72dd405555David Yeh    const char *lang = NULL;
3263decc50efede28c5d73137c30d1a95d72dd405555David Yeh    int16_t langCode = 0;
3264decc50efede28c5d73137c30d1a95d72dd405555David Yeh    if (mMeta->findCString(kKeyMediaLanguage, &lang) && lang && strnlen(lang, 3) > 2) {
3265decc50efede28c5d73137c30d1a95d72dd405555David Yeh        langCode = ((lang[0] & 0x1f) << 10) | ((lang[1] & 0x1f) << 5) | (lang[2] & 0x1f);
3266decc50efede28c5d73137c30d1a95d72dd405555David Yeh    }
3267decc50efede28c5d73137c30d1a95d72dd405555David Yeh    mOwner->writeInt16(langCode);      // language code
3268b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // predefined
3269b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3270b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3271b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3272b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() {
3273b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 3gpp2 Spec AMRSampleEntry fields
3274b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("damr");
3275b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString("   ");  // vendor: 4 bytes
3276b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // decoder version
3277b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x83FF);   // mode set: all enabled
3278b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // mode change period
3279b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(1);         // frames per sample
3280b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3281b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3282b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3283b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() {
3284b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // The table index here refers to the sample description index
3285b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // in the sample table entries.
3286b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("url ");
3287b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
3288b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // url
3289b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3290b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3291b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() {
3292b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dref");
3293b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3294b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // entry count (either url or urn)
3295b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeUrlBox();
3296b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dref
3297b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3298b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3299b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() {
3300b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dinf");
3301b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeDrefBox();
3302b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dinf
3303b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3304b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3305b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() {
3306b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
330743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(mCodecSpecificDataSize, 5);
3308b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3309b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Patch avcc's lengthSize field to match the number
3310b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // of bytes we use to indicate the size of a nal unit.
3311b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
3312b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
3313b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("avcC");
3314b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3315b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // avcC
3316b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3317b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
33189aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
33199aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimvoid MPEG4Writer::Track::writeHvccBox() {
33209aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    CHECK(mCodecSpecificData);
33219aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    CHECK_GE(mCodecSpecificDataSize, 5);
33229aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
33239aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Patch avcc's lengthSize field to match the number
33249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // of bytes we use to indicate the size of a nal unit.
33259aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
33269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ptr[21] = (ptr[21] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
33279aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->beginBox("hvcC");
33289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
33299aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->endBox();  // hvcC
33309aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
33319aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
3332b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() {
3333b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("d263");
3334b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // vendor
3335b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // decoder version
3336b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(10);  // level: 10
3337b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // profile: 0
3338b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // d263
3339b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3340b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3341b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square
3342b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() {
3343b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("pasp");
3344b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // hspacing
3345b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // vspacing
3346b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // pasp
3347b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3348b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3349000e18370baae60ffd9f25b509501dd8c26deabfJames Dongint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const {
3350a472613aec322e25891abf5c77bf3f7e3c244920James Dong    int64_t trackStartTimeOffsetUs = 0;
3351b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
3352b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mStartTimestampUs != moovStartTimeUs) {
335343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_GT(mStartTimestampUs, moovStartTimeUs);
3354b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
3355b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3356000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    return (trackStartTimeOffsetUs *  mTimeScale + 500000LL) / 1000000LL;
3357000e18370baae60ffd9f25b509501dd8c26deabfJames Dong}
3358000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
3359000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() {
3360000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->beginBox("stts");
3361000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3362c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t duration;
3363c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    CHECK(mSttsTableEntries->get(duration, 1));
3364c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    duration = htonl(duration);  // Back to host byte order
3365c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1);
3366c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->write(mOwner);
3367b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stts
3368b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
336920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3370965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() {
3371965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if (mIsAudio) {  // ctts is not for audio
3372965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
3373965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
3374965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3375000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    // There is no B frame at all
3376000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) {
3377000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        return;
3378000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    }
3379000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
3380965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    // Do not write ctts box when there is no need to have it.
3381c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mCttsTableEntries->count() == 0) {
3382965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
3383965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
3384965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3385a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("ctts box has %d entries with range [%" PRId64 ", %" PRId64 "]",
3386c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs);
3387965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3388965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->beginBox("ctts");
3389000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3390c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t duration;
3391c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    CHECK(mCttsTableEntries->get(duration, 1));
3392c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    duration = htonl(duration);  // Back host byte order
3393c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime() - mMinCttsOffsetTimeUs), 1);
3394c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->write(mOwner);
3395965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->endBox();  // ctts
3396965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
3397965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3398b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() {
3399b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stss");
3400b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3401c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->write(mOwner);
3402b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stss
3403b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
340425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
3405b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() {
3406b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsz");
3407b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3408c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mOwner->writeInt32(0);
3409c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries->write(mOwner);
3410b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsz
3411b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
341220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3413b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() {
3414b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsc");
3415b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3416c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries->write(mOwner);
3417b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsc
3418b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
341920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3420b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) {
3421b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(use32BitOffset? "stco": "co64");
3422b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3423c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (use32BitOffset) {
3424c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->write(mOwner);
3425c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
3426c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->write(mOwner);
3427b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3428b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stco or co64
342920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
343020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
343107b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() {
343207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("udta");
343307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeGeoDataBox();
343407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
343507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
343607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
3437e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeHdlr() {
3438e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("hdlr");
3439e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Version, Flags
3440e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Predefined
3441e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeFourcc("mdta");
3442e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[0]
3443e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[1]
3444e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[2]
3445e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt8(0);  // Name (empty)
3446e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3447e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3448e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3449e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeKeys() {
3450e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3451e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3452e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("keys");
3453e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0);     // Version, Flags
3454e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(count); // Entry_count
3455e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    for (size_t i = 0; i < count; i++) {
3456e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        AMessage::Type type;
3457e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        const char *key = mMetaKeys->getEntryNameAt(i, &type);
3458e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        size_t n = strlen(key);
3459e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writeInt32(n + 8);
3460e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writeFourcc("mdta");
3461e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        write(key, n); // write without the \0
3462e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3463e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3464e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3465e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3466e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeIlst() {
3467e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3468e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3469e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("ilst");
3470e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    for (size_t i = 0; i < count; i++) {
3471e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        beginBox(i + 1); // key id (1-based)
3472e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        beginBox("data");
3473e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        AMessage::Type type;
3474e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        const char *key = mMetaKeys->getEntryNameAt(i, &type);
3475e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        switch (type) {
34767c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            case AMessage::kTypeString:
34777c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            {
34787c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                AString val;
34797c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                CHECK(mMetaKeys->findString(key, &val));
34807c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(1); // type = UTF8
34817c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0); // default country/language
34827c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                write(val.c_str(), strlen(val.c_str())); // write without \0
34837c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                break;
34847c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            }
34857c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
3486e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            case AMessage::kTypeFloat:
3487e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3488e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                float val;
3489e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                CHECK(mMetaKeys->findFloat(key, &val));
34907c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(23); // type = float32
34917c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3492e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(*reinterpret_cast<int32_t *>(&val));
3493e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3494e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3495e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3496e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            case AMessage::kTypeInt32:
3497e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3498e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                int32_t val;
3499e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                CHECK(mMetaKeys->findInt32(key, &val));
35007c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(67); // type = signed int32
35017c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3502e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(val);
3503e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3504e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3505e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3506e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            default:
3507e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3508e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                ALOGW("Unsupported key type, writing 0 instead");
35097c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(77); // type = unsigned int32
35107c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3511e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(0);
3512e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3513e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3514e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        }
3515e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        endBox(); // data
3516e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        endBox(); // key id
3517e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3518e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox(); // ilst
3519e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3520e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3521e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeMetaBox() {
3522e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3523e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    if (count == 0) {
3524e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        return;
3525e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3526e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3527e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("meta");
3528e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeHdlr();
3529e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeKeys();
3530e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeIlst();
3531e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3532e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3533e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
353407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
353507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
353607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
353707b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() {
353807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("\xA9xyz");
353907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    /*
354007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * For historical reasons, any user data start
354107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * with "\0xA9", must be followed by its assoicated
354207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * language code.
3543432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x0012: text string length
3544432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x15c7: lang (locale) code: en
354507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     */
354607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt32(0x001215c7);
354707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLatitude(mLatitudex10000);
354807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLongitude(mLongitudex10000);
354907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt8(0x2F);
355007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
355107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
355207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
355320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
3554