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"
22bd7b43bb02852e51b3000185fa66e10c56b120e0Andreas Huber
23e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <arpa/inet.h>
24e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
25e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <ctype.h>
26e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <stdint.h>
27e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <stdlib.h>
28e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <string.h>
29e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
3031dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber#include <media/stagefright/foundation/ADebug.h>
31e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/DataSource.h>
32d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber#include "include/ESDS.h"
33e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaBuffer.h>
34e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaBufferGroup.h>
35e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber#include <media/stagefright/MediaDefs.h>
36e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaSource.h>
37e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MetaData.h>
38e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/Utils.h>
39e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <utils/String8.h>
40e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
41e46b7be812d68e49710b34048662cbf18e2a6550Andreas Hubernamespace android {
42e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
43e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberclass MPEG4Source : public MediaSource {
44e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberpublic:
45e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    // Caller retains ownership of both "dataSource" and "sampleTable".
46be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber    MPEG4Source(const sp<MetaData> &format,
47be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber                const sp<DataSource> &dataSource,
48fa8de752507feaca695123911915070c1ce463b2Andreas Huber                int32_t timeScale,
49be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber                const sp<SampleTable> &sampleTable);
50e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
51e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    virtual status_t start(MetaData *params = NULL);
52e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    virtual status_t stop();
53e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
54e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    virtual sp<MetaData> getFormat();
55e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
56e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    virtual status_t read(
57e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            MediaBuffer **buffer, const ReadOptions *options = NULL);
58e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
59be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huberprotected:
60be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber    virtual ~MPEG4Source();
61be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber
62e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberprivate:
63ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber    Mutex mLock;
64ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber
65e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    sp<MetaData> mFormat;
66be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber    sp<DataSource> mDataSource;
67e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    int32_t mTimescale;
68be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber    sp<SampleTable> mSampleTable;
69e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    uint32_t mCurrentSampleIndex;
70e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
71e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    bool mIsAVC;
72db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    size_t mNALLengthSize;
73db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
74e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    bool mStarted;
75e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
76e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    MediaBufferGroup *mGroup;
77e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
78e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    MediaBuffer *mBuffer;
79e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
804f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    bool mWantsNALFragments;
81e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
828a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    uint8_t *mSrcBuffer;
838a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber
84db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    size_t parseNALSize(const uint8_t *data) const;
85db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
86e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    MPEG4Source(const MPEG4Source &);
87e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    MPEG4Source &operator=(const MPEG4Source &);
88e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber};
89e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
90affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// This custom data source wraps an existing one and satisfies requests
91affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// falling entirely within a cached range from the cache while forwarding
92affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// all remaining requests to the wrapped datasource.
93affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// This is used to cache the full sampletable metadata for a single track,
94affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// possibly wrapping multiple times to cover all tracks, i.e.
95affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// Each MPEG4DataSource caches the sampletable metadata for a single track.
96affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
97affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberstruct MPEG4DataSource : public DataSource {
98affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    MPEG4DataSource(const sp<DataSource> &source);
99affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
100affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    virtual status_t initCheck() const;
101affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    virtual ssize_t readAt(off_t offset, void *data, size_t size);
102affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    virtual status_t getSize(off_t *size);
103affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    virtual uint32_t flags();
104affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
105affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    status_t setCachedRange(off_t offset, size_t size);
106affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
107affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberprotected:
108affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    virtual ~MPEG4DataSource();
109affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
110affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberprivate:
111affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    Mutex mLock;
112affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
113affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    sp<DataSource> mSource;
114affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    off_t mCachedOffset;
115affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    size_t mCachedSize;
116affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    uint8_t *mCache;
117affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
118affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    void clearCache();
119affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
120affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    MPEG4DataSource(const MPEG4DataSource &);
121affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    MPEG4DataSource &operator=(const MPEG4DataSource &);
122affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber};
123affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
124affa99c52957685f5a5652ab5254b92e729651c7Andreas HuberMPEG4DataSource::MPEG4DataSource(const sp<DataSource> &source)
125affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    : mSource(source),
126affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber      mCachedOffset(0),
127affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber      mCachedSize(0),
128affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber      mCache(NULL) {
129affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber}
130affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
131affa99c52957685f5a5652ab5254b92e729651c7Andreas HuberMPEG4DataSource::~MPEG4DataSource() {
132affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    clearCache();
133affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber}
134affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
135affa99c52957685f5a5652ab5254b92e729651c7Andreas Hubervoid MPEG4DataSource::clearCache() {
136affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    if (mCache) {
137affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber        free(mCache);
138affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber        mCache = NULL;
139affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    }
140affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
141affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    mCachedOffset = 0;
142affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    mCachedSize = 0;
143affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber}
144affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
145affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberstatus_t MPEG4DataSource::initCheck() const {
146affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    return mSource->initCheck();
147affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber}
148affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
149affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberssize_t MPEG4DataSource::readAt(off_t offset, void *data, size_t size) {
150affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    Mutex::Autolock autoLock(mLock);
151affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
152affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    if (offset >= mCachedOffset
153affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber            && offset + size <= mCachedOffset + mCachedSize) {
154affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber        memcpy(data, &mCache[offset - mCachedOffset], size);
155affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber        return size;
156affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    }
157affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
158affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    return mSource->readAt(offset, data, size);
159affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber}
160affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
161affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberstatus_t MPEG4DataSource::getSize(off_t *size) {
162affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    return mSource->getSize(size);
163affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber}
164affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
165affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberuint32_t MPEG4DataSource::flags() {
166affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    return mSource->flags();
167affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber}
168affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
169affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberstatus_t MPEG4DataSource::setCachedRange(off_t offset, size_t size) {
170affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    Mutex::Autolock autoLock(mLock);
171affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
172affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    clearCache();
173affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
174affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    mCache = (uint8_t *)malloc(size);
175affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
176affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    if (mCache == NULL) {
177affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber        return -ENOMEM;
178affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    }
179affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
180affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    mCachedOffset = offset;
181affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    mCachedSize = size;
182affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
183affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    ssize_t err = mSource->readAt(mCachedOffset, mCache, mCachedSize);
184affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
185affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    if (err < (ssize_t)size) {
186affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber        clearCache();
187affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
188affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber        return ERROR_IO;
189affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    }
190affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
191affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber    return OK;
192affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber}
193affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
194affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber////////////////////////////////////////////////////////////////////////////////
195affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
196e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatic void hexdump(const void *_data, size_t size) {
197e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    const uint8_t *data = (const uint8_t *)_data;
198e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    size_t offset = 0;
199e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    while (offset < size) {
200e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        printf("0x%04x  ", offset);
201e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
202e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        size_t n = size - offset;
203e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (n > 16) {
204e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            n = 16;
205e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
206e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
207e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        for (size_t i = 0; i < 16; ++i) {
208e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (i == 8) {
209e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                printf(" ");
210e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
211e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
212e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (offset + i < size) {
213e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                printf("%02x ", data[offset + i]);
214e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            } else {
215e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                printf("   ");
216e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
217e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
218e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
219e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        printf(" ");
220e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
221e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        for (size_t i = 0; i < n; ++i) {
222e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (isprint(data[offset + i])) {
223e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                printf("%c", data[offset + i]);
224e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            } else {
225e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                printf(".");
226e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
227e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
228e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
229e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        printf("\n");
230e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
231e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        offset += 16;
232e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
233e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
234e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
235e6c409632f773e41f33188272a0072be9fcb783fAndreas Huberstatic const char *FourCC2MIME(uint32_t fourcc) {
236e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    switch (fourcc) {
237e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
238e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber            return MEDIA_MIMETYPE_AUDIO_AAC;
239e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
240e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
241e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_NB;
242e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
2432a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber        case FOURCC('s', 'a', 'w', 'b'):
244e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_WB;
2452a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber
246e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
247e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber            return MEDIA_MIMETYPE_VIDEO_MPEG4;
248e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
249e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', '2', '6', '3'):
250e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber            return MEDIA_MIMETYPE_VIDEO_H263;
251e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
252e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
253e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber            return MEDIA_MIMETYPE_VIDEO_AVC;
254e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
255e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        default:
2564f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            CHECK(!"should not be here.");
257e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            return NULL;
258e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
259e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
260e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
261be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas HuberMPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
262e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    : mDataSource(source),
263e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mHaveMetadata(false),
2641cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber      mHasVideo(false),
265e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mFirstTrack(NULL),
266c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber      mLastTrack(NULL),
267c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber      mFileMetaData(new MetaData) {
268e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
269e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
270e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberMPEG4Extractor::~MPEG4Extractor() {
271e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    Track *track = mFirstTrack;
272e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    while (track) {
273e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        Track *next = track->next;
274e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
275e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        delete track;
276e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        track = next;
277e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
278e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mFirstTrack = mLastTrack = NULL;
279e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
280e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
2811cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Hubersp<MetaData> MPEG4Extractor::getMetaData() {
2821cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber    status_t err;
2831cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber    if ((err = readMetaData()) != OK) {
284c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        return new MetaData;
2851cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber    }
2861cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber
287c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    return mFileMetaData;
2881cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber}
2891cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber
290be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Hubersize_t MPEG4Extractor::countTracks() {
291e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    status_t err;
292e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if ((err = readMetaData()) != OK) {
293be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber        return 0;
294e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
295e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
296be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber    size_t n = 0;
297e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    Track *track = mFirstTrack;
298e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    while (track) {
299be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber        ++n;
300e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        track = track->next;
301e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
302e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
303be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber    return n;
304e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
305e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
306e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Hubersp<MetaData> MPEG4Extractor::getTrackMetaData(
307e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber        size_t index, uint32_t flags) {
308e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    status_t err;
309e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if ((err = readMetaData()) != OK) {
310e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return NULL;
311e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
312e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
313e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    Track *track = mFirstTrack;
314e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    while (index > 0) {
315e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (track == NULL) {
316e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            return NULL;
317e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
318e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
319e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        track = track->next;
320e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        --index;
321e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
322e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
3232a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber    if (track == NULL) {
3242a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber        return NULL;
3252a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber    }
3262a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber
327e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber    if ((flags & kIncludeExtensiveMetaData)
328e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber            && !track->includes_expensive_metadata) {
329e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber        track->includes_expensive_metadata = true;
330e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber
331e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber        const char *mime;
332e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber        CHECK(track->meta->findCString(kKeyMIMEType, &mime));
333e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber        if (!strncasecmp("video/", mime, 6)) {
334e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber            uint32_t sampleIndex;
335e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber            uint32_t sampleTime;
336e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber            if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK
3371faa92a1e93f311e86dca483ed7702091137de66Andreas Huber                    && track->sampleTable->getMetaDataForSample(
3381faa92a1e93f311e86dca483ed7702091137de66Andreas Huber                        sampleIndex, NULL /* offset */, NULL /* size */,
3391faa92a1e93f311e86dca483ed7702091137de66Andreas Huber                        &sampleTime) == OK) {
340e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber                track->meta->setInt64(
341e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber                        kKeyThumbnailTime,
342e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber                        ((int64_t)sampleTime * 1000000) / track->timescale);
343e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber            }
344e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber        }
345e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber    }
346e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber
347e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return track->meta;
348e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
349e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
350e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Extractor::readMetaData() {
351e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (mHaveMetadata) {
352e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return OK;
353e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
354e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
355e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    off_t offset = 0;
356e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    status_t err;
357e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    while ((err = parseChunk(&offset, 0)) == OK) {
358e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
3591cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber
360e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (mHaveMetadata) {
361c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        if (mHasVideo) {
362c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            mFileMetaData->setCString(kKeyMIMEType, "video/mp4");
363c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        } else {
364c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            mFileMetaData->setCString(kKeyMIMEType, "audio/mp4");
365c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
366c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
367e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return OK;
368e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
369e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
370e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return err;
371e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
372e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
373e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatic void MakeFourCCString(uint32_t x, char *s) {
374e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    s[0] = x >> 24;
375e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    s[1] = (x >> 16) & 0xff;
376e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    s[2] = (x >> 8) & 0xff;
377e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    s[3] = x & 0xff;
378e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    s[4] = '\0';
379e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
380e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
381c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huberstruct PathAdder {
382c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    PathAdder(Vector<uint32_t> *path, uint32_t chunkType)
383c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        : mPath(path) {
384c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        mPath->push(chunkType);
385c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    }
386c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
387c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    ~PathAdder() {
388c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        mPath->pop();
389c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    }
390c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
391c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huberprivate:
392c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    Vector<uint32_t> *mPath;
393c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
394c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    PathAdder(const PathAdder &);
395c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    PathAdder &operator=(const PathAdder &);
396c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber};
397c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
398c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huberstatic bool underMetaDataPath(const Vector<uint32_t> &path) {
399c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    return path.size() >= 5
400c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        && path[0] == FOURCC('m', 'o', 'o', 'v')
401c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        && path[1] == FOURCC('u', 'd', 't', 'a')
402c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        && path[2] == FOURCC('m', 'e', 't', 'a')
403c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        && path[3] == FOURCC('i', 'l', 's', 't');
404c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber}
405c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
406c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber// Given a time in seconds since Jan 1 1904, produce a human-readable string.
407c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huberstatic void convertTimeToDate(int64_t time_1904, String8 *s) {
408c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    time_t time_1970 = time_1904 - (((66 * 365 + 17) * 24) * 3600);
409c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
410c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    char tmp[32];
411c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    strftime(tmp, sizeof(tmp), "%Y%m%dT%H%M%S.000Z", gmtime(&time_1970));
412c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
413c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    s->setTo(tmp);
414c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber}
415c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
416e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
417e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    uint32_t hdr[2];
4189a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
419e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return ERROR_IO;
420e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
421e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    uint64_t chunk_size = ntohl(hdr[0]);
422e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    uint32_t chunk_type = ntohl(hdr[1]);
423e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    off_t data_offset = *offset + 8;
424e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
425e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (chunk_size == 1) {
4269a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
427e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            return ERROR_IO;
428e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
429e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        chunk_size = ntoh64(chunk_size);
430e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        data_offset += 8;
431736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber
432736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber        if (chunk_size < 16) {
433736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber            // The smallest valid chunk is 16 bytes long in this case.
434736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber            return ERROR_MALFORMED;
435736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber        }
436736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber    } else if (chunk_size < 8) {
437736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber        // The smallest valid chunk is 8 bytes long.
438736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber        return ERROR_MALFORMED;
439e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
440e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
441e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    char chunk[5];
442e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    MakeFourCCString(chunk_type, chunk);
443e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
444e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#if 0
445e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    static const char kWhitespace[] = "                                        ";
446e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth];
447e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    printf("%sfound chunk '%s' of size %lld\n", indent, chunk, chunk_size);
448e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
449e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    char buffer[256];
450dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber    size_t n = chunk_size;
451dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber    if (n > sizeof(buffer)) {
452dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber        n = sizeof(buffer);
453dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber    }
454dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber    if (mDataSource->readAt(*offset, buffer, n)
455dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber            < (ssize_t)n) {
456dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber        return ERROR_IO;
457e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
458dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber
459dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber    hexdump(buffer, n);
460e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#endif
461e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
462c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    PathAdder autoAdder(&mPath, chunk_type);
463c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
464e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    off_t chunk_data_size = *offset + chunk_size - data_offset;
465e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
466c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    if (chunk_type != FOURCC('c', 'p', 'r', 't')
467c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            && mPath.size() == 5 && underMetaDataPath(mPath)) {
468c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        off_t stop_offset = *offset + chunk_size;
469c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        *offset = data_offset;
470c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        while (*offset < stop_offset) {
471c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            status_t err = parseChunk(offset, depth + 1);
472c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (err != OK) {
473c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                return err;
474c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
475c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
4765ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
4775ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber        if (*offset != stop_offset) {
4785ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            return ERROR_MALFORMED;
4795ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber        }
480c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
481c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        return OK;
482c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    }
483c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
484e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    switch(chunk_type) {
485e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'o', 'o', 'v'):
486e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('t', 'r', 'a', 'k'):
487e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'd', 'i', 'a'):
488e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'i', 'n', 'f'):
489e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('d', 'i', 'n', 'f'):
490e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 'b', 'l'):
491e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'v', 'e', 'x'):
492e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'o', 'o', 'f'):
493e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('t', 'r', 'a', 'f'):
494e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'f', 'r', 'a'):
495c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('u', 'd', 't', 'a'):
496c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('i', 'l', 's', 't'):
497e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
498affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber            if (chunk_type == FOURCC('s', 't', 'b', 'l')) {
499affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                LOGV("sampleTable chunk is %d bytes long.", (size_t)chunk_size);
500affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
5016da2ae11b62f155ee83c3e31fdd9cc53b2058586Andreas Huber                if (mDataSource->flags()
5026da2ae11b62f155ee83c3e31fdd9cc53b2058586Andreas Huber                        & (DataSource::kWantsPrefetching
5036da2ae11b62f155ee83c3e31fdd9cc53b2058586Andreas Huber                            | DataSource::kIsCachingDataSource)) {
504affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                    sp<MPEG4DataSource> cachedSource =
505affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                        new MPEG4DataSource(mDataSource);
506affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
507affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                    if (cachedSource->setCachedRange(*offset, chunk_size) == OK) {
508affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                        mDataSource = cachedSource;
509affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                    }
510affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                }
511eb9128f9b0ee660504621381fd96f82d5bf8a3fdAndreas Huber
512eb9128f9b0ee660504621381fd96f82d5bf8a3fdAndreas Huber                mLastTrack->sampleTable = new SampleTable(mDataSource);
513affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber            }
514affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
5154d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber            bool isTrack = false;
5165ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            if (chunk_type == FOURCC('t', 'r', 'a', 'k')) {
5174d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                isTrack = true;
5184d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber
5195ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                Track *track = new Track;
5205ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                track->next = NULL;
5215ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                if (mLastTrack) {
5225ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                    mLastTrack->next = track;
5235ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                } else {
5245ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                    mFirstTrack = track;
5255ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                }
5265ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                mLastTrack = track;
5275ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
5285ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                track->meta = new MetaData;
5295ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                track->includes_expensive_metadata = false;
5304d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                track->skipTrack = false;
5315ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                track->timescale = 0;
5325ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                track->meta->setCString(kKeyMIMEType, "application/octet-stream");
5335ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            }
5345ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
535e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            off_t stop_offset = *offset + chunk_size;
536e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset = data_offset;
537e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            while (*offset < stop_offset) {
538e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                status_t err = parseChunk(offset, depth + 1);
539e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (err != OK) {
540e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return err;
541e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
542e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
543e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
5445ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            if (*offset != stop_offset) {
5455ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                return ERROR_MALFORMED;
5465ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            }
5475ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
5484d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber            if (isTrack) {
5494d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                if (mLastTrack->skipTrack) {
5504d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                    Track *cur = mFirstTrack;
5514d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber
5524d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                    if (cur == mLastTrack) {
5534d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                        delete cur;
5544d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                        mFirstTrack = mLastTrack = NULL;
5554d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                    } else {
5564d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                        while (cur && cur->next != mLastTrack) {
5574d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                            cur = cur->next;
5584d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                        }
5594d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                        cur->next = NULL;
5604d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                        delete mLastTrack;
5614d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                        mLastTrack = cur;
5624d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                    }
5634d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber
5644d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                    return OK;
5654d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                }
5664d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber
5675ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                status_t err = verifyTrack(mLastTrack);
5685ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
5695ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                if (err != OK) {
5705ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                    return err;
5715ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                }
5725ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
573e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mHaveMetadata = true;
574e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
575e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return UNKNOWN_ERROR;  // Return a dummy error.
576e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
577e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
578e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
579e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
580e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('t', 'k', 'h', 'd'):
581e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
58231dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber            status_t err;
58331dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber            if ((err = parseTrackHeader(data_offset, chunk_data_size)) != OK) {
58431dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber                return err;
585e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
586e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
587e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
588e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
589e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
590e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
591e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'd', 'h', 'd'):
592e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
593e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size < 4) {
594e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
595e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
596e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
597e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t version;
5989a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(
599e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, &version, sizeof(version))
600e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    < (ssize_t)sizeof(version)) {
601e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
602e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
603e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
604e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            off_t timescale_offset;
605e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
606e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (version == 1) {
607e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                timescale_offset = data_offset + 4 + 16;
608e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            } else if (version == 0) {
609e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                timescale_offset = data_offset + 4 + 8;
610e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            } else {
611e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
612e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
613e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
614e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint32_t timescale;
6159a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(
616e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        timescale_offset, &timescale, sizeof(timescale))
617e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    < (ssize_t)sizeof(timescale)) {
618e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
619e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
620e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
621e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->timescale = ntohl(timescale);
622e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
623e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            int64_t duration;
624e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (version == 1) {
6259a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber                if (mDataSource->readAt(
626e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                            timescale_offset + 4, &duration, sizeof(duration))
627e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        < (ssize_t)sizeof(duration)) {
628e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return ERROR_IO;
629e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
630e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                duration = ntoh64(duration);
631e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            } else {
632e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                int32_t duration32;
6339a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber                if (mDataSource->readAt(
634e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                            timescale_offset + 4, &duration32, sizeof(duration32))
635e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        < (ssize_t)sizeof(duration32)) {
636e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return ERROR_IO;
637e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
638e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                duration = ntohl(duration32);
639e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
640fa8de752507feaca695123911915070c1ce463b2Andreas Huber            mLastTrack->meta->setInt64(
641fa8de752507feaca695123911915070c1ce463b2Andreas Huber                    kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
642e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
643e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
644e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
645e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
646e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
647e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 's', 'd'):
648e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
649e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size < 8) {
650e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
651e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
652e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
653e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t buffer[8];
6545ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            if (chunk_data_size < (off_t)sizeof(buffer)) {
6555ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                return ERROR_MALFORMED;
6565ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            }
6575ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
6589a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(
659e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, buffer, 8) < 8) {
660e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
661e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
662e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
663e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (U32_AT(buffer) != 0) {
664e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // Should be version 0, flags 0.
665e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
666e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
667e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
668e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint32_t entry_count = U32_AT(&buffer[4]);
669e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
670e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (entry_count > 1) {
671e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // For now we only support a single type of media per track.
6724d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber
6734d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                mLastTrack->skipTrack = true;
6744d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                *offset += chunk_size;
6754d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                break;
676e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
677e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
678e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            off_t stop_offset = *offset + chunk_size;
679e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset = data_offset + 8;
680e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            for (uint32_t i = 0; i < entry_count; ++i) {
681e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                status_t err = parseChunk(offset, depth + 1);
682e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (err != OK) {
683e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return err;
684e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
685e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
6865ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
6875ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            if (*offset != stop_offset) {
6885ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                return ERROR_MALFORMED;
6895ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            }
690e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
691e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
692e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
693e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
694e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
6952a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber        case FOURCC('s', 'a', 'w', 'b'):
696e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
697e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t buffer[8 + 20];
698e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
699e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // Basic AudioSampleEntry size.
700e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
701e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
702e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
7039a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(
704e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
705e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
706e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
707e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
708e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
709e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint16_t num_channels = U16_AT(&buffer[16]);
710e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
711d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber            uint16_t sample_size = U16_AT(&buffer[18]);
712d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber            uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
713d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber
714e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber            if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB,
715d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber                            FourCC2MIME(chunk_type))) {
716d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber                // AMR NB audio is always mono, 8kHz
717d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber                num_channels = 1;
718d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber                sample_rate = 8000;
719d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber            } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB,
720e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber                               FourCC2MIME(chunk_type))) {
721d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber                // AMR WB audio is always mono, 16kHz
722e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                num_channels = 1;
723d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber                sample_rate = 16000;
724e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
725e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
726d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber#if 0
727d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber            printf("*** coding='%s' %d channels, size %d, rate %d\n",
728d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber                   chunk, num_channels, sample_size, sample_rate);
729d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber#endif
730e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
731e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
732e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
733e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
734e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
735e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            off_t stop_offset = *offset + chunk_size;
736e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset = data_offset + sizeof(buffer);
737e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            while (*offset < stop_offset) {
738e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                status_t err = parseChunk(offset, depth + 1);
739e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (err != OK) {
740e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return err;
741e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
742e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
7435ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
7445ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            if (*offset != stop_offset) {
7455ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                return ERROR_MALFORMED;
7465ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            }
747e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
748e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
749e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
750e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
751e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', '2', '6', '3'):
752e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
753e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
7541cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber            mHasVideo = true;
7551cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber
756e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t buffer[78];
757e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
758e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // Basic VideoSampleEntry size.
759e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
760e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
761e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
7629a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(
763e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
764e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
765e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
766e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
767e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
768e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint16_t width = U16_AT(&buffer[6 + 18]);
769e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint16_t height = U16_AT(&buffer[6 + 20]);
770e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
7712ea14e231945afb6581fa8f54015b33bc74a19e5Andreas Huber            // printf("*** coding='%s' width=%d height=%d\n",
7722ea14e231945afb6581fa8f54015b33bc74a19e5Andreas Huber            //        chunk, width, height);
773e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
774e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
775e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setInt32(kKeyWidth, width);
776e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setInt32(kKeyHeight, height);
777e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
778e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            off_t stop_offset = *offset + chunk_size;
779e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset = data_offset + sizeof(buffer);
780e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            while (*offset < stop_offset) {
781e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                status_t err = parseChunk(offset, depth + 1);
782e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (err != OK) {
783e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return err;
784e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
785e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
7865ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
7875ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            if (*offset != stop_offset) {
7885ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                return ERROR_MALFORMED;
7895ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            }
790e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
791e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
792e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
793e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 'c', 'o'):
794e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('c', 'o', '6', '4'):
795e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
796e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            status_t err =
797e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mLastTrack->sampleTable->setChunkOffsetParams(
798e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        chunk_type, data_offset, chunk_data_size);
799e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
800e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (err != OK) {
801e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return err;
802e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
803e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
804e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
805e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
806e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
807e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
808e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 's', 'c'):
809e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
810e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            status_t err =
811e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mLastTrack->sampleTable->setSampleToChunkParams(
812e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, chunk_data_size);
813e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
814e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (err != OK) {
815e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return err;
816e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
817e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
818e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
819e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
820e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
821e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
822e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 's', 'z'):
823e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 'z', '2'):
824e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
825e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            status_t err =
826e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mLastTrack->sampleTable->setSampleSizeParams(
827e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        chunk_type, data_offset, chunk_data_size);
828e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
829e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (err != OK) {
830e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return err;
831e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
832e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
8331bceff916a72246fa208605d50615823d7f1688bAndreas Huber            size_t max_size;
834d7f2225e7455f5e0da32f409a528ced283631c5dAndreas Huber            err = mLastTrack->sampleTable->getMaxSampleSize(&max_size);
835d7f2225e7455f5e0da32f409a528ced283631c5dAndreas Huber
836d7f2225e7455f5e0da32f409a528ced283631c5dAndreas Huber            if (err != OK) {
837d7f2225e7455f5e0da32f409a528ced283631c5dAndreas Huber                return err;
838d7f2225e7455f5e0da32f409a528ced283631c5dAndreas Huber            }
8391bceff916a72246fa208605d50615823d7f1688bAndreas Huber
8401bceff916a72246fa208605d50615823d7f1688bAndreas Huber            // Assume that a given buffer only contains at most 10 fragments,
8411bceff916a72246fa208605d50615823d7f1688bAndreas Huber            // each fragment originally prefixed with a 2 byte length will
8421bceff916a72246fa208605d50615823d7f1688bAndreas Huber            // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
8431bceff916a72246fa208605d50615823d7f1688bAndreas Huber            // and thus will grow by 2 bytes per fragment.
8441bceff916a72246fa208605d50615823d7f1688bAndreas Huber            mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
8451bceff916a72246fa208605d50615823d7f1688bAndreas Huber
846e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
847e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
848e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
849e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
850e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 't', 's'):
851e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
852e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            status_t err =
853e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mLastTrack->sampleTable->setTimeToSampleParams(
854e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, chunk_data_size);
855e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
856e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (err != OK) {
857e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return err;
858e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
859e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
860e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
861e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
862e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
863e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
864e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 's', 's'):
865e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
866e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            status_t err =
867e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mLastTrack->sampleTable->setSyncSampleParams(
868e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, chunk_data_size);
869e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
870e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (err != OK) {
871e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return err;
872e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
873e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
874e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
875e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
876e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
877e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
878e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('e', 's', 'd', 's'):
879e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
880e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size < 4) {
881e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
882e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
883e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
884e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t buffer[256];
885e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size > (off_t)sizeof(buffer)) {
886e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
887e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
888e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
8899a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(
890e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
891e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
892e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
893e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
894e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (U32_AT(buffer) != 0) {
895e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // Should be version 0, flags 0.
896e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
897e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
898e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
899e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setData(
900e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
901e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
902d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber            if (mPath.size() >= 2
903d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                    && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) {
904d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                // Information from the ESDS must be relied on for proper
905d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                // setup of sample rate and channel count for MPEG4 Audio.
906d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                // The generic header appears to only contain generic
907d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                // information...
908d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
909d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio(
910d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                        &buffer[4], chunk_data_size - 4);
911d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
912d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                if (err != OK) {
913d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                    return err;
914d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                }
915d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber            }
916d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
917e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
918e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
919e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
920e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
921e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('a', 'v', 'c', 'C'):
922e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
923e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            char buffer[256];
924e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size > (off_t)sizeof(buffer)) {
925e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
926e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
927e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
9289a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(
929e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
930e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
931e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
932e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
933e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setData(
934e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    kKeyAVCC, kTypeAVCC, buffer, chunk_data_size);
935e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
936e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
937e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
938e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
939e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
940c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('m', 'e', 't', 'a'):
941c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
942c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            uint8_t buffer[4];
9435ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            if (chunk_data_size < (off_t)sizeof(buffer)) {
9445ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                return ERROR_MALFORMED;
9455ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            }
9465ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
947c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (mDataSource->readAt(
948c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                        data_offset, buffer, 4) < 4) {
949c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                return ERROR_IO;
950c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
951c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
952c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (U32_AT(buffer) != 0) {
953c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                // Should be version 0, flags 0.
954dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber
955dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber                // If it's not, let's assume this is one of those
956dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber                // apparently malformed chunks that don't have flags
957dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber                // and completely different semantics than what's
958dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber                // in the MPEG4 specs and skip it.
959dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber                *offset += chunk_size;
960dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber                return OK;
961c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
962c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
963c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            off_t stop_offset = *offset + chunk_size;
964c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            *offset = data_offset + sizeof(buffer);
965c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            while (*offset < stop_offset) {
966c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                status_t err = parseChunk(offset, depth + 1);
967c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                if (err != OK) {
968c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                    return err;
969c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                }
970c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
9715ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
9725ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            if (*offset != stop_offset) {
9735ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                return ERROR_MALFORMED;
9745ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            }
975c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
976c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
977c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
978c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('d', 'a', 't', 'a'):
979c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
980c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (mPath.size() == 6 && underMetaDataPath(mPath)) {
981c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                status_t err = parseMetaData(data_offset, chunk_data_size);
982c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
983c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                if (err != OK) {
984c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                    return err;
985c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                }
986c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
987c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
988c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            *offset += chunk_size;
989c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
990c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
991c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
992c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('m', 'v', 'h', 'd'):
993c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
994c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (chunk_data_size < 12) {
995c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                return ERROR_MALFORMED;
996c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
997c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
998c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            uint8_t header[12];
999c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (mDataSource->readAt(
1000c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                        data_offset, header, sizeof(header))
1001c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                    < (ssize_t)sizeof(header)) {
1002c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                return ERROR_IO;
1003c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
1004c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1005c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            int64_t creationTime;
1006c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (header[0] == 1) {
1007c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                creationTime = U64_AT(&header[4]);
10085ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            } else if (header[0] != 0) {
10095ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                return ERROR_MALFORMED;
1010c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            } else {
1011c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                creationTime = U32_AT(&header[4]);
1012c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
1013c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1014c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            String8 s;
1015c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            convertTimeToDate(creationTime, &s);
1016c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1017c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            mFileMetaData->setCString(kKeyDate, s.string());
1018c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1019c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            *offset += chunk_size;
1020c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1021c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1022c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1023e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        default:
1024e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
1025e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
1026e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
1027e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
1028e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1029e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1030e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return OK;
1031e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1032e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
103331dc911aee2b50752c0eb7785176075cdaed139cAndreas Huberstatus_t MPEG4Extractor::parseTrackHeader(
103431dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber        off_t data_offset, off_t data_size) {
103531dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    if (data_size < 4) {
103631dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber        return ERROR_MALFORMED;
103731dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    }
103831dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber
103931dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    uint8_t version;
104031dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    if (mDataSource->readAt(data_offset, &version, 1) < 1) {
104131dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber        return ERROR_IO;
104231dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    }
104331dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber
104431dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    size_t dynSize = (version == 1) ? 36 : 24;
104531dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber
104631dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    uint8_t buffer[36 + 60];
104731dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber
104831dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    if (data_size != (off_t)dynSize + 60) {
104931dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber        return ERROR_MALFORMED;
105031dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    }
105131dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber
105231dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    if (mDataSource->readAt(
105331dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber                data_offset, buffer, data_size) < (ssize_t)data_size) {
105431dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber        return ERROR_IO;
105531dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    }
105631dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber
105731dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    uint64_t ctime, mtime, duration;
105831dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    int32_t id;
105931dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber
106031dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    if (version == 1) {
106131dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber        ctime = U64_AT(&buffer[4]);
106231dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber        mtime = U64_AT(&buffer[12]);
106331dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber        id = U32_AT(&buffer[20]);
106431dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber        duration = U64_AT(&buffer[28]);
106531dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    } else if (version == 0) {
106631dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber        ctime = U32_AT(&buffer[4]);
106731dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber        mtime = U32_AT(&buffer[8]);
106831dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber        id = U32_AT(&buffer[12]);
106931dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber        duration = U32_AT(&buffer[20]);
107031dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    }
107131dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber
107231dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    size_t matrixOffset = dynSize + 16;
107331dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    int32_t a00 = U32_AT(&buffer[matrixOffset]);
107431dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    int32_t a01 = U32_AT(&buffer[matrixOffset + 4]);
107531dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    int32_t dx = U32_AT(&buffer[matrixOffset + 8]);
107631dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    int32_t a10 = U32_AT(&buffer[matrixOffset + 12]);
107731dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    int32_t a11 = U32_AT(&buffer[matrixOffset + 16]);
107831dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    int32_t dy = U32_AT(&buffer[matrixOffset + 20]);
107931dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber
108031dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber#if 0
108131dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    LOGI("x' = %.2f * x + %.2f * y + %.2f",
108231dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber         a00 / 65536.0f, a01 / 65536.0f, dx / 65536.0f);
108331dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    LOGI("y' = %.2f * x + %.2f * y + %.2f",
108431dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber         a10 / 65536.0f, a11 / 65536.0f, dy / 65536.0f);
108531dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber#endif
108631dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber
108731dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    uint32_t rotationDegrees;
108831dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber
108931dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    static const int32_t kFixedOne = 0x10000;
109031dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    if (a00 == kFixedOne && a01 == 0 && a10 == 0 && a11 == kFixedOne) {
109131dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber        // Identity, no rotation
109231dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber        rotationDegrees = 0;
109331dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    } else if (a00 == 0 && a01 == kFixedOne && a10 == -kFixedOne && a11 == 0) {
109431dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber        rotationDegrees = 90;
109531dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    } else if (a00 == 0 && a01 == -kFixedOne && a10 == kFixedOne && a11 == 0) {
109631dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber        rotationDegrees = 270;
109731dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    } else if (a00 == -kFixedOne && a01 == 0 && a10 == 0 && a11 == -kFixedOne) {
109831dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber        rotationDegrees = 180;
109931dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    } else {
110031dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber        LOGW("We only support 0,90,180,270 degree rotation matrices");
110131dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber        rotationDegrees = 0;
110231dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    }
110331dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber
110431dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    if (rotationDegrees != 0) {
110531dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber        mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees);
110631dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    }
110731dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber
110831dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber#if 0
110931dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    uint32_t width = U32_AT(&buffer[dynSize + 52]);
111031dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    uint32_t height = U32_AT(&buffer[dynSize + 56]);
111131dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber#endif
111231dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber
111331dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber    return OK;
111431dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber}
111531dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber
1116c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huberstatus_t MPEG4Extractor::parseMetaData(off_t offset, size_t size) {
1117c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    if (size < 4) {
1118c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        return ERROR_MALFORMED;
1119c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    }
1120c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1121c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    uint8_t *buffer = new uint8_t[size + 1];
1122c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    if (mDataSource->readAt(
1123c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                offset, buffer, size) != (ssize_t)size) {
1124c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        delete[] buffer;
1125c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        buffer = NULL;
1126c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1127c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        return ERROR_IO;
1128c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    }
1129c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1130c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    uint32_t flags = U32_AT(buffer);
1131c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1132c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    uint32_t metadataKey = 0;
1133c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    switch (mPath[4]) {
1134c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC(0xa9, 'a', 'l', 'b'):
1135c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1136c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            metadataKey = kKeyAlbum;
1137c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1138c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1139c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC(0xa9, 'A', 'R', 'T'):
1140c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1141c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            metadataKey = kKeyArtist;
1142c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1143c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1144c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen        case FOURCC('a', 'A', 'R', 'T'):
1145c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen        {
1146c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen            metadataKey = kKeyAlbumArtist;
1147c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen            break;
1148c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen        }
1149c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC(0xa9, 'd', 'a', 'y'):
1150c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1151c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            metadataKey = kKeyYear;
1152c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1153c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1154c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC(0xa9, 'n', 'a', 'm'):
1155c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1156c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            metadataKey = kKeyTitle;
1157c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1158c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1159c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC(0xa9, 'w', 'r', 't'):
1160c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1161c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            metadataKey = kKeyWriter;
1162c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1163c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1164c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('c', 'o', 'v', 'r'):
1165c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1166c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            metadataKey = kKeyAlbumArt;
1167c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1168c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1169c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('g', 'n', 'r', 'e'):
1170c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1171c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            metadataKey = kKeyGenre;
1172c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1173c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1174fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen        case FOURCC(0xa9, 'g', 'e', 'n'):
1175fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen        {
1176fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen            metadataKey = kKeyGenre;
1177fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen            break;
1178fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen        }
1179ba77a3f9cb1d68b2ed4813aaae856444578e3a75Marco Nelissen        case FOURCC('c', 'p', 'i', 'l'):
1180ba77a3f9cb1d68b2ed4813aaae856444578e3a75Marco Nelissen        {
1181ba77a3f9cb1d68b2ed4813aaae856444578e3a75Marco Nelissen            if (size == 9 && flags == 21) {
1182ba77a3f9cb1d68b2ed4813aaae856444578e3a75Marco Nelissen                char tmp[16];
1183ba77a3f9cb1d68b2ed4813aaae856444578e3a75Marco Nelissen                sprintf(tmp, "%d",
1184ba77a3f9cb1d68b2ed4813aaae856444578e3a75Marco Nelissen                        (int)buffer[size - 1]);
1185ba77a3f9cb1d68b2ed4813aaae856444578e3a75Marco Nelissen
1186ba77a3f9cb1d68b2ed4813aaae856444578e3a75Marco Nelissen                mFileMetaData->setCString(kKeyCompilation, tmp);
1187ba77a3f9cb1d68b2ed4813aaae856444578e3a75Marco Nelissen            }
1188ba77a3f9cb1d68b2ed4813aaae856444578e3a75Marco Nelissen            break;
1189ba77a3f9cb1d68b2ed4813aaae856444578e3a75Marco Nelissen        }
1190c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('t', 'r', 'k', 'n'):
1191c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1192c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (size == 16 && flags == 0) {
1193c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                char tmp[16];
1194c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                sprintf(tmp, "%d/%d",
1195c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                        (int)buffer[size - 5], (int)buffer[size - 3]);
1196c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1197c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
1198c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
1199c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1200c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1201fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen        case FOURCC('d', 'i', 's', 'k'):
1202fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen        {
1203fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen            if (size == 14 && flags == 0) {
1204fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                char tmp[16];
1205fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                sprintf(tmp, "%d/%d",
1206fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                        (int)buffer[size - 3], (int)buffer[size - 1]);
1207fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen
1208fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                mFileMetaData->setCString(kKeyDiscNumber, tmp);
1209fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen            }
1210fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen            break;
1211fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen        }
1212fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen
1213c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        default:
1214c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1215c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    }
1216c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1217c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    if (size >= 8 && metadataKey) {
1218c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        if (metadataKey == kKeyAlbumArt) {
1219c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            mFileMetaData->setData(
1220c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                    kKeyAlbumArt, MetaData::TYPE_NONE,
1221c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                    buffer + 8, size - 8);
1222c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        } else if (metadataKey == kKeyGenre) {
1223c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (flags == 0) {
1224fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                // uint8_t genre code, iTunes genre codes are
1225fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                // the standard id3 codes, except they start
1226fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                // at 1 instead of 0 (e.g. Pop is 14, not 13)
1227fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                // We use standard id3 numbering, so subtract 1.
1228fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                int genrecode = (int)buffer[size - 1];
1229fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                genrecode--;
1230fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                if (genrecode < 0) {
1231fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                    genrecode = 255; // reserved for 'unknown genre'
1232fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                }
1233c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                char genre[10];
1234fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                sprintf(genre, "%d", genrecode);
1235c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1236c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                mFileMetaData->setCString(metadataKey, genre);
1237fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen            } else if (flags == 1) {
1238fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                // custom genre string
1239fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                buffer[size] = '\0';
1240fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen
1241fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                mFileMetaData->setCString(
1242fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                        metadataKey, (const char *)buffer + 8);
1243c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
1244c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        } else {
1245c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            buffer[size] = '\0';
1246c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1247c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            mFileMetaData->setCString(
1248c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                    metadataKey, (const char *)buffer + 8);
1249c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1250c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    }
1251c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1252c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    delete[] buffer;
1253c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    buffer = NULL;
1254c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1255c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    return OK;
1256c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber}
1257c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1258be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
1259e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    status_t err;
1260e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if ((err = readMetaData()) != OK) {
1261be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber        return NULL;
1262e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1263e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1264e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    Track *track = mFirstTrack;
1265e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    while (index > 0) {
1266e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (track == NULL) {
1267be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber            return NULL;
1268e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
1269e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1270e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        track = track->next;
1271e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        --index;
1272e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1273e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
12742a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber    if (track == NULL) {
12752a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber        return NULL;
12762a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber    }
12772a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber
1278be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber    return new MPEG4Source(
1279fa8de752507feaca695123911915070c1ce463b2Andreas Huber            track->meta, mDataSource, track->timescale, track->sampleTable);
1280e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1281e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
12825ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber// static
12835ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huberstatus_t MPEG4Extractor::verifyTrack(Track *track) {
12845ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber    const char *mime;
12855ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber    CHECK(track->meta->findCString(kKeyMIMEType, &mime));
12865ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
12875ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber    uint32_t type;
12885ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber    const void *data;
12895ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber    size_t size;
12905ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
12915ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber        if (!track->meta->findData(kKeyAVCC, &type, &data, &size)
12925ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                || type != kTypeAVCC) {
12935ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            return ERROR_MALFORMED;
12945ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber        }
12955ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
12965ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
12975ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber        if (!track->meta->findData(kKeyESDS, &type, &data, &size)
12985ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                || type != kTypeESDS) {
12995ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            return ERROR_MALFORMED;
13005ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber        }
13015ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber    }
13025ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
13035ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber    return OK;
13045ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber}
13055ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
1306d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huberstatus_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(
1307d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        const void *esds_data, size_t esds_size) {
1308d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    ESDS esds(esds_data, esds_size);
1309d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber
1310d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber    uint8_t objectTypeIndication;
1311d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber    if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) {
1312d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber        return ERROR_MALFORMED;
1313d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber    }
1314d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber
1315d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber    if (objectTypeIndication == 0xe1) {
1316d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber        // This isn't MPEG4 audio at all, it's QCELP 14k...
1317d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber        mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
1318d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber        return OK;
1319d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber    }
1320d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber
1321d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    const uint8_t *csd;
1322d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    size_t csd_size;
1323d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    if (esds.getCodecSpecificInfo(
1324d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                (const void **)&csd, &csd_size) != OK) {
1325d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        return ERROR_MALFORMED;
1326d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    }
1327d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1328d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber#if 0
1329d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    printf("ESD of size %d\n", csd_size);
1330d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    hexdump(csd, csd_size);
1331d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber#endif
1332d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
133308c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber    if (csd_size == 0) {
133408c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber        // There's no further information, i.e. no codec specific data
133508c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber        // Let's assume that the information provided in the mpeg4 headers
133608c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber        // is accurate and hope for the best.
133708c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber
133808c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber        return OK;
133908c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber    }
134008c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber
1341d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    if (csd_size < 2) {
1342d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        return ERROR_MALFORMED;
1343d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    }
1344d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1345d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    uint32_t objectType = csd[0] >> 3;
1346d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1347d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    if (objectType == 31) {
1348d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        return ERROR_UNSUPPORTED;
1349d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    }
1350d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1351d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    uint32_t freqIndex = (csd[0] & 7) << 1 | (csd[1] >> 7);
1352d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    int32_t sampleRate = 0;
1353d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    int32_t numChannels = 0;
1354d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    if (freqIndex == 15) {
1355d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        if (csd_size < 5) {
1356d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber            return ERROR_MALFORMED;
1357d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        }
1358d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1359d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        sampleRate = (csd[1] & 0x7f) << 17
1360d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                        | csd[2] << 9
1361d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                        | csd[3] << 1
1362d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                        | (csd[4] >> 7);
1363d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1364d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        numChannels = (csd[4] >> 3) & 15;
1365d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    } else {
1366cc14a8393b92cd1ed6cba74829396045605ab211Andreas Huber        static uint32_t kSamplingRate[] = {
1367cc14a8393b92cd1ed6cba74829396045605ab211Andreas Huber            96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
1368cc14a8393b92cd1ed6cba74829396045605ab211Andreas Huber            16000, 12000, 11025, 8000, 7350
1369cc14a8393b92cd1ed6cba74829396045605ab211Andreas Huber        };
1370d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1371d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        if (freqIndex == 13 || freqIndex == 14) {
1372d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber            return ERROR_MALFORMED;
1373d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        }
1374d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1375d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        sampleRate = kSamplingRate[freqIndex];
1376d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        numChannels = (csd[1] >> 3) & 15;
1377d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    }
1378d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1379d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    if (numChannels == 0) {
1380d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        return ERROR_UNSUPPORTED;
1381d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    }
1382d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1383d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    int32_t prevSampleRate;
1384d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));
1385d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1386d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    if (prevSampleRate != sampleRate) {
13874a9375ef2a06fc36ec308835ef9e7e4eea2ba69fAndreas Huber        LOGV("mpeg4 audio sample rate different from previous setting. "
1388d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber             "was: %d, now: %d", prevSampleRate, sampleRate);
1389d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    }
1390d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1391d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
1392d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1393d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    int32_t prevChannelCount;
1394d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount));
1395d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1396d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    if (prevChannelCount != numChannels) {
13974a9375ef2a06fc36ec308835ef9e7e4eea2ba69fAndreas Huber        LOGV("mpeg4 audio channel count different from previous setting. "
1398d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber             "was: %d, now: %d", prevChannelCount, numChannels);
1399d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    }
1400d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1401d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    mLastTrack->meta->setInt32(kKeyChannelCount, numChannels);
1402d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1403d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    return OK;
1404d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber}
1405d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1406e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber////////////////////////////////////////////////////////////////////////////////
1407e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1408e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberMPEG4Source::MPEG4Source(
1409e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        const sp<MetaData> &format,
1410be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber        const sp<DataSource> &dataSource,
1411fa8de752507feaca695123911915070c1ce463b2Andreas Huber        int32_t timeScale,
1412be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber        const sp<SampleTable> &sampleTable)
1413e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    : mFormat(format),
1414e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mDataSource(dataSource),
1415fa8de752507feaca695123911915070c1ce463b2Andreas Huber      mTimescale(timeScale),
1416e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mSampleTable(sampleTable),
1417e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mCurrentSampleIndex(0),
1418e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mIsAVC(false),
1419db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber      mNALLengthSize(0),
1420e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mStarted(false),
1421e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mGroup(NULL),
1422e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mBuffer(NULL),
14234f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber      mWantsNALFragments(false),
14248a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber      mSrcBuffer(NULL) {
1425e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    const char *mime;
1426e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    bool success = mFormat->findCString(kKeyMIMEType, &mime);
14274f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    CHECK(success);
1428e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1429e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber    mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
1430db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
1431db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    if (mIsAVC) {
1432db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        uint32_t type;
1433db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        const void *data;
1434db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        size_t size;
1435db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        CHECK(format->findData(kKeyAVCC, &type, &data, &size));
1436db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
1437db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        const uint8_t *ptr = (const uint8_t *)data;
1438db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
1439db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        CHECK(size >= 7);
144031dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber        CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
1441db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
1442db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        // The number of bytes used to encode the length of a NAL unit.
1443db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        mNALLengthSize = 1 + (ptr[4] & 3);
1444db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    }
1445e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1446e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1447e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberMPEG4Source::~MPEG4Source() {
1448e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (mStarted) {
1449e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        stop();
1450e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1451e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1452e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1453e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Source::start(MetaData *params) {
1454ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber    Mutex::Autolock autoLock(mLock);
1455ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber
14564f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    CHECK(!mStarted);
1457e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1458e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    int32_t val;
14594f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    if (params && params->findInt32(kKeyWantsNALFragments, &val)
1460e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        && val != 0) {
14614f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        mWantsNALFragments = true;
1462e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    } else {
14634f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        mWantsNALFragments = false;
1464e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1465e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1466e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mGroup = new MediaBufferGroup;
1467e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
14681bceff916a72246fa208605d50615823d7f1688bAndreas Huber    int32_t max_size;
14691bceff916a72246fa208605d50615823d7f1688bAndreas Huber    CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size));
1470e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
14711bceff916a72246fa208605d50615823d7f1688bAndreas Huber    mGroup->add_buffer(new MediaBuffer(max_size));
14728a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber
14738a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    mSrcBuffer = new uint8_t[max_size];
1474e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1475e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mStarted = true;
1476e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1477e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return OK;
1478e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1479e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1480e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Source::stop() {
1481ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber    Mutex::Autolock autoLock(mLock);
1482ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber
14834f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    CHECK(mStarted);
1484e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1485e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (mBuffer != NULL) {
1486e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        mBuffer->release();
1487e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        mBuffer = NULL;
1488e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1489e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
14908a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    delete[] mSrcBuffer;
14918a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    mSrcBuffer = NULL;
14928a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber
1493e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    delete mGroup;
1494e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mGroup = NULL;
1495e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1496e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mStarted = false;
1497e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mCurrentSampleIndex = 0;
1498e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1499e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return OK;
1500e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1501e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1502e46b7be812d68e49710b34048662cbf18e2a6550Andreas Hubersp<MetaData> MPEG4Source::getFormat() {
1503ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber    Mutex::Autolock autoLock(mLock);
1504ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber
1505e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return mFormat;
1506e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1507e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1508db5d662254f2ed788d32e2466739adc8d655c732Andreas Hubersize_t MPEG4Source::parseNALSize(const uint8_t *data) const {
1509db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    switch (mNALLengthSize) {
1510db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        case 1:
1511db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber            return *data;
1512db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        case 2:
1513db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber            return U16_AT(data);
1514db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        case 3:
1515db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber            return ((size_t)data[0] << 16) | U16_AT(&data[1]);
1516db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        case 4:
1517db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber            return U32_AT(data);
1518db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    }
1519db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
1520db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    // This cannot happen, mNALLengthSize springs to life by adding 1 to
1521db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    // a 2-bit integer.
1522db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    CHECK(!"Should not be here.");
1523db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
1524db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    return 0;
1525db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber}
1526db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
1527e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Source::read(
1528e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        MediaBuffer **out, const ReadOptions *options) {
1529ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber    Mutex::Autolock autoLock(mLock);
1530ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber
15314f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    CHECK(mStarted);
1532e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1533e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    *out = NULL;
1534e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
15356624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber    int64_t targetSampleTimeUs = -1;
15366624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber
1537e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    int64_t seekTimeUs;
15386624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber    ReadOptions::SeekMode mode;
15396624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
15406624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        uint32_t findFlags = 0;
15416624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        switch (mode) {
15426624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber            case ReadOptions::SEEK_PREVIOUS_SYNC:
15436624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber                findFlags = SampleTable::kFlagBefore;
15446624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber                break;
15456624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber            case ReadOptions::SEEK_NEXT_SYNC:
15466624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber                findFlags = SampleTable::kFlagAfter;
15476624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber                break;
15486624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber            case ReadOptions::SEEK_CLOSEST_SYNC:
15496624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber            case ReadOptions::SEEK_CLOSEST:
15506624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber                findFlags = SampleTable::kFlagClosest;
15516624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber                break;
15526624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber            default:
15536624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber                CHECK(!"Should not be here.");
15546624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber                break;
15556624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        }
15566624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber
1557e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        uint32_t sampleIndex;
15586624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        status_t err = mSampleTable->findSampleAtTime(
1559e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                seekTimeUs * mTimescale / 1000000,
15606624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber                &sampleIndex, findFlags);
15616624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber
15626624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
15636624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber            // We found the closest sample already, now we want the sync
15646624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber            // sample preceding it (or the sample itself of course), even
15656624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber            // if the subsequent sync sample is closer.
15666624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber            findFlags = SampleTable::kFlagBefore;
15676624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        }
15686624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber
15696624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        uint32_t syncSampleIndex;
15706624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        if (err == OK) {
15716624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber            err = mSampleTable->findSyncSampleNear(
15726624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber                    sampleIndex, &syncSampleIndex, findFlags);
15736624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        }
1574e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1575e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (err != OK) {
1576d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber            if (err == ERROR_OUT_OF_RANGE) {
1577d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber                // An attempt to seek past the end of the stream would
1578d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber                // normally cause this ERROR_OUT_OF_RANGE error. Propagating
1579d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber                // this all the way to the MediaPlayer would cause abnormal
1580d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber                // termination. Legacy behaviour appears to be to behave as if
1581d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber                // we had seeked to the end of stream, ending normally.
1582d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber                err = ERROR_END_OF_STREAM;
1583d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber            }
1584e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            return err;
1585e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
1586e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
15876624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        uint32_t sampleTime;
158831dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber        CHECK_EQ((status_t)OK, mSampleTable->getMetaDataForSample(
15896624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber                    sampleIndex, NULL, NULL, &sampleTime));
15906624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber
15916624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
15926624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber            targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
15936624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        }
15946624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber
15956624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber#if 0
15966624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        uint32_t syncSampleTime;
15976624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
15986624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber                    syncSampleIndex, NULL, NULL, &syncSampleTime));
15996624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber
16006624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        LOGI("seek to time %lld us => sample at time %lld us, "
16016624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber             "sync sample at time %lld us",
16026624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber             seekTimeUs,
16036624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber             sampleTime * 1000000ll / mTimescale,
16046624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber             syncSampleTime * 1000000ll / mTimescale);
16056624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber#endif
16066624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber
16076624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        mCurrentSampleIndex = syncSampleIndex;
1608e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (mBuffer != NULL) {
1609e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mBuffer->release();
1610e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mBuffer = NULL;
1611e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
1612e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1613e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        // fall through
1614e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1615e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
16168a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    off_t offset;
16178a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    size_t size;
16184f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    uint32_t dts;
1619ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber    bool isSyncSample;
16204f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    bool newBuffer = false;
16214f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    if (mBuffer == NULL) {
16224f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        newBuffer = true;
1623e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
16241faa92a1e93f311e86dca483ed7702091137de66Andreas Huber        status_t err =
16251faa92a1e93f311e86dca483ed7702091137de66Andreas Huber            mSampleTable->getMetaDataForSample(
1626ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber                    mCurrentSampleIndex, &offset, &size, &dts, &isSyncSample);
1627e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
16284f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        if (err != OK) {
16294f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            return err;
16304f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
16314f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
16324f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        err = mGroup->acquire_buffer(&mBuffer);
16331faa92a1e93f311e86dca483ed7702091137de66Andreas Huber
16344f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        if (err != OK) {
163531dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber            CHECK(mBuffer == NULL);
16364f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            return err;
16374f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
16388a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    }
1639e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
16404f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    if (!mIsAVC || mWantsNALFragments) {
16414f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        if (newBuffer) {
16424f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            ssize_t num_bytes_read =
16439a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
16444f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
16454f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            if (num_bytes_read < (ssize_t)size) {
16464f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber                mBuffer->release();
16474f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber                mBuffer = NULL;
16484f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
16494f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber                return ERROR_IO;
16504f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            }
16514f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
1652ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber            CHECK(mBuffer != NULL);
16534f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            mBuffer->set_range(0, size);
16544f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            mBuffer->meta_data()->clear();
1655fa8de752507feaca695123911915070c1ce463b2Andreas Huber            mBuffer->meta_data()->setInt64(
1656fa8de752507feaca695123911915070c1ce463b2Andreas Huber                    kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
16576624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber
16586624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber            if (targetSampleTimeUs >= 0) {
16596624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber                mBuffer->meta_data()->setInt64(
16606624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber                        kKeyTargetTime, targetSampleTimeUs);
16616624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber            }
16626624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber
1663ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber            if (isSyncSample) {
1664ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
1665ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber            }
1666ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber
16674f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            ++mCurrentSampleIndex;
16684f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
16694f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
16704f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        if (!mIsAVC) {
16714f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            *out = mBuffer;
16724f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            mBuffer = NULL;
16734f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
16744f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            return OK;
16754f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
16764f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
16774f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        // Each NAL unit is split up into its constituent fragments and
16784f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        // each one of them returned in its own buffer.
16794f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
1680db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        CHECK(mBuffer->range_length() >= mNALLengthSize);
16814f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
16824f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        const uint8_t *src =
16834f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
16844f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
1685db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        size_t nal_size = parseNALSize(src);
1686909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
1687909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber            LOGE("incomplete NAL unit.");
1688909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber
1689909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber            mBuffer->release();
1690909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber            mBuffer = NULL;
1691909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber
1692909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber            return ERROR_MALFORMED;
1693909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber        }
16944f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
16954f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        MediaBuffer *clone = mBuffer->clone();
1696ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber        CHECK(clone != NULL);
1697db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
16984f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
1699ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber        CHECK(mBuffer != NULL);
17004f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        mBuffer->set_range(
1701db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber                mBuffer->range_offset() + mNALLengthSize + nal_size,
1702db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber                mBuffer->range_length() - mNALLengthSize - nal_size);
17034f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
17044f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        if (mBuffer->range_length() == 0) {
17054f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            mBuffer->release();
17064f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            mBuffer = NULL;
17074f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
17084f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
17094f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        *out = clone;
17104f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
17114f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        return OK;
17124f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    } else {
17134f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        // Whole NAL units are returned but each fragment is prefixed by
17144f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        // the start code (0x00 00 00 01).
17154f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
1716e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        ssize_t num_bytes_read =
17179a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            mDataSource->readAt(offset, mSrcBuffer, size);
1718e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1719e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (num_bytes_read < (ssize_t)size) {
1720e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mBuffer->release();
1721e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mBuffer = NULL;
1722e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
17234f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            return ERROR_IO;
1724e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
1725e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
17264f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        uint8_t *dstData = (uint8_t *)mBuffer->data();
17274f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        size_t srcOffset = 0;
17284f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        size_t dstOffset = 0;
1729db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
17304f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        while (srcOffset < size) {
1731db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber            CHECK(srcOffset + mNALLengthSize <= size);
1732db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber            size_t nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
1733db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber            srcOffset += mNALLengthSize;
1734909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber
1735909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber            if (srcOffset + nalLength > size) {
1736909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber                mBuffer->release();
1737909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber                mBuffer = NULL;
1738909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber
1739909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber                return ERROR_MALFORMED;
1740909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber            }
17414f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
17424f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            if (nalLength == 0) {
17434f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber                continue;
17444f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            }
17454f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
17464f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            CHECK(dstOffset + 4 <= mBuffer->size());
17474f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
17484f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            dstData[dstOffset++] = 0;
17494f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            dstData[dstOffset++] = 0;
17504f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            dstData[dstOffset++] = 0;
17514f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            dstData[dstOffset++] = 1;
17524f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
17534f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            srcOffset += nalLength;
17544f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            dstOffset += nalLength;
17554f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
1756db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        CHECK_EQ(srcOffset, size);
17574f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
1758ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber        CHECK(mBuffer != NULL);
17594f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        mBuffer->set_range(0, dstOffset);
1760e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        mBuffer->meta_data()->clear();
1761fa8de752507feaca695123911915070c1ce463b2Andreas Huber        mBuffer->meta_data()->setInt64(
1762fa8de752507feaca695123911915070c1ce463b2Andreas Huber                kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
17636624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber
17646624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        if (targetSampleTimeUs >= 0) {
17656624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber            mBuffer->meta_data()->setInt64(
17666624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber                    kKeyTargetTime, targetSampleTimeUs);
17676624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber        }
17686624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber
1769ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber        if (isSyncSample) {
1770ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
1771ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber        }
1772ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber
1773e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        ++mCurrentSampleIndex;
1774e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1775e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        *out = mBuffer;
1776e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        mBuffer = NULL;
1777e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1778e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return OK;
1779e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1780e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1781e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1782261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huberstatic bool LegacySniffMPEG4(
1783be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
1784e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    uint8_t header[8];
1785e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
17869a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber    ssize_t n = source->readAt(4, header, sizeof(header));
1787e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (n < (ssize_t)sizeof(header)) {
1788e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return false;
1789e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1790e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1791e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
1792e1130662d0455231853e7d6880bb84d8547d7229James Dong        || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8)
1793e1130662d0455231853e7d6880bb84d8547d7229James Dong        || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8)
17946bce6d87b3fd98e68fb54328fb4dc8e40cd2c293Andreas Huber        || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
1795dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber        || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)
1796eea1eefeada90ec54488e1742e81e4226fc6ace5Andreas Huber        || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) {
1797e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber        *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
1798efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber        *confidence = 0.4;
1799e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1800e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return true;
1801e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1802e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1803e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return false;
1804e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1805e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1806261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huberstatic bool isCompatibleBrand(uint32_t fourcc) {
1807261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    static const uint32_t kCompatibleBrands[] = {
1808261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        FOURCC('i', 's', 'o', 'm'),
1809261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        FOURCC('i', 's', 'o', '2'),
1810261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        FOURCC('a', 'v', 'c', '1'),
1811261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        FOURCC('3', 'g', 'p', '4'),
1812261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        FOURCC('m', 'p', '4', '1'),
1813261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        FOURCC('m', 'p', '4', '2'),
1814261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    };
1815261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
1816261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    for (size_t i = 0;
1817261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber         i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]);
1818261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber         ++i) {
1819261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        if (kCompatibleBrands[i] == fourcc) {
1820261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber            return true;
1821261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        }
1822261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    }
1823261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
1824261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    return false;
1825261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber}
1826261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
1827261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber// Attempt to actually parse the 'ftyp' atom and determine if a suitable
1828261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber// compatible brand is present.
1829261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huberstatic bool BetterSniffMPEG4(
1830261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
1831261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    uint8_t header[12];
1832261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    if (source->readAt(0, header, 12) != 12
1833261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber            || memcmp("ftyp", &header[4], 4)) {
1834261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        return false;
1835261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    }
1836261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
1837261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    size_t atomSize = U32_AT(&header[0]);
1838261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    if (atomSize < 16 || (atomSize % 4) != 0) {
1839261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        return false;
1840261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    }
1841261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
1842261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    bool success = false;
1843261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    if (isCompatibleBrand(U32_AT(&header[8]))) {
1844261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        success = true;
1845261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    } else {
1846261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        size_t numCompatibleBrands = (atomSize - 16) / 4;
1847261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        for (size_t i = 0; i < numCompatibleBrands; ++i) {
1848261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber            uint8_t tmp[4];
1849261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber            if (source->readAt(16 + i * 4, tmp, 4) != 4) {
1850261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber                return false;
1851261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber            }
1852261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
1853261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber            if (isCompatibleBrand(U32_AT(&tmp[0]))) {
1854261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber                success = true;
1855261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber                break;
1856261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber            }
1857261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        }
1858261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    }
1859261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
1860261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    if (!success) {
1861261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        return false;
1862261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    }
1863261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
1864261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
1865efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber    *confidence = 0.4f;
1866261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
1867261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    return true;
1868261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber}
1869261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
1870261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huberbool SniffMPEG4(
1871efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
1872efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber        sp<AMessage> *) {
1873261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    if (BetterSniffMPEG4(source, mimeType, confidence)) {
1874261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        return true;
1875261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    }
1876261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
1877261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    if (LegacySniffMPEG4(source, mimeType, confidence)) {
1878261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        LOGW("Identified supported mpeg4 through LegacySniffMPEG4.");
1879261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        return true;
1880261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    }
1881261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
1882261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    return false;
1883261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber}
1884261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
1885e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}  // namespace android
1886e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1887