MPEG4Extractor.cpp revision 90ba107fcf36ce6df111a594b2cc27163b36793d
1e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber/*
2e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * Copyright (C) 2009 The Android Open Source Project
3e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *
4e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * you may not use this file except in compliance with the License.
6e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * You may obtain a copy of the License at
7e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *
8e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *
10e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * Unless required by applicable law or agreed to in writing, software
11e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * See the License for the specific language governing permissions and
14e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * limitations under the License.
15e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber */
16e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
17e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#define LOG_TAG "MPEG4Extractor"
18e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <utils/Log.h>
19e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
2057515f334bcc1f66f95e342bfcaa13bf9ca802adAndreas Huber#include "include/MPEG4Extractor.h"
21bd7b43bb02852e51b3000185fa66e10c56b120e0Andreas Huber#include "include/SampleTable.h"
22c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang#include "include/ESDS.h"
2313bc8cde1c842bea1fa3000a48739a6e22f25a9cGloria Wang#include "timedtext/TimedTextPlayer.h"
24bd7b43bb02852e51b3000185fa66e10c56b120e0Andreas Huber
25e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <arpa/inet.h>
26e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
27e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <ctype.h>
28e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <stdint.h>
29e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <stdlib.h>
30e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <string.h>
31e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
32940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber#include <media/stagefright/foundation/ADebug.h>
33e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/DataSource.h>
34e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaBuffer.h>
35e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaBufferGroup.h>
36e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber#include <media/stagefright/MediaDefs.h>
37e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaSource.h>
38e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MetaData.h>
39e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/Utils.h>
40e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <utils/String8.h>
41e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
42e46b7be812d68e49710b34048662cbf18e2a6550Andreas Hubernamespace android {
43e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
44e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberclass MPEG4Source : public MediaSource {
45e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberpublic:
46e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    // Caller retains ownership of both "dataSource" and "sampleTable".
47be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber    MPEG4Source(const sp<MetaData> &format,
48be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber                const sp<DataSource> &dataSource,
49fa8de752507feaca695123911915070c1ce463b2Andreas Huber                int32_t timeScale,
50be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber                const sp<SampleTable> &sampleTable);
51e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
52e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    virtual status_t start(MetaData *params = NULL);
53e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    virtual status_t stop();
54e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
55e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    virtual sp<MetaData> getFormat();
56e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
57e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    virtual status_t read(
58e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            MediaBuffer **buffer, const ReadOptions *options = NULL);
59e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
60be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huberprotected:
61be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber    virtual ~MPEG4Source();
62be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber
63e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberprivate:
64ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber    Mutex mLock;
65ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber
66e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    sp<MetaData> mFormat;
67be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber    sp<DataSource> mDataSource;
68e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    int32_t mTimescale;
69be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber    sp<SampleTable> mSampleTable;
70e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    uint32_t mCurrentSampleIndex;
71e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
72e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    bool mIsAVC;
73db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    size_t mNALLengthSize;
74db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
75e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    bool mStarted;
76e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
77e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    MediaBufferGroup *mGroup;
78e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
79e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    MediaBuffer *mBuffer;
80e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
814f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    bool mWantsNALFragments;
82e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
838a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    uint8_t *mSrcBuffer;
848a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber
85db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    size_t parseNALSize(const uint8_t *data) const;
86db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
87e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    MPEG4Source(const MPEG4Source &);
88e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    MPEG4Source &operator=(const MPEG4Source &);
89e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber};
90e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
91affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// This custom data source wraps an existing one and satisfies requests
92affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// falling entirely within a cached range from the cache while forwarding
93affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// all remaining requests to the wrapped datasource.
94affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// This is used to cache the full sampletable metadata for a single track,
95affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// possibly wrapping multiple times to cover all tracks, i.e.
96affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// Each MPEG4DataSource caches the sampletable metadata for a single track.
97affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
98affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberstruct MPEG4DataSource : public DataSource {
99affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    MPEG4DataSource(const sp<DataSource> &source);
100affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
101affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    virtual status_t initCheck() const;
102b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong    virtual ssize_t readAt(off64_t offset, void *data, size_t size);
103b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong    virtual status_t getSize(off64_t *size);
104affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    virtual uint32_t flags();
105affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
106b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong    status_t setCachedRange(off64_t offset, size_t size);
107affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
108affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberprotected:
109affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    virtual ~MPEG4DataSource();
110affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
111affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberprivate:
112affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    Mutex mLock;
113affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
114affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    sp<DataSource> mSource;
115b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong    off64_t mCachedOffset;
116affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    size_t mCachedSize;
117affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    uint8_t *mCache;
118affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
119affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    void clearCache();
120affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
121affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    MPEG4DataSource(const MPEG4DataSource &);
122affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    MPEG4DataSource &operator=(const MPEG4DataSource &);
123affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber};
124affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
125affa99c52957685f5a5652ab5254b92e729651c7Andreas HuberMPEG4DataSource::MPEG4DataSource(const sp<DataSource> &source)
126affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    : mSource(source),
127affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber      mCachedOffset(0),
128affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber      mCachedSize(0),
129affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber      mCache(NULL) {
130affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber}
131affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
132affa99c52957685f5a5652ab5254b92e729651c7Andreas HuberMPEG4DataSource::~MPEG4DataSource() {
133affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    clearCache();
134affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber}
135affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
136affa99c52957685f5a5652ab5254b92e729651c7Andreas Hubervoid MPEG4DataSource::clearCache() {
137affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    if (mCache) {
138affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber        free(mCache);
139affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber        mCache = NULL;
140affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    }
141affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
142affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    mCachedOffset = 0;
143affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    mCachedSize = 0;
144affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber}
145affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
146affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberstatus_t MPEG4DataSource::initCheck() const {
147affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    return mSource->initCheck();
148affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber}
149affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
150b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dongssize_t MPEG4DataSource::readAt(off64_t offset, void *data, size_t size) {
151affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    Mutex::Autolock autoLock(mLock);
152affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
153affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    if (offset >= mCachedOffset
154affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber            && offset + size <= mCachedOffset + mCachedSize) {
155affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber        memcpy(data, &mCache[offset - mCachedOffset], size);
156affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber        return size;
157affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    }
158affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
159affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    return mSource->readAt(offset, data, size);
160affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber}
161affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
162b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dongstatus_t MPEG4DataSource::getSize(off64_t *size) {
163affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    return mSource->getSize(size);
164affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber}
165affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
166affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberuint32_t MPEG4DataSource::flags() {
167affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    return mSource->flags();
168affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber}
169affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
170b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dongstatus_t MPEG4DataSource::setCachedRange(off64_t offset, size_t size) {
171affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    Mutex::Autolock autoLock(mLock);
172affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
173affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    clearCache();
174affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
175affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    mCache = (uint8_t *)malloc(size);
176affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
177affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    if (mCache == NULL) {
178affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber        return -ENOMEM;
179affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    }
180affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
181affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    mCachedOffset = offset;
182affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    mCachedSize = size;
183affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
184affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    ssize_t err = mSource->readAt(mCachedOffset, mCache, mCachedSize);
185affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
186affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    if (err < (ssize_t)size) {
187affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber        clearCache();
188affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
189affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber        return ERROR_IO;
190affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    }
191affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
192affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    return OK;
193affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber}
194affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
195affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber////////////////////////////////////////////////////////////////////////////////
196affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
197e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatic void hexdump(const void *_data, size_t size) {
198e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    const uint8_t *data = (const uint8_t *)_data;
199e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    size_t offset = 0;
200e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    while (offset < size) {
201e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        printf("0x%04x  ", offset);
202e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
203e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        size_t n = size - offset;
204e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (n > 16) {
205e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            n = 16;
206e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
207e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
208e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        for (size_t i = 0; i < 16; ++i) {
209e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (i == 8) {
210e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                printf(" ");
211e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
212e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
213e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (offset + i < size) {
214e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                printf("%02x ", data[offset + i]);
215e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            } else {
216e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                printf("   ");
217e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
218e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
219e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
220e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        printf(" ");
221e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
222e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        for (size_t i = 0; i < n; ++i) {
223e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (isprint(data[offset + i])) {
224e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                printf("%c", data[offset + i]);
225e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            } else {
226e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                printf(".");
227e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
228e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
229e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
230e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        printf("\n");
231e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
232e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        offset += 16;
233e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
234e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
235e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
236e6c409632f773e41f33188272a0072be9fcb783fAndreas Huberstatic const char *FourCC2MIME(uint32_t fourcc) {
237e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    switch (fourcc) {
238e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
239e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber            return MEDIA_MIMETYPE_AUDIO_AAC;
240e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
241e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
242e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_NB;
243e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
2442a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber        case FOURCC('s', 'a', 'w', 'b'):
245e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_WB;
2462a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber
247e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
248e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber            return MEDIA_MIMETYPE_VIDEO_MPEG4;
249e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
250e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', '2', '6', '3'):
2510efdc95d59a51a130ce9d2515bcc9e2c01b52f14James Dong        case FOURCC('h', '2', '6', '3'):
2520efdc95d59a51a130ce9d2515bcc9e2c01b52f14James Dong        case FOURCC('H', '2', '6', '3'):
253e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber            return MEDIA_MIMETYPE_VIDEO_H263;
254e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
255e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
256e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber            return MEDIA_MIMETYPE_VIDEO_AVC;
257e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
258e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        default:
2594f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            CHECK(!"should not be here.");
260e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            return NULL;
261e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
262e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
263e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
264be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas HuberMPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
265e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    : mDataSource(source),
266f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber      mInitCheck(NO_INIT),
2671cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber      mHasVideo(false),
268e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mFirstTrack(NULL),
269c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber      mLastTrack(NULL),
270d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang      mFileMetaData(new MetaData),
271d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang      mFirstSINF(NULL),
272d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang      mIsDrm(false) {
273e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
274e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
275e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberMPEG4Extractor::~MPEG4Extractor() {
276e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    Track *track = mFirstTrack;
277e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    while (track) {
278e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        Track *next = track->next;
279e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
280e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        delete track;
281e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        track = next;
282e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
283e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mFirstTrack = mLastTrack = NULL;
284d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
285d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    SINF *sinf = mFirstSINF;
286d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    while (sinf) {
287d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        SINF *next = sinf->next;
288d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        delete sinf->IPMPData;
289d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        delete sinf;
290d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        sinf = next;
291d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    }
292d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    mFirstSINF = NULL;
293e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
294e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
2951cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Hubersp<MetaData> MPEG4Extractor::getMetaData() {
2961cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber    status_t err;
2971cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber    if ((err = readMetaData()) != OK) {
298c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        return new MetaData;
2991cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber    }
3001cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber
301c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    return mFileMetaData;
3021cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber}
3031cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber
304be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Hubersize_t MPEG4Extractor::countTracks() {
305e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    status_t err;
306e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if ((err = readMetaData()) != OK) {
307be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber        return 0;
308e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
309e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
310be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber    size_t n = 0;
311e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    Track *track = mFirstTrack;
312e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    while (track) {
313be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber        ++n;
314e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        track = track->next;
315e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
316e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
317be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber    return n;
318e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
319e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
320e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Hubersp<MetaData> MPEG4Extractor::getTrackMetaData(
321e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber        size_t index, uint32_t flags) {
322e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    status_t err;
323e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if ((err = readMetaData()) != OK) {
324e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return NULL;
325e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
326e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
327e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    Track *track = mFirstTrack;
328e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    while (index > 0) {
329e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (track == NULL) {
330e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            return NULL;
331e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
332e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
333e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        track = track->next;
334e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        --index;
335e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
336e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
3372a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber    if (track == NULL) {
3382a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber        return NULL;
3392a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber    }
3402a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber
341e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber    if ((flags & kIncludeExtensiveMetaData)
342e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber            && !track->includes_expensive_metadata) {
343e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber        track->includes_expensive_metadata = true;
344e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber
345e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber        const char *mime;
346e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber        CHECK(track->meta->findCString(kKeyMIMEType, &mime));
347e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber        if (!strncasecmp("video/", mime, 6)) {
348e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber            uint32_t sampleIndex;
349e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber            uint32_t sampleTime;
350e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber            if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK
3511faa92a1e93f311e86dca483ed7702091137de66Andreas Huber                    && track->sampleTable->getMetaDataForSample(
3521faa92a1e93f311e86dca483ed7702091137de66Andreas Huber                        sampleIndex, NULL /* offset */, NULL /* size */,
3531faa92a1e93f311e86dca483ed7702091137de66Andreas Huber                        &sampleTime) == OK) {
354e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber                track->meta->setInt64(
355e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber                        kKeyThumbnailTime,
356e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber                        ((int64_t)sampleTime * 1000000) / track->timescale);
357e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber            }
358e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber        }
359e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber    }
360e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber
361e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return track->meta;
362e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
363e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
364e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Extractor::readMetaData() {
365f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber    if (mInitCheck != NO_INIT) {
366f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber        return mInitCheck;
367e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
368e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
369b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong    off64_t offset = 0;
370e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    status_t err;
371e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    while ((err = parseChunk(&offset, 0)) == OK) {
372e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
3731cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber
374f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber    if (mInitCheck == OK) {
375c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        if (mHasVideo) {
376c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            mFileMetaData->setCString(kKeyMIMEType, "video/mp4");
377c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        } else {
378c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            mFileMetaData->setCString(kKeyMIMEType, "audio/mp4");
379c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
380c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
38144fdac0c62916ddcfac1fe887d867e7ff0cf446fAndreas Huber        mInitCheck = OK;
382f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber    } else {
383f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber        mInitCheck = err;
384e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
385e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
386f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber    CHECK_NE(err, (status_t)NO_INIT);
387f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber    return mInitCheck;
388e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
389e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
390d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wangchar* MPEG4Extractor::getDrmTrackInfo(size_t trackID, int *len) {
391d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    if (mFirstSINF == NULL) {
392d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        return NULL;
393d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    }
394d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
395d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    SINF *sinf = mFirstSINF;
396d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    while (sinf && (trackID != sinf->trackID)) {
397d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        sinf = sinf->next;
398d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    }
399d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
400d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    if (sinf == NULL) {
401d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        return NULL;
402d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    }
403d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
404d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    *len = sinf->len;
405d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    return sinf->IPMPData;
406d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang}
407d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
408d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang// Reads an encoded integer 7 bits at a time until it encounters the high bit clear.
409b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dongint32_t readSize(off64_t offset,
410d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        const sp<DataSource> DataSource, uint8_t *numOfBytes) {
411d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    uint32_t size = 0;
412d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    uint8_t data;
413d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    bool moreData = true;
414d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    *numOfBytes = 0;
415d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
416d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    while (moreData) {
417d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        if (DataSource->readAt(offset, &data, 1) < 1) {
418d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            return -1;
419d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        }
420d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        offset ++;
421d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        moreData = (data >= 128) ? true : false;
422d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        size = (size << 7) | (data & 0x7f); // Take last 7 bits
423d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        (*numOfBytes) ++;
424d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    }
425d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
426d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    return size;
427d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang}
428d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
429b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dongstatus_t MPEG4Extractor::parseDrmSINF(off64_t *offset, off64_t data_offset) {
430d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    uint8_t updateIdTag;
431d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
432d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        return ERROR_IO;
433d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    }
434d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    data_offset ++;
435d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
436d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    if (0x01/*OBJECT_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
437d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        return ERROR_MALFORMED;
438d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    }
439d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
440d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    uint8_t numOfBytes;
441d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    int32_t size = readSize(data_offset, mDataSource, &numOfBytes);
442d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    if (size < 0) {
443d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        return ERROR_IO;
444d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    }
445d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    int32_t classSize = size;
446d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    data_offset += numOfBytes;
447d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
448d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    while(size >= 11 ) {
449d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        uint8_t descriptorTag;
450d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        if (mDataSource->readAt(data_offset, &descriptorTag, 1) < 1) {
451d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            return ERROR_IO;
452d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        }
453d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        data_offset ++;
454d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
455d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        if (0x11/*OBJECT_DESCRIPTOR_ID_TAG*/ != descriptorTag) {
456d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            return ERROR_MALFORMED;
457d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        }
458d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
459d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        uint8_t buffer[8];
460d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        //ObjectDescriptorID and ObjectDescriptor url flag
461d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        if (mDataSource->readAt(data_offset, buffer, 2) < 2) {
462d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            return ERROR_IO;
463d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        }
464d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        data_offset += 2;
465d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
466d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        if ((buffer[1] >> 5) & 0x0001) { //url flag is set
467d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            return ERROR_MALFORMED;
468d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        }
469d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
470d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        if (mDataSource->readAt(data_offset, buffer, 8) < 8) {
471d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            return ERROR_IO;
472d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        }
473d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        data_offset += 8;
474d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
475d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        if ((0x0F/*ES_ID_REF_TAG*/ != buffer[1])
476d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                || ( 0x0A/*IPMP_DESCRIPTOR_POINTER_ID_TAG*/ != buffer[5])) {
477d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            return ERROR_MALFORMED;
478d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        }
479d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
480d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        SINF *sinf = new SINF;
481d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        sinf->trackID = U16_AT(&buffer[3]);
482d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        sinf->IPMPDescriptorID = buffer[7];
483d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        sinf->next = mFirstSINF;
484d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        mFirstSINF = sinf;
485d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
486d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        size -= (8 + 2 + 1);
487d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    }
488d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
489d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    if (size != 0) {
490d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        return ERROR_MALFORMED;
491d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    }
492d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
493d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
494d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        return ERROR_IO;
495d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    }
496d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    data_offset ++;
497d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
498d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    if(0x05/*IPMP_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
499d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        return ERROR_MALFORMED;
500d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    }
501d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
502d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    size = readSize(data_offset, mDataSource, &numOfBytes);
503d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    if (size < 0) {
504d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        return ERROR_IO;
505d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    }
506d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    classSize = size;
507d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    data_offset += numOfBytes;
508d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
509d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    while (size > 0) {
510d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        uint8_t tag;
511d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        int32_t dataLen;
512d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        if (mDataSource->readAt(data_offset, &tag, 1) < 1) {
513d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            return ERROR_IO;
514d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        }
515d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        data_offset ++;
516d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
517d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        if (0x0B/*IPMP_DESCRIPTOR_ID_TAG*/ == tag) {
518d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            uint8_t id;
519d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            dataLen = readSize(data_offset, mDataSource, &numOfBytes);
520d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            if (dataLen < 0) {
521d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                return ERROR_IO;
522d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            } else if (dataLen < 4) {
523d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                return ERROR_MALFORMED;
524d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            }
525d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            data_offset += numOfBytes;
526d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
527d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            if (mDataSource->readAt(data_offset, &id, 1) < 1) {
528d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                return ERROR_IO;
529d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            }
530d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            data_offset ++;
531d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
532d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            SINF *sinf = mFirstSINF;
533d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            while (sinf && (sinf->IPMPDescriptorID != id)) {
534d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                sinf = sinf->next;
535d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            }
536d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            if (sinf == NULL) {
537d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                return ERROR_MALFORMED;
538d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            }
539d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            sinf->len = dataLen - 3;
540d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            sinf->IPMPData = new char[sinf->len];
541d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
542d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            if (mDataSource->readAt(data_offset + 2, sinf->IPMPData, sinf->len) < sinf->len) {
543d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                return ERROR_IO;
544d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            }
545d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            data_offset += sinf->len;
546d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
547d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            size -= (dataLen + numOfBytes + 1);
548d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        }
549d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    }
550d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
551d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    if (size != 0) {
552d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        return ERROR_MALFORMED;
553d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    }
554d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
555d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang    return UNKNOWN_ERROR;  // Return a dummy error.
556d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang}
557d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
558e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatic void MakeFourCCString(uint32_t x, char *s) {
559e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    s[0] = x >> 24;
560e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    s[1] = (x >> 16) & 0xff;
561e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    s[2] = (x >> 8) & 0xff;
562e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    s[3] = x & 0xff;
563e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    s[4] = '\0';
564e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
565e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
566c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huberstruct PathAdder {
567c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    PathAdder(Vector<uint32_t> *path, uint32_t chunkType)
568c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        : mPath(path) {
569c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        mPath->push(chunkType);
570c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    }
571c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
572c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    ~PathAdder() {
573c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        mPath->pop();
574c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    }
575c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
576c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huberprivate:
577c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    Vector<uint32_t> *mPath;
578c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
579c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    PathAdder(const PathAdder &);
580c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    PathAdder &operator=(const PathAdder &);
581c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber};
582c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
583c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huberstatic bool underMetaDataPath(const Vector<uint32_t> &path) {
584c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    return path.size() >= 5
585c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        && path[0] == FOURCC('m', 'o', 'o', 'v')
586c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        && path[1] == FOURCC('u', 'd', 't', 'a')
587c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        && path[2] == FOURCC('m', 'e', 't', 'a')
588c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        && path[3] == FOURCC('i', 'l', 's', 't');
589c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber}
590c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
591c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber// Given a time in seconds since Jan 1 1904, produce a human-readable string.
592c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huberstatic void convertTimeToDate(int64_t time_1904, String8 *s) {
593c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    time_t time_1970 = time_1904 - (((66 * 365 + 17) * 24) * 3600);
594c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
595c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    char tmp[32];
596c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    strftime(tmp, sizeof(tmp), "%Y%m%dT%H%M%S.000Z", gmtime(&time_1970));
597c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
598c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    s->setTo(tmp);
599c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber}
600c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
601b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dongstatus_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
602e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    uint32_t hdr[2];
6039a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
604e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return ERROR_IO;
605e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
606e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    uint64_t chunk_size = ntohl(hdr[0]);
607e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    uint32_t chunk_type = ntohl(hdr[1]);
608b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong    off64_t data_offset = *offset + 8;
609e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
610e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (chunk_size == 1) {
6119a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
612e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            return ERROR_IO;
613e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
614e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        chunk_size = ntoh64(chunk_size);
615e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        data_offset += 8;
616736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber
617736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber        if (chunk_size < 16) {
618736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber            // The smallest valid chunk is 16 bytes long in this case.
619736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber            return ERROR_MALFORMED;
620736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber        }
621736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber    } else if (chunk_size < 8) {
622736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber        // The smallest valid chunk is 8 bytes long.
623736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber        return ERROR_MALFORMED;
624e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
625e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
626e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    char chunk[5];
627e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    MakeFourCCString(chunk_type, chunk);
628e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
629e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#if 0
630e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    static const char kWhitespace[] = "                                        ";
631e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth];
632e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    printf("%sfound chunk '%s' of size %lld\n", indent, chunk, chunk_size);
633e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
634e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    char buffer[256];
635dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber    size_t n = chunk_size;
636dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber    if (n > sizeof(buffer)) {
637dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber        n = sizeof(buffer);
638dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber    }
639dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber    if (mDataSource->readAt(*offset, buffer, n)
640dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber            < (ssize_t)n) {
641dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber        return ERROR_IO;
642e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
643dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber
644dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber    hexdump(buffer, n);
645e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#endif
646e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
647c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    PathAdder autoAdder(&mPath, chunk_type);
648c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
649b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong    off64_t chunk_data_size = *offset + chunk_size - data_offset;
650e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
651c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    if (chunk_type != FOURCC('c', 'p', 'r', 't')
652e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong            && chunk_type != FOURCC('c', 'o', 'v', 'r')
653c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            && mPath.size() == 5 && underMetaDataPath(mPath)) {
654b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong        off64_t stop_offset = *offset + chunk_size;
655c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        *offset = data_offset;
656c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        while (*offset < stop_offset) {
657c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            status_t err = parseChunk(offset, depth + 1);
658c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (err != OK) {
659c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                return err;
660c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
661c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
6625ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
6635ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber        if (*offset != stop_offset) {
6645ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            return ERROR_MALFORMED;
6655ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber        }
666c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
667c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        return OK;
668c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    }
669c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
670e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    switch(chunk_type) {
671e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'o', 'o', 'v'):
672e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('t', 'r', 'a', 'k'):
673e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'd', 'i', 'a'):
674e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'i', 'n', 'f'):
675e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('d', 'i', 'n', 'f'):
676e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 'b', 'l'):
677e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'v', 'e', 'x'):
678e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'o', 'o', 'f'):
679e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('t', 'r', 'a', 'f'):
680e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'f', 'r', 'a'):
681c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('u', 'd', 't', 'a'):
682c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('i', 'l', 's', 't'):
683e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
684affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber            if (chunk_type == FOURCC('s', 't', 'b', 'l')) {
685affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                LOGV("sampleTable chunk is %d bytes long.", (size_t)chunk_size);
686affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
6876da2ae11b62f155ee83c3e31fdd9cc53b2058586Andreas Huber                if (mDataSource->flags()
6886da2ae11b62f155ee83c3e31fdd9cc53b2058586Andreas Huber                        & (DataSource::kWantsPrefetching
6896da2ae11b62f155ee83c3e31fdd9cc53b2058586Andreas Huber                            | DataSource::kIsCachingDataSource)) {
690affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                    sp<MPEG4DataSource> cachedSource =
691affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                        new MPEG4DataSource(mDataSource);
692affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
693affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                    if (cachedSource->setCachedRange(*offset, chunk_size) == OK) {
694affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                        mDataSource = cachedSource;
695affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                    }
696affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                }
697eb9128f9b0ee660504621381fd96f82d5bf8a3fdAndreas Huber
698eb9128f9b0ee660504621381fd96f82d5bf8a3fdAndreas Huber                mLastTrack->sampleTable = new SampleTable(mDataSource);
699affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber            }
700affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
7014d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber            bool isTrack = false;
7025ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            if (chunk_type == FOURCC('t', 'r', 'a', 'k')) {
7034d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                isTrack = true;
7044d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber
7055ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                Track *track = new Track;
7065ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                track->next = NULL;
7075ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                if (mLastTrack) {
7085ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                    mLastTrack->next = track;
7095ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                } else {
7105ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                    mFirstTrack = track;
7115ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                }
7125ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                mLastTrack = track;
7135ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
7145ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                track->meta = new MetaData;
7155ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                track->includes_expensive_metadata = false;
7164d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                track->skipTrack = false;
7175ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                track->timescale = 0;
7185ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                track->meta->setCString(kKeyMIMEType, "application/octet-stream");
7195ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            }
7205ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
721b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong            off64_t stop_offset = *offset + chunk_size;
722e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset = data_offset;
723e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            while (*offset < stop_offset) {
724e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                status_t err = parseChunk(offset, depth + 1);
725e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (err != OK) {
726e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return err;
727e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
728e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
729e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
7305ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            if (*offset != stop_offset) {
7315ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                return ERROR_MALFORMED;
7325ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            }
7335ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
7344d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber            if (isTrack) {
7354d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                if (mLastTrack->skipTrack) {
7364d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                    Track *cur = mFirstTrack;
7374d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber
7384d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                    if (cur == mLastTrack) {
7394d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                        delete cur;
7404d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                        mFirstTrack = mLastTrack = NULL;
7414d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                    } else {
7424d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                        while (cur && cur->next != mLastTrack) {
7434d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                            cur = cur->next;
7444d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                        }
7454d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                        cur->next = NULL;
7464d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                        delete mLastTrack;
7474d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                        mLastTrack = cur;
7484d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                    }
7494d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber
7504d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                    return OK;
7514d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                }
7524d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber
7535ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                status_t err = verifyTrack(mLastTrack);
7545ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
7555ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                if (err != OK) {
7565ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                    return err;
7575ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                }
7585ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
759f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber                mInitCheck = OK;
760e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
761d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                if (!mIsDrm) {
762d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                    return UNKNOWN_ERROR;  // Return a dummy error.
763d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                } else {
764d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                    return OK;
765d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                }
766e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
767e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
768e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
769e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
770e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('t', 'k', 'h', 'd'):
771e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
772940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber            status_t err;
773940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber            if ((err = parseTrackHeader(data_offset, chunk_data_size)) != OK) {
774940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber                return err;
775e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
776e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
777e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
778e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
779e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
780e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
781e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'd', 'h', 'd'):
782e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
783e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size < 4) {
784e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
785e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
786e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
787e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t version;
7889a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(
789e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, &version, sizeof(version))
790e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    < (ssize_t)sizeof(version)) {
791e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
792e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
793e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
794b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong            off64_t timescale_offset;
795e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
796e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (version == 1) {
797e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                timescale_offset = data_offset + 4 + 16;
798e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            } else if (version == 0) {
799e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                timescale_offset = data_offset + 4 + 8;
800e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            } else {
801e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
802e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
803e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
804e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint32_t timescale;
8059a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(
806e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        timescale_offset, &timescale, sizeof(timescale))
807e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    < (ssize_t)sizeof(timescale)) {
808e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
809e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
810e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
811e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->timescale = ntohl(timescale);
812e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
813e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            int64_t duration;
814e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (version == 1) {
8159a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber                if (mDataSource->readAt(
816e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                            timescale_offset + 4, &duration, sizeof(duration))
817e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        < (ssize_t)sizeof(duration)) {
818e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return ERROR_IO;
819e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
820e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                duration = ntoh64(duration);
821e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            } else {
822e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                int32_t duration32;
8239a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber                if (mDataSource->readAt(
824e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                            timescale_offset + 4, &duration32, sizeof(duration32))
825e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        < (ssize_t)sizeof(duration32)) {
826e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return ERROR_IO;
827e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
828e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                duration = ntohl(duration32);
829e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
830fa8de752507feaca695123911915070c1ce463b2Andreas Huber            mLastTrack->meta->setInt64(
831fa8de752507feaca695123911915070c1ce463b2Andreas Huber                    kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
832e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
833c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang            uint8_t lang[2];
834c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang            off64_t lang_offset;
835c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang            if (version == 1) {
836c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang                lang_offset = timescale_offset + 4 + 8;
837c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang            } else if (version == 0) {
838c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang                lang_offset = timescale_offset + 4 + 4;
839c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang            } else {
840c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang                return ERROR_IO;
841c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang            }
842c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang
843c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang            if (mDataSource->readAt(lang_offset, &lang, sizeof(lang))
844c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang                    < (ssize_t)sizeof(lang)) {
845c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang                return ERROR_IO;
846c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang            }
847c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang
848c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang            // To get the ISO-639-2/T three character language code
849c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang            // 1 bit pad followed by 3 5-bits characters. Each character
850c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang            // is packed as the difference between its ASCII value and 0x60.
851c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang            char lang_code[4];
852c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang            lang_code[0] = ((lang[0] >> 2) & 0x1f) + 0x60;
853c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang            lang_code[1] = ((lang[0] & 0x3) << 3 | (lang[1] >> 5)) + 0x60;
854c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang            lang_code[2] = (lang[1] & 0x1f) + 0x60;
855c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang            lang_code[3] = '\0';
856c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang
857c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang            mLastTrack->meta->setCString(
858c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang                    kKeyMediaLanguage, lang_code);
859c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang
860e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
861e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
862e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
863e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
864e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 's', 'd'):
865e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
866e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size < 8) {
867e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
868e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
869e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
870e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t buffer[8];
871b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong            if (chunk_data_size < (off64_t)sizeof(buffer)) {
8725ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                return ERROR_MALFORMED;
8735ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            }
8745ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
8759a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(
876e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, buffer, 8) < 8) {
877e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
878e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
879e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
880e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (U32_AT(buffer) != 0) {
881e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // Should be version 0, flags 0.
882e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
883e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
884e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
885e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint32_t entry_count = U32_AT(&buffer[4]);
886e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
887e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (entry_count > 1) {
888eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang                // For 3GPP timed text, there could be multiple tx3g boxes contain
889eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang                // multiple text display formats. These formats will be used to
890eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang                // display the timed text.
891eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang                const char *mime;
892eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang                CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
893eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang                if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
894eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang                    // For now we only support a single type of media per track.
895eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang                    mLastTrack->skipTrack = true;
896eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang                    *offset += chunk_size;
897eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang                    break;
898eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang                }
899e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
900e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
901b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong            off64_t stop_offset = *offset + chunk_size;
902e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset = data_offset + 8;
903e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            for (uint32_t i = 0; i < entry_count; ++i) {
904e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                status_t err = parseChunk(offset, depth + 1);
905e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (err != OK) {
906e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return err;
907e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
908e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
9095ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
9105ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            if (*offset != stop_offset) {
9115ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                return ERROR_MALFORMED;
9125ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            }
913e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
914e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
915e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
916e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
917e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
9182a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber        case FOURCC('s', 'a', 'w', 'b'):
919e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
920e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t buffer[8 + 20];
921e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
922e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // Basic AudioSampleEntry size.
923e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
924e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
925e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
9269a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(
927e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
928e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
929e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
930e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
931e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
932e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint16_t num_channels = U16_AT(&buffer[16]);
933e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
934d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber            uint16_t sample_size = U16_AT(&buffer[18]);
935d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber            uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
936d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber
937e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber            if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB,
938d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber                            FourCC2MIME(chunk_type))) {
939d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber                // AMR NB audio is always mono, 8kHz
940d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber                num_channels = 1;
941d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber                sample_rate = 8000;
942d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber            } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB,
943e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber                               FourCC2MIME(chunk_type))) {
944d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber                // AMR WB audio is always mono, 16kHz
945e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                num_channels = 1;
946d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber                sample_rate = 16000;
947e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
948e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
949d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber#if 0
950d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber            printf("*** coding='%s' %d channels, size %d, rate %d\n",
951d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber                   chunk, num_channels, sample_size, sample_rate);
952d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber#endif
953e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
954e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
955e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
956e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
957e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
958b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong            off64_t stop_offset = *offset + chunk_size;
959e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset = data_offset + sizeof(buffer);
960e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            while (*offset < stop_offset) {
961e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                status_t err = parseChunk(offset, depth + 1);
962e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (err != OK) {
963e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return err;
964e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
965e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
9665ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
9675ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            if (*offset != stop_offset) {
9685ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                return ERROR_MALFORMED;
9695ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            }
970e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
971e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
972e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
973e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
974e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', '2', '6', '3'):
9750efdc95d59a51a130ce9d2515bcc9e2c01b52f14James Dong        case FOURCC('H', '2', '6', '3'):
9760efdc95d59a51a130ce9d2515bcc9e2c01b52f14James Dong        case FOURCC('h', '2', '6', '3'):
977e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
978e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
9791cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber            mHasVideo = true;
9801cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber
981e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t buffer[78];
982e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
983e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // Basic VideoSampleEntry size.
984e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
985e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
986e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
9879a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(
988e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
989e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
990e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
991e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
992e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
993e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint16_t width = U16_AT(&buffer[6 + 18]);
994e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint16_t height = U16_AT(&buffer[6 + 20]);
995e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
996c9e1c80f786667e264748bf2843dabdc2029c006James Dong            // The video sample is not stand-compliant if it has invalid dimension.
997c9e1c80f786667e264748bf2843dabdc2029c006James Dong            // Use some default width and height value, and
998c9e1c80f786667e264748bf2843dabdc2029c006James Dong            // let the decoder figure out the actual width and height (and thus
999c9e1c80f786667e264748bf2843dabdc2029c006James Dong            // be prepared for INFO_FOMRAT_CHANGED event).
1000c9e1c80f786667e264748bf2843dabdc2029c006James Dong            if (width == 0)  width  = 352;
1001c9e1c80f786667e264748bf2843dabdc2029c006James Dong            if (height == 0) height = 288;
1002c9e1c80f786667e264748bf2843dabdc2029c006James Dong
10032ea14e231945afb6581fa8f54015b33bc74a19e5Andreas Huber            // printf("*** coding='%s' width=%d height=%d\n",
10042ea14e231945afb6581fa8f54015b33bc74a19e5Andreas Huber            //        chunk, width, height);
1005e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1006e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
1007e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setInt32(kKeyWidth, width);
1008e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setInt32(kKeyHeight, height);
1009e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1010b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong            off64_t stop_offset = *offset + chunk_size;
1011e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset = data_offset + sizeof(buffer);
1012e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            while (*offset < stop_offset) {
1013e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                status_t err = parseChunk(offset, depth + 1);
1014e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (err != OK) {
1015e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return err;
1016e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
1017e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
10185ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
10195ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            if (*offset != stop_offset) {
10205ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                return ERROR_MALFORMED;
10215ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            }
1022e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
1023e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
1024e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1025e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 'c', 'o'):
1026e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('c', 'o', '6', '4'):
1027e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
1028e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            status_t err =
1029e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mLastTrack->sampleTable->setChunkOffsetParams(
1030e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        chunk_type, data_offset, chunk_data_size);
1031e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1032e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (err != OK) {
1033e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return err;
1034e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
1035e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1036e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
1037e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
1038e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
1039e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1040e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 's', 'c'):
1041e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
1042e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            status_t err =
1043e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mLastTrack->sampleTable->setSampleToChunkParams(
1044e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, chunk_data_size);
1045e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1046e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (err != OK) {
1047e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return err;
1048e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
1049e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1050e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
1051e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
1052e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
1053e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1054e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 's', 'z'):
1055e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 'z', '2'):
1056e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
1057e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            status_t err =
1058e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mLastTrack->sampleTable->setSampleSizeParams(
1059e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        chunk_type, data_offset, chunk_data_size);
1060e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1061e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (err != OK) {
1062e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return err;
1063e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
1064e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
10651bceff916a72246fa208605d50615823d7f1688bAndreas Huber            size_t max_size;
1066d7f2225e7455f5e0da32f409a528ced283631c5dAndreas Huber            err = mLastTrack->sampleTable->getMaxSampleSize(&max_size);
1067d7f2225e7455f5e0da32f409a528ced283631c5dAndreas Huber
1068d7f2225e7455f5e0da32f409a528ced283631c5dAndreas Huber            if (err != OK) {
1069d7f2225e7455f5e0da32f409a528ced283631c5dAndreas Huber                return err;
1070d7f2225e7455f5e0da32f409a528ced283631c5dAndreas Huber            }
10711bceff916a72246fa208605d50615823d7f1688bAndreas Huber
10721bceff916a72246fa208605d50615823d7f1688bAndreas Huber            // Assume that a given buffer only contains at most 10 fragments,
10731bceff916a72246fa208605d50615823d7f1688bAndreas Huber            // each fragment originally prefixed with a 2 byte length will
10741bceff916a72246fa208605d50615823d7f1688bAndreas Huber            // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
10751bceff916a72246fa208605d50615823d7f1688bAndreas Huber            // and thus will grow by 2 bytes per fragment.
10761bceff916a72246fa208605d50615823d7f1688bAndreas Huber            mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
1077e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
1078cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong
1079cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong            // Calculate average frame rate.
1080cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong            const char *mime;
1081cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong            CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1082cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong            if (!strncasecmp("video/", mime, 6)) {
1083cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong                size_t nSamples = mLastTrack->sampleTable->countSamples();
1084cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong                int64_t durationUs;
1085cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong                if (mLastTrack->meta->findInt64(kKeyDuration, &durationUs)) {
1086cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong                    if (durationUs > 0) {
1087cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong                        int32_t frameRate = (nSamples * 1000000LL +
1088cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong                                    (durationUs >> 1)) / durationUs;
1089cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong                        mLastTrack->meta->setInt32(kKeyFrameRate, frameRate);
1090cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong                    }
1091cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong                }
1092cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong            }
1093cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong
1094e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
1095e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
1096e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1097e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 't', 's'):
1098e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
1099e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            status_t err =
1100e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mLastTrack->sampleTable->setTimeToSampleParams(
1101e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, chunk_data_size);
1102e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1103e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (err != OK) {
1104e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return err;
1105e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
1106e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1107e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
1108e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
1109e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
1110e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1111bd352c3cdc6a8682dae58a5108c82a303be05274Andreas Huber        case FOURCC('c', 't', 't', 's'):
1112bd352c3cdc6a8682dae58a5108c82a303be05274Andreas Huber        {
1113bd352c3cdc6a8682dae58a5108c82a303be05274Andreas Huber            status_t err =
1114bd352c3cdc6a8682dae58a5108c82a303be05274Andreas Huber                mLastTrack->sampleTable->setCompositionTimeToSampleParams(
1115bd352c3cdc6a8682dae58a5108c82a303be05274Andreas Huber                        data_offset, chunk_data_size);
1116bd352c3cdc6a8682dae58a5108c82a303be05274Andreas Huber
1117bd352c3cdc6a8682dae58a5108c82a303be05274Andreas Huber            if (err != OK) {
1118bd352c3cdc6a8682dae58a5108c82a303be05274Andreas Huber                return err;
1119bd352c3cdc6a8682dae58a5108c82a303be05274Andreas Huber            }
1120bd352c3cdc6a8682dae58a5108c82a303be05274Andreas Huber
1121bd352c3cdc6a8682dae58a5108c82a303be05274Andreas Huber            *offset += chunk_size;
1122bd352c3cdc6a8682dae58a5108c82a303be05274Andreas Huber            break;
1123bd352c3cdc6a8682dae58a5108c82a303be05274Andreas Huber        }
1124bd352c3cdc6a8682dae58a5108c82a303be05274Andreas Huber
1125e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 's', 's'):
1126e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
1127e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            status_t err =
1128e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mLastTrack->sampleTable->setSyncSampleParams(
1129e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, chunk_data_size);
1130e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1131e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (err != OK) {
1132e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return err;
1133e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
1134e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1135e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
1136e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
1137e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
1138e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1139e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('e', 's', 'd', 's'):
1140e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
1141e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size < 4) {
1142e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
1143e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
1144e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1145e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t buffer[256];
1146b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong            if (chunk_data_size > (off64_t)sizeof(buffer)) {
1147e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
1148e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
1149e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
11509a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(
1151e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
1152e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
1153e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
1154e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1155e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (U32_AT(buffer) != 0) {
1156e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // Should be version 0, flags 0.
1157e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
1158e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
1159e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1160e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setData(
1161e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
1162e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1163d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber            if (mPath.size() >= 2
1164d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                    && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) {
1165d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                // Information from the ESDS must be relied on for proper
1166d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                // setup of sample rate and channel count for MPEG4 Audio.
1167d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                // The generic header appears to only contain generic
1168d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                // information...
1169d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1170d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio(
1171d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                        &buffer[4], chunk_data_size - 4);
1172d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1173d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                if (err != OK) {
1174d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                    return err;
1175d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                }
1176d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber            }
1177d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1178e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
1179e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
1180e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
1181e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1182e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('a', 'v', 'c', 'C'):
1183e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
1184e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            char buffer[256];
1185b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong            if (chunk_data_size > (off64_t)sizeof(buffer)) {
1186e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
1187e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
1188e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
11899a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(
1190e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
1191e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
1192e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
1193e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1194e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setData(
1195e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    kKeyAVCC, kTypeAVCC, buffer, chunk_data_size);
1196e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1197e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
1198e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
1199e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
1200e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1201fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong        case FOURCC('d', '2', '6', '3'):
1202fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong        {
1203bc5f1f5c815e6a158859c031fa7bb0fd68d973b9James Dong            /*
1204bc5f1f5c815e6a158859c031fa7bb0fd68d973b9James Dong             * d263 contains a fixed 7 bytes part:
1205bc5f1f5c815e6a158859c031fa7bb0fd68d973b9James Dong             *   vendor - 4 bytes
1206bc5f1f5c815e6a158859c031fa7bb0fd68d973b9James Dong             *   version - 1 byte
1207bc5f1f5c815e6a158859c031fa7bb0fd68d973b9James Dong             *   level - 1 byte
1208bc5f1f5c815e6a158859c031fa7bb0fd68d973b9James Dong             *   profile - 1 byte
1209bc5f1f5c815e6a158859c031fa7bb0fd68d973b9James Dong             * optionally, "d263" box itself may contain a 16-byte
1210bc5f1f5c815e6a158859c031fa7bb0fd68d973b9James Dong             * bit rate box (bitr)
1211bc5f1f5c815e6a158859c031fa7bb0fd68d973b9James Dong             *   average bit rate - 4 bytes
1212bc5f1f5c815e6a158859c031fa7bb0fd68d973b9James Dong             *   max bit rate - 4 bytes
1213bc5f1f5c815e6a158859c031fa7bb0fd68d973b9James Dong             */
1214bc5f1f5c815e6a158859c031fa7bb0fd68d973b9James Dong            char buffer[23];
1215bc5f1f5c815e6a158859c031fa7bb0fd68d973b9James Dong            if (chunk_data_size != 7 &&
1216bc5f1f5c815e6a158859c031fa7bb0fd68d973b9James Dong                chunk_data_size != 23) {
1217fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong                LOGE("Incorrect D263 box size %lld", chunk_data_size);
1218fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong                return ERROR_MALFORMED;
1219fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong            }
1220fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong
1221fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong            if (mDataSource->readAt(
1222fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong                    data_offset, buffer, chunk_data_size) < chunk_data_size) {
1223fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong                return ERROR_IO;
1224fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong            }
1225fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong
1226fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong            mLastTrack->meta->setData(kKeyD263, kTypeD263, buffer, chunk_data_size);
1227fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong
1228fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong            *offset += chunk_size;
1229fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong            break;
1230fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong        }
1231fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong
1232c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('m', 'e', 't', 'a'):
1233c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1234c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            uint8_t buffer[4];
1235b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong            if (chunk_data_size < (off64_t)sizeof(buffer)) {
12365ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                return ERROR_MALFORMED;
12375ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            }
12385ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
1239c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (mDataSource->readAt(
1240c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                        data_offset, buffer, 4) < 4) {
1241c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                return ERROR_IO;
1242c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
1243c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1244c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (U32_AT(buffer) != 0) {
1245c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                // Should be version 0, flags 0.
1246dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber
1247dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber                // If it's not, let's assume this is one of those
1248dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber                // apparently malformed chunks that don't have flags
1249dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber                // and completely different semantics than what's
1250dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber                // in the MPEG4 specs and skip it.
1251dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber                *offset += chunk_size;
1252dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber                return OK;
1253c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
1254c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1255b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong            off64_t stop_offset = *offset + chunk_size;
1256c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            *offset = data_offset + sizeof(buffer);
1257c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            while (*offset < stop_offset) {
1258c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                status_t err = parseChunk(offset, depth + 1);
1259c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                if (err != OK) {
1260c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                    return err;
1261c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                }
1262c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
12635ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
12645ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            if (*offset != stop_offset) {
12655ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                return ERROR_MALFORMED;
12665ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            }
1267c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1268c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1269c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1270c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('d', 'a', 't', 'a'):
1271c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1272c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (mPath.size() == 6 && underMetaDataPath(mPath)) {
1273c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                status_t err = parseMetaData(data_offset, chunk_data_size);
1274c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1275c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                if (err != OK) {
1276c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                    return err;
1277c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                }
1278c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
1279c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1280c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            *offset += chunk_size;
1281c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1282c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1283c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1284c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('m', 'v', 'h', 'd'):
1285c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1286c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (chunk_data_size < 12) {
1287c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                return ERROR_MALFORMED;
1288c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
1289c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1290c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            uint8_t header[12];
1291c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (mDataSource->readAt(
1292c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                        data_offset, header, sizeof(header))
1293c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                    < (ssize_t)sizeof(header)) {
1294c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                return ERROR_IO;
1295c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
1296c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1297c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            int64_t creationTime;
1298c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (header[0] == 1) {
1299c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                creationTime = U64_AT(&header[4]);
13005ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            } else if (header[0] != 0) {
13015ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                return ERROR_MALFORMED;
1302c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            } else {
1303c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                creationTime = U32_AT(&header[4]);
1304c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
1305c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1306c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            String8 s;
1307c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            convertTimeToDate(creationTime, &s);
1308c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1309c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            mFileMetaData->setCString(kKeyDate, s.string());
1310c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1311c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            *offset += chunk_size;
1312c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1313c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1314c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1315d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        case FOURCC('m', 'd', 'a', 't'):
1316d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        {
1317d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            if (!mIsDrm) {
1318d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                *offset += chunk_size;
1319d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                break;
1320d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            }
1321d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
1322d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            if (chunk_size < 8) {
1323d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                return ERROR_MALFORMED;
1324d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            }
1325d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
1326d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            return parseDrmSINF(offset, data_offset);
1327d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        }
1328d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
1329eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang        case FOURCC('h', 'd', 'l', 'r'):
1330eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang        {
1331eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang            uint32_t buffer;
1332eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang            if (mDataSource->readAt(
1333eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang                        data_offset + 8, &buffer, 4) < 4) {
1334eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang                return ERROR_IO;
1335eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang            }
1336eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang
1337eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang            uint32_t type = ntohl(buffer);
1338eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang            // For the 3GPP file format, the handler-type within the 'hdlr' box
1339eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang            // shall be 'text'
1340eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang            if (type == FOURCC('t', 'e', 'x', 't')) {
1341eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang                mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP);
1342eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang            }
1343eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang
1344eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang            *offset += chunk_size;
1345eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang            break;
1346eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang        }
1347eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang
1348c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang        case FOURCC('t', 'x', '3', 'g'):
1349c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang        {
1350eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang            uint32_t type;
1351eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang            const void *data;
1352eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang            size_t size = 0;
1353eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang            if (!mLastTrack->meta->findData(
1354eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang                    kKeyTextFormatData, &type, &data, &size)) {
1355eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang                size = 0;
1356eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang            }
1357eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang
1358eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang            uint8_t *buffer = new uint8_t[size + chunk_size];
1359eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang
1360eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang            if (size > 0) {
1361eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang                memcpy(buffer, data, size);
1362eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang            }
1363eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang
1364eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang            if ((size_t)(mDataSource->readAt(*offset, buffer + size, chunk_size))
1365eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang                    < chunk_size) {
1366eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang                delete[] buffer;
1367eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang                buffer = NULL;
1368eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang
1369eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang                return ERROR_IO;
1370eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang            }
1371eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang
1372eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang            mLastTrack->meta->setData(
1373eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang                    kKeyTextFormatData, 0, buffer, size + chunk_size);
1374eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang
1375eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang            delete[] buffer;
1376c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang
1377c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang            *offset += chunk_size;
1378c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang            break;
1379c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang        }
1380c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang
1381e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong        case FOURCC('c', 'o', 'v', 'r'):
1382e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong        {
1383e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong            if (mFileMetaData != NULL) {
1384e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong                LOGV("chunk_data_size = %lld and data_offset = %lld",
1385e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong                        chunk_data_size, data_offset);
1386e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong                uint8_t *buffer = new uint8_t[chunk_data_size + 1];
1387e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong                if (mDataSource->readAt(
1388e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong                    data_offset, buffer, chunk_data_size) != (ssize_t)chunk_data_size) {
1389e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong                    delete[] buffer;
1390e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong                    buffer = NULL;
1391e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong
1392e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong                    return ERROR_IO;
1393e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong                }
1394e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong                const int kSkipBytesOfDataBox = 16;
1395e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong                mFileMetaData->setData(
1396e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong                    kKeyAlbumArt, MetaData::TYPE_NONE,
1397e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong                    buffer + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox);
1398e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong            }
1399e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong
1400e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong            *offset += chunk_size;
1401e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong            break;
1402e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong        }
1403e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong
1404e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        default:
1405e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
1406e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
1407e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
1408e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
1409e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1410e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1411e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return OK;
1412e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1413e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1414940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huberstatus_t MPEG4Extractor::parseTrackHeader(
1415b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong        off64_t data_offset, off64_t data_size) {
1416940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    if (data_size < 4) {
1417940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber        return ERROR_MALFORMED;
1418940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    }
1419940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber
1420940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    uint8_t version;
1421940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    if (mDataSource->readAt(data_offset, &version, 1) < 1) {
1422940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber        return ERROR_IO;
1423940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    }
1424940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber
1425940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    size_t dynSize = (version == 1) ? 36 : 24;
1426940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber
1427940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    uint8_t buffer[36 + 60];
1428940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber
1429b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong    if (data_size != (off64_t)dynSize + 60) {
1430940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber        return ERROR_MALFORMED;
1431940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    }
1432940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber
1433940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    if (mDataSource->readAt(
1434940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber                data_offset, buffer, data_size) < (ssize_t)data_size) {
1435940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber        return ERROR_IO;
1436940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    }
1437940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber
1438940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    uint64_t ctime, mtime, duration;
1439940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    int32_t id;
1440940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber
1441940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    if (version == 1) {
1442940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber        ctime = U64_AT(&buffer[4]);
1443940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber        mtime = U64_AT(&buffer[12]);
1444940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber        id = U32_AT(&buffer[20]);
1445940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber        duration = U64_AT(&buffer[28]);
1446940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    } else {
1447940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber        CHECK_EQ((unsigned)version, 0u);
1448940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber
1449940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber        ctime = U32_AT(&buffer[4]);
1450940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber        mtime = U32_AT(&buffer[8]);
1451940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber        id = U32_AT(&buffer[12]);
1452940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber        duration = U32_AT(&buffer[20]);
1453940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    }
1454940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber
1455940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    mLastTrack->meta->setInt32(kKeyTrackID, id);
1456940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber
1457940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    size_t matrixOffset = dynSize + 16;
1458940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    int32_t a00 = U32_AT(&buffer[matrixOffset]);
1459940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    int32_t a01 = U32_AT(&buffer[matrixOffset + 4]);
1460940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    int32_t dx = U32_AT(&buffer[matrixOffset + 8]);
1461940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    int32_t a10 = U32_AT(&buffer[matrixOffset + 12]);
1462940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    int32_t a11 = U32_AT(&buffer[matrixOffset + 16]);
1463940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    int32_t dy = U32_AT(&buffer[matrixOffset + 20]);
1464940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber
1465940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber#if 0
1466940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    LOGI("x' = %.2f * x + %.2f * y + %.2f",
1467940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber         a00 / 65536.0f, a01 / 65536.0f, dx / 65536.0f);
1468940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    LOGI("y' = %.2f * x + %.2f * y + %.2f",
1469940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber         a10 / 65536.0f, a11 / 65536.0f, dy / 65536.0f);
1470940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber#endif
1471940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber
1472940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    uint32_t rotationDegrees;
1473940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber
1474940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    static const int32_t kFixedOne = 0x10000;
1475940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    if (a00 == kFixedOne && a01 == 0 && a10 == 0 && a11 == kFixedOne) {
1476940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber        // Identity, no rotation
1477940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber        rotationDegrees = 0;
1478940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    } else if (a00 == 0 && a01 == kFixedOne && a10 == -kFixedOne && a11 == 0) {
1479940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber        rotationDegrees = 90;
1480940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    } else if (a00 == 0 && a01 == -kFixedOne && a10 == kFixedOne && a11 == 0) {
1481940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber        rotationDegrees = 270;
1482940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    } else if (a00 == -kFixedOne && a01 == 0 && a10 == 0 && a11 == -kFixedOne) {
1483940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber        rotationDegrees = 180;
1484940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    } else {
1485940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber        LOGW("We only support 0,90,180,270 degree rotation matrices");
1486940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber        rotationDegrees = 0;
1487940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    }
1488940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber
1489940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    if (rotationDegrees != 0) {
1490940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber        mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees);
1491940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    }
1492940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber
149308adfd29ae3634b554cfe184ab82f112ef934d7bJames Dong    // Handle presentation display size, which could be different
149408adfd29ae3634b554cfe184ab82f112ef934d7bJames Dong    // from the image size indicated by kKeyWidth and kKeyHeight.
1495940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    uint32_t width = U32_AT(&buffer[dynSize + 52]);
1496940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    uint32_t height = U32_AT(&buffer[dynSize + 56]);
149708adfd29ae3634b554cfe184ab82f112ef934d7bJames Dong    mLastTrack->meta->setInt32(kKeyDisplayWidth, width >> 16);
149808adfd29ae3634b554cfe184ab82f112ef934d7bJames Dong    mLastTrack->meta->setInt32(kKeyDisplayHeight, height >> 16);
1499940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber
1500940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber    return OK;
1501940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber}
1502940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber
1503b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dongstatus_t MPEG4Extractor::parseMetaData(off64_t offset, size_t size) {
1504c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    if (size < 4) {
1505c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        return ERROR_MALFORMED;
1506c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    }
1507c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1508c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    uint8_t *buffer = new uint8_t[size + 1];
1509c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    if (mDataSource->readAt(
1510c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                offset, buffer, size) != (ssize_t)size) {
1511c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        delete[] buffer;
1512c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        buffer = NULL;
1513c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1514c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        return ERROR_IO;
1515c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    }
1516c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1517c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    uint32_t flags = U32_AT(buffer);
1518c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1519c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    uint32_t metadataKey = 0;
1520c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    switch (mPath[4]) {
1521c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC(0xa9, 'a', 'l', 'b'):
1522c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1523c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            metadataKey = kKeyAlbum;
1524c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1525c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1526c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC(0xa9, 'A', 'R', 'T'):
1527c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1528c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            metadataKey = kKeyArtist;
1529c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1530c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1531c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen        case FOURCC('a', 'A', 'R', 'T'):
1532c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen        {
1533c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen            metadataKey = kKeyAlbumArtist;
1534c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen            break;
1535c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen        }
1536c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC(0xa9, 'd', 'a', 'y'):
1537c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1538c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            metadataKey = kKeyYear;
1539c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1540c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1541c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC(0xa9, 'n', 'a', 'm'):
1542c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1543c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            metadataKey = kKeyTitle;
1544c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1545c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1546c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC(0xa9, 'w', 'r', 't'):
1547c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1548c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            metadataKey = kKeyWriter;
1549c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1550c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1551c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('c', 'o', 'v', 'r'):
1552c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1553c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            metadataKey = kKeyAlbumArt;
1554c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1555c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1556c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('g', 'n', 'r', 'e'):
1557c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1558c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            metadataKey = kKeyGenre;
1559c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1560c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1561fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen        case FOURCC(0xa9, 'g', 'e', 'n'):
1562fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen        {
1563fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen            metadataKey = kKeyGenre;
1564fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen            break;
1565fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen        }
1566ee35aff74494e6c0b718e219427af6a6c573b928Marco Nelissen        case FOURCC('c', 'p', 'i', 'l'):
1567ee35aff74494e6c0b718e219427af6a6c573b928Marco Nelissen        {
1568ee35aff74494e6c0b718e219427af6a6c573b928Marco Nelissen            if (size == 9 && flags == 21) {
1569ee35aff74494e6c0b718e219427af6a6c573b928Marco Nelissen                char tmp[16];
1570ee35aff74494e6c0b718e219427af6a6c573b928Marco Nelissen                sprintf(tmp, "%d",
1571ee35aff74494e6c0b718e219427af6a6c573b928Marco Nelissen                        (int)buffer[size - 1]);
1572ee35aff74494e6c0b718e219427af6a6c573b928Marco Nelissen
1573ee35aff74494e6c0b718e219427af6a6c573b928Marco Nelissen                mFileMetaData->setCString(kKeyCompilation, tmp);
1574ee35aff74494e6c0b718e219427af6a6c573b928Marco Nelissen            }
1575ee35aff74494e6c0b718e219427af6a6c573b928Marco Nelissen            break;
1576ee35aff74494e6c0b718e219427af6a6c573b928Marco Nelissen        }
1577c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('t', 'r', 'k', 'n'):
1578c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1579c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (size == 16 && flags == 0) {
1580c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                char tmp[16];
1581c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                sprintf(tmp, "%d/%d",
1582c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                        (int)buffer[size - 5], (int)buffer[size - 3]);
1583c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1584c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
1585c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
1586c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1587c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1588fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen        case FOURCC('d', 'i', 's', 'k'):
1589fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen        {
1590fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen            if (size == 14 && flags == 0) {
1591fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                char tmp[16];
1592fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                sprintf(tmp, "%d/%d",
1593fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                        (int)buffer[size - 3], (int)buffer[size - 1]);
1594fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen
1595fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                mFileMetaData->setCString(kKeyDiscNumber, tmp);
1596fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen            }
1597fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen            break;
1598fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen        }
1599fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen
1600c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        default:
1601c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1602c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    }
1603c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1604c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    if (size >= 8 && metadataKey) {
1605c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        if (metadataKey == kKeyAlbumArt) {
1606c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            mFileMetaData->setData(
1607c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                    kKeyAlbumArt, MetaData::TYPE_NONE,
1608c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                    buffer + 8, size - 8);
1609c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        } else if (metadataKey == kKeyGenre) {
1610c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (flags == 0) {
1611fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                // uint8_t genre code, iTunes genre codes are
1612fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                // the standard id3 codes, except they start
1613fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                // at 1 instead of 0 (e.g. Pop is 14, not 13)
1614fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                // We use standard id3 numbering, so subtract 1.
1615fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                int genrecode = (int)buffer[size - 1];
1616fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                genrecode--;
1617fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                if (genrecode < 0) {
1618fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                    genrecode = 255; // reserved for 'unknown genre'
1619fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                }
1620c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                char genre[10];
1621fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                sprintf(genre, "%d", genrecode);
1622c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1623c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                mFileMetaData->setCString(metadataKey, genre);
1624fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen            } else if (flags == 1) {
1625fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                // custom genre string
1626fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                buffer[size] = '\0';
1627fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen
1628fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                mFileMetaData->setCString(
1629fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                        metadataKey, (const char *)buffer + 8);
1630c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
1631c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        } else {
1632c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            buffer[size] = '\0';
1633c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1634c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            mFileMetaData->setCString(
1635c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                    metadataKey, (const char *)buffer + 8);
1636c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1637c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    }
1638c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1639c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    delete[] buffer;
1640c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    buffer = NULL;
1641c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1642c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    return OK;
1643c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber}
1644c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1645be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
1646e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    status_t err;
1647e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if ((err = readMetaData()) != OK) {
1648be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber        return NULL;
1649e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1650e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1651e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    Track *track = mFirstTrack;
1652e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    while (index > 0) {
1653e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (track == NULL) {
1654be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber            return NULL;
1655e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
1656e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1657e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        track = track->next;
1658e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        --index;
1659e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1660e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
16612a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber    if (track == NULL) {
16622a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber        return NULL;
16632a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber    }
16642a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber
1665be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber    return new MPEG4Source(
1666fa8de752507feaca695123911915070c1ce463b2Andreas Huber            track->meta, mDataSource, track->timescale, track->sampleTable);
1667e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1668e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
16695ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber// static
16705ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huberstatus_t MPEG4Extractor::verifyTrack(Track *track) {
16715ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber    const char *mime;
16725ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber    CHECK(track->meta->findCString(kKeyMIMEType, &mime));
16735ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
16745ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber    uint32_t type;
16755ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber    const void *data;
16765ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber    size_t size;
16775ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
16785ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber        if (!track->meta->findData(kKeyAVCC, &type, &data, &size)
16795ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                || type != kTypeAVCC) {
16805ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            return ERROR_MALFORMED;
16815ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber        }
16825ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
16835ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
16845ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber        if (!track->meta->findData(kKeyESDS, &type, &data, &size)
16855ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                || type != kTypeESDS) {
16865ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            return ERROR_MALFORMED;
16875ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber        }
16885ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber    }
16895ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
1690987cb2ed4a3aebdb624088c38981b2409ab8f6b1Andreas Huber    if (!track->sampleTable->isValid()) {
1691987cb2ed4a3aebdb624088c38981b2409ab8f6b1Andreas Huber        // Make sure we have all the metadata we need.
1692987cb2ed4a3aebdb624088c38981b2409ab8f6b1Andreas Huber        return ERROR_MALFORMED;
1693987cb2ed4a3aebdb624088c38981b2409ab8f6b1Andreas Huber    }
1694987cb2ed4a3aebdb624088c38981b2409ab8f6b1Andreas Huber
16955ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber    return OK;
16965ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber}
16975ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
1698d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huberstatus_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(
1699d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        const void *esds_data, size_t esds_size) {
1700d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    ESDS esds(esds_data, esds_size);
1701d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber
1702d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber    uint8_t objectTypeIndication;
1703d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber    if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) {
1704d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber        return ERROR_MALFORMED;
1705d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber    }
1706d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber
1707d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber    if (objectTypeIndication == 0xe1) {
1708d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber        // This isn't MPEG4 audio at all, it's QCELP 14k...
1709d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber        mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
1710d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber        return OK;
1711d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber    }
1712d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber
1713e883d317d51733145b880ce11c610f0287fba447James Dong    if (objectTypeIndication  == 0x6b) {
1714e883d317d51733145b880ce11c610f0287fba447James Dong        // The media subtype is MP3 audio
1715e883d317d51733145b880ce11c610f0287fba447James Dong        // Our software MP3 audio decoder may not be able to handle
1716e883d317d51733145b880ce11c610f0287fba447James Dong        // packetized MP3 audio; for now, lets just return ERROR_UNSUPPORTED
1717e883d317d51733145b880ce11c610f0287fba447James Dong        LOGE("MP3 track in MP4/3GPP file is not supported");
1718e883d317d51733145b880ce11c610f0287fba447James Dong        return ERROR_UNSUPPORTED;
1719e883d317d51733145b880ce11c610f0287fba447James Dong    }
1720e883d317d51733145b880ce11c610f0287fba447James Dong
1721d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    const uint8_t *csd;
1722d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    size_t csd_size;
1723d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    if (esds.getCodecSpecificInfo(
1724d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                (const void **)&csd, &csd_size) != OK) {
1725d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        return ERROR_MALFORMED;
1726d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    }
1727d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1728d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber#if 0
1729d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    printf("ESD of size %d\n", csd_size);
1730d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    hexdump(csd, csd_size);
1731d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber#endif
1732d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
173308c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber    if (csd_size == 0) {
173408c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber        // There's no further information, i.e. no codec specific data
173508c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber        // Let's assume that the information provided in the mpeg4 headers
173608c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber        // is accurate and hope for the best.
173708c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber
173808c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber        return OK;
173908c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber    }
174008c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber
1741d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    if (csd_size < 2) {
1742d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        return ERROR_MALFORMED;
1743d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    }
1744d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1745d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    uint32_t objectType = csd[0] >> 3;
1746d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1747d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    if (objectType == 31) {
1748d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        return ERROR_UNSUPPORTED;
1749d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    }
1750d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1751d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    uint32_t freqIndex = (csd[0] & 7) << 1 | (csd[1] >> 7);
1752d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    int32_t sampleRate = 0;
1753d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    int32_t numChannels = 0;
1754d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    if (freqIndex == 15) {
1755d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        if (csd_size < 5) {
1756d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber            return ERROR_MALFORMED;
1757d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        }
1758d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1759d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        sampleRate = (csd[1] & 0x7f) << 17
1760d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                        | csd[2] << 9
1761d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                        | csd[3] << 1
1762d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                        | (csd[4] >> 7);
1763d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1764d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        numChannels = (csd[4] >> 3) & 15;
1765d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    } else {
1766cc14a8393b92cd1ed6cba74829396045605ab211Andreas Huber        static uint32_t kSamplingRate[] = {
1767cc14a8393b92cd1ed6cba74829396045605ab211Andreas Huber            96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
1768cc14a8393b92cd1ed6cba74829396045605ab211Andreas Huber            16000, 12000, 11025, 8000, 7350
1769cc14a8393b92cd1ed6cba74829396045605ab211Andreas Huber        };
1770d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1771d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        if (freqIndex == 13 || freqIndex == 14) {
1772d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber            return ERROR_MALFORMED;
1773d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        }
1774d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1775d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        sampleRate = kSamplingRate[freqIndex];
1776d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        numChannels = (csd[1] >> 3) & 15;
1777d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    }
1778d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1779d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    if (numChannels == 0) {
1780d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        return ERROR_UNSUPPORTED;
1781d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    }
1782d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1783d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    int32_t prevSampleRate;
1784d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));
1785d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1786d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    if (prevSampleRate != sampleRate) {
17874a9375ef2a06fc36ec308835ef9e7e4eea2ba69fAndreas Huber        LOGV("mpeg4 audio sample rate different from previous setting. "
1788d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber             "was: %d, now: %d", prevSampleRate, sampleRate);
1789d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    }
1790d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1791d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
1792d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1793d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    int32_t prevChannelCount;
1794d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount));
1795d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1796d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    if (prevChannelCount != numChannels) {
17974a9375ef2a06fc36ec308835ef9e7e4eea2ba69fAndreas Huber        LOGV("mpeg4 audio channel count different from previous setting. "
1798d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber             "was: %d, now: %d", prevChannelCount, numChannels);
1799d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    }
1800d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1801d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    mLastTrack->meta->setInt32(kKeyChannelCount, numChannels);
1802d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1803d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    return OK;
1804d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber}
1805d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1806e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber////////////////////////////////////////////////////////////////////////////////
1807e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1808e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberMPEG4Source::MPEG4Source(
1809e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        const sp<MetaData> &format,
1810be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber        const sp<DataSource> &dataSource,
1811fa8de752507feaca695123911915070c1ce463b2Andreas Huber        int32_t timeScale,
1812be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber        const sp<SampleTable> &sampleTable)
1813e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    : mFormat(format),
1814e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mDataSource(dataSource),
1815fa8de752507feaca695123911915070c1ce463b2Andreas Huber      mTimescale(timeScale),
1816e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mSampleTable(sampleTable),
1817e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mCurrentSampleIndex(0),
1818e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mIsAVC(false),
1819db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber      mNALLengthSize(0),
1820e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mStarted(false),
1821e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mGroup(NULL),
1822e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mBuffer(NULL),
18234f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber      mWantsNALFragments(false),
18248a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber      mSrcBuffer(NULL) {
1825e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    const char *mime;
1826e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    bool success = mFormat->findCString(kKeyMIMEType, &mime);
18274f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    CHECK(success);
1828e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1829e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber    mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
1830db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
1831db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    if (mIsAVC) {
1832db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        uint32_t type;
1833db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        const void *data;
1834db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        size_t size;
1835db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        CHECK(format->findData(kKeyAVCC, &type, &data, &size));
1836db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
1837db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        const uint8_t *ptr = (const uint8_t *)data;
1838db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
1839db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        CHECK(size >= 7);
1840940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber        CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
1841db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
1842db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        // The number of bytes used to encode the length of a NAL unit.
1843db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        mNALLengthSize = 1 + (ptr[4] & 3);
1844db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    }
1845e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1846e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1847e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberMPEG4Source::~MPEG4Source() {
1848e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (mStarted) {
1849e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        stop();
1850e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1851e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1852e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1853e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Source::start(MetaData *params) {
1854ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber    Mutex::Autolock autoLock(mLock);
1855ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber
18564f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    CHECK(!mStarted);
1857e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1858e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    int32_t val;
18594f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    if (params && params->findInt32(kKeyWantsNALFragments, &val)
1860e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        && val != 0) {
18614f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        mWantsNALFragments = true;
1862e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    } else {
18634f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        mWantsNALFragments = false;
1864e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1865e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1866e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mGroup = new MediaBufferGroup;
1867e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
18681bceff916a72246fa208605d50615823d7f1688bAndreas Huber    int32_t max_size;
18691bceff916a72246fa208605d50615823d7f1688bAndreas Huber    CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size));
1870e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
18711bceff916a72246fa208605d50615823d7f1688bAndreas Huber    mGroup->add_buffer(new MediaBuffer(max_size));
18728a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber
18738a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    mSrcBuffer = new uint8_t[max_size];
1874e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1875e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mStarted = true;
1876e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1877e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return OK;
1878e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1879e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1880e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Source::stop() {
1881ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber    Mutex::Autolock autoLock(mLock);
1882ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber
18834f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    CHECK(mStarted);
1884e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1885e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (mBuffer != NULL) {
1886e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        mBuffer->release();
1887e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        mBuffer = NULL;
1888e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1889e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
18908a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    delete[] mSrcBuffer;
18918a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    mSrcBuffer = NULL;
18928a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber
1893e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    delete mGroup;
1894e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mGroup = NULL;
1895e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1896e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mStarted = false;
1897e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mCurrentSampleIndex = 0;
1898e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1899e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return OK;
1900e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1901e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1902e46b7be812d68e49710b34048662cbf18e2a6550Andreas Hubersp<MetaData> MPEG4Source::getFormat() {
1903ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber    Mutex::Autolock autoLock(mLock);
1904ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber
1905e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return mFormat;
1906e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1907e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1908db5d662254f2ed788d32e2466739adc8d655c732Andreas Hubersize_t MPEG4Source::parseNALSize(const uint8_t *data) const {
1909db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    switch (mNALLengthSize) {
1910db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        case 1:
1911db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber            return *data;
1912db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        case 2:
1913db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber            return U16_AT(data);
1914db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        case 3:
1915db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber            return ((size_t)data[0] << 16) | U16_AT(&data[1]);
1916db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        case 4:
1917db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber            return U32_AT(data);
1918db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    }
1919db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
1920db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    // This cannot happen, mNALLengthSize springs to life by adding 1 to
1921db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    // a 2-bit integer.
1922db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    CHECK(!"Should not be here.");
1923db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
1924db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    return 0;
1925db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber}
1926db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
1927e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Source::read(
1928e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        MediaBuffer **out, const ReadOptions *options) {
1929ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber    Mutex::Autolock autoLock(mLock);
1930ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber
19314f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    CHECK(mStarted);
1932e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1933e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    *out = NULL;
1934e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
19356624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber    int64_t targetSampleTimeUs = -1;
19366624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber
1937e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    int64_t seekTimeUs;
19386624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber    ReadOptions::SeekMode mode;
19396624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
19406624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        uint32_t findFlags = 0;
19416624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        switch (mode) {
19426624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber            case ReadOptions::SEEK_PREVIOUS_SYNC:
19436624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber                findFlags = SampleTable::kFlagBefore;
19446624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber                break;
19456624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber            case ReadOptions::SEEK_NEXT_SYNC:
19466624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber                findFlags = SampleTable::kFlagAfter;
19476624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber                break;
19486624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber            case ReadOptions::SEEK_CLOSEST_SYNC:
19496624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber            case ReadOptions::SEEK_CLOSEST:
19506624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber                findFlags = SampleTable::kFlagClosest;
19516624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber                break;
19526624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber            default:
19536624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber                CHECK(!"Should not be here.");
19546624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber                break;
19556624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        }
19566624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber
1957e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        uint32_t sampleIndex;
19586624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        status_t err = mSampleTable->findSampleAtTime(
1959e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                seekTimeUs * mTimescale / 1000000,
19606624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber                &sampleIndex, findFlags);
19616624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber
19626624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
19636624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber            // We found the closest sample already, now we want the sync
19646624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber            // sample preceding it (or the sample itself of course), even
19656624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber            // if the subsequent sync sample is closer.
19666624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber            findFlags = SampleTable::kFlagBefore;
19676624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        }
19686624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber
19696624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        uint32_t syncSampleIndex;
19706624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        if (err == OK) {
19716624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber            err = mSampleTable->findSyncSampleNear(
19726624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber                    sampleIndex, &syncSampleIndex, findFlags);
19736624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        }
1974e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
197590ba107fcf36ce6df111a594b2cc27163b36793dAndreas Huber        uint32_t sampleTime;
197690ba107fcf36ce6df111a594b2cc27163b36793dAndreas Huber        if (err == OK) {
197790ba107fcf36ce6df111a594b2cc27163b36793dAndreas Huber            err = mSampleTable->getMetaDataForSample(
197890ba107fcf36ce6df111a594b2cc27163b36793dAndreas Huber                    sampleIndex, NULL, NULL, &sampleTime);
197990ba107fcf36ce6df111a594b2cc27163b36793dAndreas Huber        }
198090ba107fcf36ce6df111a594b2cc27163b36793dAndreas Huber
1981e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (err != OK) {
1982d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber            if (err == ERROR_OUT_OF_RANGE) {
1983d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber                // An attempt to seek past the end of the stream would
1984d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber                // normally cause this ERROR_OUT_OF_RANGE error. Propagating
1985d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber                // this all the way to the MediaPlayer would cause abnormal
1986d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber                // termination. Legacy behaviour appears to be to behave as if
1987d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber                // we had seeked to the end of stream, ending normally.
1988d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber                err = ERROR_END_OF_STREAM;
1989d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber            }
1990e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            return err;
1991e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
1992e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
19936624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
19946624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber            targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
19956624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        }
19966624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber
19976624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber#if 0
19986624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        uint32_t syncSampleTime;
19996624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
20006624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber                    syncSampleIndex, NULL, NULL, &syncSampleTime));
20016624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber
20026624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        LOGI("seek to time %lld us => sample at time %lld us, "
20036624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber             "sync sample at time %lld us",
20046624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber             seekTimeUs,
20056624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber             sampleTime * 1000000ll / mTimescale,
20066624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber             syncSampleTime * 1000000ll / mTimescale);
20076624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber#endif
20086624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber
20096624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        mCurrentSampleIndex = syncSampleIndex;
2010e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (mBuffer != NULL) {
2011e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mBuffer->release();
2012e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mBuffer = NULL;
2013e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
2014e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
2015e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        // fall through
2016e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
2017e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
2018b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong    off64_t offset;
20198a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    size_t size;
202044fdac0c62916ddcfac1fe887d867e7ff0cf446fAndreas Huber    uint32_t cts;
2021ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber    bool isSyncSample;
20224f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    bool newBuffer = false;
20234f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    if (mBuffer == NULL) {
20244f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        newBuffer = true;
2025e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
20261faa92a1e93f311e86dca483ed7702091137de66Andreas Huber        status_t err =
20271faa92a1e93f311e86dca483ed7702091137de66Andreas Huber            mSampleTable->getMetaDataForSample(
202844fdac0c62916ddcfac1fe887d867e7ff0cf446fAndreas Huber                    mCurrentSampleIndex, &offset, &size, &cts, &isSyncSample);
2029e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
20304f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        if (err != OK) {
20314f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            return err;
20324f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
20334f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
20344f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        err = mGroup->acquire_buffer(&mBuffer);
20351faa92a1e93f311e86dca483ed7702091137de66Andreas Huber
20364f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        if (err != OK) {
2037940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber            CHECK(mBuffer == NULL);
20384f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            return err;
20394f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
20408a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    }
2041e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
20424f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    if (!mIsAVC || mWantsNALFragments) {
20434f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        if (newBuffer) {
20444f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            ssize_t num_bytes_read =
20459a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
20464f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
20474f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            if (num_bytes_read < (ssize_t)size) {
20484f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber                mBuffer->release();
20494f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber                mBuffer = NULL;
20504f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
20514f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber                return ERROR_IO;
20524f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            }
20534f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
2054ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber            CHECK(mBuffer != NULL);
20554f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            mBuffer->set_range(0, size);
20564f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            mBuffer->meta_data()->clear();
2057fa8de752507feaca695123911915070c1ce463b2Andreas Huber            mBuffer->meta_data()->setInt64(
205844fdac0c62916ddcfac1fe887d867e7ff0cf446fAndreas Huber                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
20596624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber
20606624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber            if (targetSampleTimeUs >= 0) {
20616624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber                mBuffer->meta_data()->setInt64(
20626624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber                        kKeyTargetTime, targetSampleTimeUs);
20636624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber            }
20646624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber
2065ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber            if (isSyncSample) {
2066ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
2067ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber            }
2068ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber
20694f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            ++mCurrentSampleIndex;
20704f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
20714f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
20724f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        if (!mIsAVC) {
20734f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            *out = mBuffer;
20744f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            mBuffer = NULL;
20754f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
20764f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            return OK;
20774f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
20784f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
20794f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        // Each NAL unit is split up into its constituent fragments and
20804f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        // each one of them returned in its own buffer.
20814f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
2082db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        CHECK(mBuffer->range_length() >= mNALLengthSize);
20834f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
20844f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        const uint8_t *src =
20854f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
20864f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
2087db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        size_t nal_size = parseNALSize(src);
2088909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
2089909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber            LOGE("incomplete NAL unit.");
2090909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber
2091909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber            mBuffer->release();
2092909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber            mBuffer = NULL;
2093909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber
2094909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber            return ERROR_MALFORMED;
2095909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber        }
20964f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
20974f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        MediaBuffer *clone = mBuffer->clone();
2098ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber        CHECK(clone != NULL);
2099db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
21004f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
2101ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber        CHECK(mBuffer != NULL);
21024f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        mBuffer->set_range(
2103db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber                mBuffer->range_offset() + mNALLengthSize + nal_size,
2104db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber                mBuffer->range_length() - mNALLengthSize - nal_size);
21054f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
21064f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        if (mBuffer->range_length() == 0) {
21074f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            mBuffer->release();
21084f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            mBuffer = NULL;
21094f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
21104f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
21114f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        *out = clone;
21124f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
21134f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        return OK;
21144f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    } else {
21154f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        // Whole NAL units are returned but each fragment is prefixed by
21164f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        // the start code (0x00 00 00 01).
2117d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        ssize_t num_bytes_read = 0;
2118d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        int32_t drm = 0;
2119d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
2120d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        if (usesDRM) {
2121d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            num_bytes_read =
2122d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
2123d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        } else {
2124d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
2125d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        }
2126e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
2127e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (num_bytes_read < (ssize_t)size) {
2128e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mBuffer->release();
2129e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mBuffer = NULL;
2130e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
21314f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            return ERROR_IO;
2132e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
2133e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
2134d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        if (usesDRM) {
2135d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            CHECK(mBuffer != NULL);
2136d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            mBuffer->set_range(0, size);
2137db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
2138d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang        } else {
2139d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            uint8_t *dstData = (uint8_t *)mBuffer->data();
2140d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            size_t srcOffset = 0;
2141d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            size_t dstOffset = 0;
2142909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber
2143d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            while (srcOffset < size) {
214434d76acc4edb359a8639ddb6ce537b5156deb760James Dong                bool isMalFormed = (srcOffset + mNALLengthSize > size);
214534d76acc4edb359a8639ddb6ce537b5156deb760James Dong                size_t nalLength = 0;
214634d76acc4edb359a8639ddb6ce537b5156deb760James Dong                if (!isMalFormed) {
214734d76acc4edb359a8639ddb6ce537b5156deb760James Dong                    nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
214834d76acc4edb359a8639ddb6ce537b5156deb760James Dong                    srcOffset += mNALLengthSize;
214934d76acc4edb359a8639ddb6ce537b5156deb760James Dong                    isMalFormed = srcOffset + nalLength > size;
215034d76acc4edb359a8639ddb6ce537b5156deb760James Dong                }
2151909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber
215234d76acc4edb359a8639ddb6ce537b5156deb760James Dong                if (isMalFormed) {
215334d76acc4edb359a8639ddb6ce537b5156deb760James Dong                    LOGE("Video is malformed");
2154d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                    mBuffer->release();
2155d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                    mBuffer = NULL;
2156d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                    return ERROR_MALFORMED;
2157d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                }
2158d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang
2159d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                if (nalLength == 0) {
2160d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                    continue;
2161d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                }
21624f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
2163d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                CHECK(dstOffset + 4 <= mBuffer->size());
21644f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
2165d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                dstData[dstOffset++] = 0;
2166d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                dstData[dstOffset++] = 0;
2167d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                dstData[dstOffset++] = 0;
2168d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                dstData[dstOffset++] = 1;
2169d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
2170d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                srcOffset += nalLength;
2171d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang                dstOffset += nalLength;
2172d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            }
2173d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            CHECK_EQ(srcOffset, size);
2174d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            CHECK(mBuffer != NULL);
2175d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang            mBuffer->set_range(0, dstOffset);
21764f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
21774f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
2178e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        mBuffer->meta_data()->clear();
2179fa8de752507feaca695123911915070c1ce463b2Andreas Huber        mBuffer->meta_data()->setInt64(
218044fdac0c62916ddcfac1fe887d867e7ff0cf446fAndreas Huber                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
21816624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber
21826624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        if (targetSampleTimeUs >= 0) {
21836624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber            mBuffer->meta_data()->setInt64(
21846624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber                    kKeyTargetTime, targetSampleTimeUs);
21856624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        }
21866624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber
2187ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber        if (isSyncSample) {
2188ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
2189ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber        }
2190ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber
2191e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        ++mCurrentSampleIndex;
2192e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
2193e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        *out = mBuffer;
2194e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        mBuffer = NULL;
2195e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
2196e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return OK;
2197e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
2198e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
2199e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
2200f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas HuberMPEG4Extractor::Track *MPEG4Extractor::findTrackByMimePrefix(
2201f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber        const char *mimePrefix) {
2202f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber    for (Track *track = mFirstTrack; track != NULL; track = track->next) {
2203f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber        const char *mime;
2204f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber        if (track->meta != NULL
2205f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber                && track->meta->findCString(kKeyMIMEType, &mime)
2206f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber                && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) {
2207f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber            return track;
2208f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber        }
2209f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber    }
2210f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber
2211f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber    return NULL;
2212f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber}
2213f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber
2214261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huberstatic bool LegacySniffMPEG4(
2215be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
2216e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    uint8_t header[8];
2217e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
22189a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber    ssize_t n = source->readAt(4, header, sizeof(header));
2219e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (n < (ssize_t)sizeof(header)) {
2220e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return false;
2221e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
2222e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
2223e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
2224e1130662d0455231853e7d6880bb84d8547d7229James Dong        || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8)
2225e1130662d0455231853e7d6880bb84d8547d7229James Dong        || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8)
22266bce6d87b3fd98e68fb54328fb4dc8e40cd2c293Andreas Huber        || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
2227dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber        || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)
2228eea1eefeada90ec54488e1742e81e4226fc6ace5Andreas Huber        || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) {
2229e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber        *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
2230efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber        *confidence = 0.4;
2231e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
2232e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return true;
2233e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
2234e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
2235e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return false;
2236e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
2237e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
2238261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huberstatic bool isCompatibleBrand(uint32_t fourcc) {
2239261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    static const uint32_t kCompatibleBrands[] = {
2240261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        FOURCC('i', 's', 'o', 'm'),
2241261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        FOURCC('i', 's', 'o', '2'),
2242261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        FOURCC('a', 'v', 'c', '1'),
2243261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        FOURCC('3', 'g', 'p', '4'),
2244261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        FOURCC('m', 'p', '4', '1'),
2245261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        FOURCC('m', 'p', '4', '2'),
22465f3586e1ad21b011ff7d70ce26c2e0aa6d44a3ffJames Dong
22475f3586e1ad21b011ff7d70ce26c2e0aa6d44a3ffJames Dong        // Won't promise that the following file types can be played.
22485f3586e1ad21b011ff7d70ce26c2e0aa6d44a3ffJames Dong        // Just give these file types a chance.
22495f3586e1ad21b011ff7d70ce26c2e0aa6d44a3ffJames Dong        FOURCC('q', 't', ' ', ' '),  // Apple's QuickTime
22505f3586e1ad21b011ff7d70ce26c2e0aa6d44a3ffJames Dong        FOURCC('M', 'S', 'N', 'V'),  // Sony's PSP
2251708d908668b4c3d0ac2493dfc06385dfd8693dc9Andreas Huber
2252708d908668b4c3d0ac2493dfc06385dfd8693dc9Andreas Huber        FOURCC('3', 'g', '2', 'a'),  // 3GPP2
2253708d908668b4c3d0ac2493dfc06385dfd8693dc9Andreas Huber        FOURCC('3', 'g', '2', 'b'),
2254261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    };
2255261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
2256261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    for (size_t i = 0;
2257261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber         i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]);
2258261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber         ++i) {
2259261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        if (kCompatibleBrands[i] == fourcc) {
2260261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber            return true;
2261261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        }
2262261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    }
2263261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
2264261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    return false;
2265261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber}
2266261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
2267261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber// Attempt to actually parse the 'ftyp' atom and determine if a suitable
2268261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber// compatible brand is present.
2269261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huberstatic bool BetterSniffMPEG4(
2270261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
2271261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    uint8_t header[12];
2272261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    if (source->readAt(0, header, 12) != 12
2273261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber            || memcmp("ftyp", &header[4], 4)) {
2274261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        return false;
2275261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    }
2276261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
2277261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    size_t atomSize = U32_AT(&header[0]);
2278261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    if (atomSize < 16 || (atomSize % 4) != 0) {
2279261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        return false;
2280261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    }
2281261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
2282261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    bool success = false;
2283261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    if (isCompatibleBrand(U32_AT(&header[8]))) {
2284261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        success = true;
2285261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    } else {
2286261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        size_t numCompatibleBrands = (atomSize - 16) / 4;
2287261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        for (size_t i = 0; i < numCompatibleBrands; ++i) {
2288261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber            uint8_t tmp[4];
2289261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber            if (source->readAt(16 + i * 4, tmp, 4) != 4) {
2290261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber                return false;
2291261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber            }
2292261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
2293261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber            if (isCompatibleBrand(U32_AT(&tmp[0]))) {
2294261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber                success = true;
2295261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber                break;
2296261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber            }
2297261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        }
2298261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    }
2299261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
2300261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    if (!success) {
2301261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        return false;
2302261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    }
2303261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
2304261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
2305efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber    *confidence = 0.4f;
2306261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
2307261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    return true;
2308261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber}
2309261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
2310261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huberbool SniffMPEG4(
2311efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
2312efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber        sp<AMessage> *) {
2313261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    if (BetterSniffMPEG4(source, mimeType, confidence)) {
2314261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        return true;
2315261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    }
2316261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
2317261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    if (LegacySniffMPEG4(source, mimeType, confidence)) {
2318261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        LOGW("Identified supported mpeg4 through LegacySniffMPEG4.");
2319261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        return true;
2320261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    }
2321261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
2322261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    return false;
2323261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber}
2324261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
2325e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}  // namespace android
2326e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
2327