MPEG4Extractor.cpp revision cc14a8393b92cd1ed6cba74829396045605ab211
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
30e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/DataSource.h>
31d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber#include "include/ESDS.h"
32e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaBuffer.h>
33e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaBufferGroup.h>
344f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber#include <media/stagefright/MediaDebug.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'):
495e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 'k', 'i' ,'p'):
496c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('u', 'd', 't', 'a'):
497c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('i', 'l', 's', 't'):
498e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
499affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber            if (chunk_type == FOURCC('s', 't', 'b', 'l')) {
500affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                LOGV("sampleTable chunk is %d bytes long.", (size_t)chunk_size);
501affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
502affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                if (mDataSource->flags() & DataSource::kWantsPrefetching) {
503affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                    sp<MPEG4DataSource> cachedSource =
504affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                        new MPEG4DataSource(mDataSource);
505affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
506affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                    if (cachedSource->setCachedRange(*offset, chunk_size) == OK) {
507affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                        mDataSource = cachedSource;
508affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                    }
509affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                }
510eb9128f9b0ee660504621381fd96f82d5bf8a3fdAndreas Huber
511eb9128f9b0ee660504621381fd96f82d5bf8a3fdAndreas Huber                mLastTrack->sampleTable = new SampleTable(mDataSource);
512affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber            }
513affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
5144d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber            bool isTrack = false;
5155ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            if (chunk_type == FOURCC('t', 'r', 'a', 'k')) {
5164d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                isTrack = true;
5174d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber
5185ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                Track *track = new Track;
5195ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                track->next = NULL;
5205ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                if (mLastTrack) {
5215ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                    mLastTrack->next = track;
5225ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                } else {
5235ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                    mFirstTrack = track;
5245ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                }
5255ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                mLastTrack = track;
5265ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
5275ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                track->meta = new MetaData;
5285ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                track->includes_expensive_metadata = false;
5294d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                track->skipTrack = false;
5305ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                track->timescale = 0;
5315ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                track->meta->setCString(kKeyMIMEType, "application/octet-stream");
5325ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            }
5335ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
534e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            off_t stop_offset = *offset + chunk_size;
535e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset = data_offset;
536e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            while (*offset < stop_offset) {
537e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                status_t err = parseChunk(offset, depth + 1);
538e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (err != OK) {
539e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return err;
540e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
541e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
542e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
5435ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            if (*offset != stop_offset) {
5445ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                return ERROR_MALFORMED;
5455ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            }
5465ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
5474d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber            if (isTrack) {
5484d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                if (mLastTrack->skipTrack) {
5494d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                    Track *cur = mFirstTrack;
5504d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber
5514d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                    if (cur == mLastTrack) {
5524d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                        delete cur;
5534d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                        mFirstTrack = mLastTrack = NULL;
5544d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                    } else {
5554d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                        while (cur && cur->next != mLastTrack) {
5564d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                            cur = cur->next;
5574d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                        }
5584d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                        cur->next = NULL;
5594d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                        delete mLastTrack;
5604d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                        mLastTrack = cur;
5614d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                    }
5624d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber
5634d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                    return OK;
5644d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                }
5654d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber
5665ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                status_t err = verifyTrack(mLastTrack);
5675ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
5685ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                if (err != OK) {
5695ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                    return err;
5705ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                }
5715ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
572e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mHaveMetadata = true;
573e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
574e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return UNKNOWN_ERROR;  // Return a dummy error.
575e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
576e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
577e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
578e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
579e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('t', 'k', 'h', 'd'):
580e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
5815ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            if (chunk_data_size < 4) {
5825ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                return ERROR_MALFORMED;
5835ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            }
584e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
585e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t version;
5869a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(data_offset, &version, 1) < 1) {
587e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
588e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
589e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
590e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint64_t ctime, mtime, duration;
591e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            int32_t id;
592e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint32_t width, height;
593e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
594e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (version == 1) {
595e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (chunk_data_size != 36 + 60) {
596e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return ERROR_MALFORMED;
597e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
598e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
599e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                uint8_t buffer[36 + 60];
6009a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber                if (mDataSource->readAt(
601e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                            data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
602e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return ERROR_IO;
603e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
604e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
605e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                ctime = U64_AT(&buffer[4]);
606e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mtime = U64_AT(&buffer[12]);
607e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                id = U32_AT(&buffer[20]);
608e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                duration = U64_AT(&buffer[28]);
609e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                width = U32_AT(&buffer[88]);
610e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                height = U32_AT(&buffer[92]);
611e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            } else if (version == 0) {
612e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (chunk_data_size != 24 + 60) {
613e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return ERROR_MALFORMED;
614e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
615e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
616e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                uint8_t buffer[24 + 60];
6179a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber                if (mDataSource->readAt(
618e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                            data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
619e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return ERROR_IO;
620e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
621e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                ctime = U32_AT(&buffer[4]);
622e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mtime = U32_AT(&buffer[8]);
623e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                id = U32_AT(&buffer[12]);
624e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                duration = U32_AT(&buffer[20]);
625e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                width = U32_AT(&buffer[76]);
626e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                height = U32_AT(&buffer[80]);
627e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
628e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
629e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
630e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
631e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
632e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
633e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'd', 'h', 'd'):
634e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
635e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size < 4) {
636e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
637e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
638e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
639e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t version;
6409a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(
641e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, &version, sizeof(version))
642e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    < (ssize_t)sizeof(version)) {
643e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
644e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
645e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
646e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            off_t timescale_offset;
647e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
648e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (version == 1) {
649e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                timescale_offset = data_offset + 4 + 16;
650e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            } else if (version == 0) {
651e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                timescale_offset = data_offset + 4 + 8;
652e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            } else {
653e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
654e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
655e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
656e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint32_t timescale;
6579a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(
658e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        timescale_offset, &timescale, sizeof(timescale))
659e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    < (ssize_t)sizeof(timescale)) {
660e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
661e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
662e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
663e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->timescale = ntohl(timescale);
664e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
665e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            int64_t duration;
666e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (version == 1) {
6679a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber                if (mDataSource->readAt(
668e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                            timescale_offset + 4, &duration, sizeof(duration))
669e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        < (ssize_t)sizeof(duration)) {
670e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return ERROR_IO;
671e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
672e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                duration = ntoh64(duration);
673e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            } else {
674e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                int32_t duration32;
6759a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber                if (mDataSource->readAt(
676e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                            timescale_offset + 4, &duration32, sizeof(duration32))
677e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        < (ssize_t)sizeof(duration32)) {
678e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return ERROR_IO;
679e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
680e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                duration = ntohl(duration32);
681e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
682fa8de752507feaca695123911915070c1ce463b2Andreas Huber            mLastTrack->meta->setInt64(
683fa8de752507feaca695123911915070c1ce463b2Andreas Huber                    kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
684e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
685e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
686e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
687e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
688e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
689e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 's', 'd'):
690e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
691e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size < 8) {
692e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
693e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
694e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
695e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t buffer[8];
6965ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            if (chunk_data_size < (off_t)sizeof(buffer)) {
6975ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                return ERROR_MALFORMED;
6985ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            }
6995ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
7009a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(
701e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, buffer, 8) < 8) {
702e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
703e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
704e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
705e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (U32_AT(buffer) != 0) {
706e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // Should be version 0, flags 0.
707e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
708e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
709e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
710e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint32_t entry_count = U32_AT(&buffer[4]);
711e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
712e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (entry_count > 1) {
713e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // For now we only support a single type of media per track.
7144d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber
7154d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                mLastTrack->skipTrack = true;
7164d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                *offset += chunk_size;
7174d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber                break;
718e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
719e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
720e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            off_t stop_offset = *offset + chunk_size;
721e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset = data_offset + 8;
722e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            for (uint32_t i = 0; i < entry_count; ++i) {
723e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                status_t err = parseChunk(offset, depth + 1);
724e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (err != OK) {
725e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return err;
726e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
727e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
7285ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
7295ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            if (*offset != stop_offset) {
7305ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                return ERROR_MALFORMED;
7315ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            }
732e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
733e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
734e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
735e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
736e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
7372a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber        case FOURCC('s', 'a', 'w', 'b'):
738e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
739e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t buffer[8 + 20];
740e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
741e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // Basic AudioSampleEntry size.
742e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
743e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
744e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
7459a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(
746e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
747e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
748e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
749e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
750e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
751e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint16_t num_channels = U16_AT(&buffer[16]);
752e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
753d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber            uint16_t sample_size = U16_AT(&buffer[18]);
754d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber            uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
755d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber
756e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber            if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB,
757d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber                            FourCC2MIME(chunk_type))) {
758d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber                // AMR NB audio is always mono, 8kHz
759d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber                num_channels = 1;
760d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber                sample_rate = 8000;
761d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber            } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB,
762e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber                               FourCC2MIME(chunk_type))) {
763d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber                // AMR WB audio is always mono, 16kHz
764e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                num_channels = 1;
765d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber                sample_rate = 16000;
766e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
767e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
768d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber#if 0
769d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber            printf("*** coding='%s' %d channels, size %d, rate %d\n",
770d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber                   chunk, num_channels, sample_size, sample_rate);
771d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber#endif
772e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
773e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
774e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
775e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
776e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
777e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            off_t stop_offset = *offset + chunk_size;
778e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset = data_offset + sizeof(buffer);
779e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            while (*offset < stop_offset) {
780e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                status_t err = parseChunk(offset, depth + 1);
781e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (err != OK) {
782e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return err;
783e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
784e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
7855ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
7865ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            if (*offset != stop_offset) {
7875ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                return ERROR_MALFORMED;
7885ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            }
789e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
790e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
791e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
792e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
793e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', '2', '6', '3'):
794e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
795e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
7961cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber            mHasVideo = true;
7971cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber
798e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t buffer[78];
799e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
800e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // Basic VideoSampleEntry size.
801e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
802e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
803e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
8049a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(
805e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
806e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
807e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
808e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
809e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
810e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint16_t width = U16_AT(&buffer[6 + 18]);
811e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint16_t height = U16_AT(&buffer[6 + 20]);
812e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
8132ea14e231945afb6581fa8f54015b33bc74a19e5Andreas Huber            // printf("*** coding='%s' width=%d height=%d\n",
8142ea14e231945afb6581fa8f54015b33bc74a19e5Andreas Huber            //        chunk, width, height);
815e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
816e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
817e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setInt32(kKeyWidth, width);
818e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setInt32(kKeyHeight, height);
819e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
820e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            off_t stop_offset = *offset + chunk_size;
821e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset = data_offset + sizeof(buffer);
822e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            while (*offset < stop_offset) {
823e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                status_t err = parseChunk(offset, depth + 1);
824e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (err != OK) {
825e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return err;
826e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
827e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
8285ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
8295ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            if (*offset != stop_offset) {
8305ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                return ERROR_MALFORMED;
8315ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            }
832e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
833e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
834e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
835e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 'c', 'o'):
836e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('c', 'o', '6', '4'):
837e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
838e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            status_t err =
839e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mLastTrack->sampleTable->setChunkOffsetParams(
840e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        chunk_type, data_offset, chunk_data_size);
841e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
842e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (err != OK) {
843e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return err;
844e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
845e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
846e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
847e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
848e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
849e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
850e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 's', 'c'):
851e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
852e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            status_t err =
853e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mLastTrack->sampleTable->setSampleToChunkParams(
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', 'z'):
865e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 'z', '2'):
866e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
867e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            status_t err =
868e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mLastTrack->sampleTable->setSampleSizeParams(
869e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        chunk_type, data_offset, chunk_data_size);
870e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
871e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (err != OK) {
872e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return err;
873e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
874e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
8751bceff916a72246fa208605d50615823d7f1688bAndreas Huber            size_t max_size;
8761bceff916a72246fa208605d50615823d7f1688bAndreas Huber            CHECK_EQ(mLastTrack->sampleTable->getMaxSampleSize(&max_size), OK);
8771bceff916a72246fa208605d50615823d7f1688bAndreas Huber
8781bceff916a72246fa208605d50615823d7f1688bAndreas Huber            // Assume that a given buffer only contains at most 10 fragments,
8791bceff916a72246fa208605d50615823d7f1688bAndreas Huber            // each fragment originally prefixed with a 2 byte length will
8801bceff916a72246fa208605d50615823d7f1688bAndreas Huber            // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
8811bceff916a72246fa208605d50615823d7f1688bAndreas Huber            // and thus will grow by 2 bytes per fragment.
8821bceff916a72246fa208605d50615823d7f1688bAndreas Huber            mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
8831bceff916a72246fa208605d50615823d7f1688bAndreas Huber
884e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
885e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
886e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
887e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
888e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 't', 's'):
889e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
890e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            status_t err =
891e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mLastTrack->sampleTable->setTimeToSampleParams(
892e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, chunk_data_size);
893e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
894e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (err != OK) {
895e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return err;
896e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
897e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
898e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
899e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
900e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
901e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
902e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 's', 's'):
903e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
904e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            status_t err =
905e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mLastTrack->sampleTable->setSyncSampleParams(
906e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, chunk_data_size);
907e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
908e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (err != OK) {
909e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return err;
910e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
911e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
912e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
913e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
914e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
915e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
916e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('e', 's', 'd', 's'):
917e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
918e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size < 4) {
919e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
920e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
921e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
922e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t buffer[256];
923e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size > (off_t)sizeof(buffer)) {
924e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
925e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
926e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
9279a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(
928e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
929e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
930e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
931e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
932e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (U32_AT(buffer) != 0) {
933e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // Should be version 0, flags 0.
934e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
935e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
936e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
937e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setData(
938e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
939e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
940d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber            if (mPath.size() >= 2
941d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                    && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) {
942d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                // Information from the ESDS must be relied on for proper
943d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                // setup of sample rate and channel count for MPEG4 Audio.
944d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                // The generic header appears to only contain generic
945d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                // information...
946d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
947d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio(
948d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                        &buffer[4], chunk_data_size - 4);
949d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
950d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                if (err != OK) {
951d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                    return err;
952d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                }
953d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber            }
954d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
955e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
956e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
957e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
958e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
959e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('a', 'v', 'c', 'C'):
960e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
961e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            char buffer[256];
962e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size > (off_t)sizeof(buffer)) {
963e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
964e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
965e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
9669a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(
967e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
968e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
969e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
970e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
971e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setData(
972e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    kKeyAVCC, kTypeAVCC, buffer, chunk_data_size);
973e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
974e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
975e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
976e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
977e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
978c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('m', 'e', 't', 'a'):
979c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
980c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            uint8_t buffer[4];
9815ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            if (chunk_data_size < (off_t)sizeof(buffer)) {
9825ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                return ERROR_MALFORMED;
9835ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            }
9845ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
985c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (mDataSource->readAt(
986c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                        data_offset, buffer, 4) < 4) {
987c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                return ERROR_IO;
988c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
989c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
990c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (U32_AT(buffer) != 0) {
991c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                // Should be version 0, flags 0.
992dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber
993dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber                // If it's not, let's assume this is one of those
994dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber                // apparently malformed chunks that don't have flags
995dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber                // and completely different semantics than what's
996dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber                // in the MPEG4 specs and skip it.
997dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber                *offset += chunk_size;
998dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber                return OK;
999c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
1000c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1001c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            off_t stop_offset = *offset + chunk_size;
1002c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            *offset = data_offset + sizeof(buffer);
1003c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            while (*offset < stop_offset) {
1004c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                status_t err = parseChunk(offset, depth + 1);
1005c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                if (err != OK) {
1006c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                    return err;
1007c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                }
1008c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
10095ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
10105ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            if (*offset != stop_offset) {
10115ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                return ERROR_MALFORMED;
10125ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            }
1013c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1014c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1015c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1016c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('d', 'a', 't', 'a'):
1017c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1018c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (mPath.size() == 6 && underMetaDataPath(mPath)) {
1019c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                status_t err = parseMetaData(data_offset, chunk_data_size);
1020c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1021c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                if (err != OK) {
1022c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                    return err;
1023c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                }
1024c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
1025c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1026c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            *offset += chunk_size;
1027c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1028c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1029c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1030c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('m', 'v', 'h', 'd'):
1031c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1032c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (chunk_data_size < 12) {
1033c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                return ERROR_MALFORMED;
1034c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
1035c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1036c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            uint8_t header[12];
1037c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (mDataSource->readAt(
1038c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                        data_offset, header, sizeof(header))
1039c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                    < (ssize_t)sizeof(header)) {
1040c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                return ERROR_IO;
1041c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
1042c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1043c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            int64_t creationTime;
1044c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (header[0] == 1) {
1045c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                creationTime = U64_AT(&header[4]);
10465ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            } else if (header[0] != 0) {
10475ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                return ERROR_MALFORMED;
1048c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            } else {
1049c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                creationTime = U32_AT(&header[4]);
1050c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
1051c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1052c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            String8 s;
1053c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            convertTimeToDate(creationTime, &s);
1054c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1055c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            mFileMetaData->setCString(kKeyDate, s.string());
1056c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1057c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            *offset += chunk_size;
1058c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1059c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1060c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1061e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        default:
1062e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
1063e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
1064e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
1065e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
1066e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1067e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1068e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return OK;
1069e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1070e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1071c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huberstatus_t MPEG4Extractor::parseMetaData(off_t offset, size_t size) {
1072c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    if (size < 4) {
1073c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        return ERROR_MALFORMED;
1074c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    }
1075c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1076c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    uint8_t *buffer = new uint8_t[size + 1];
1077c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    if (mDataSource->readAt(
1078c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                offset, buffer, size) != (ssize_t)size) {
1079c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        delete[] buffer;
1080c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        buffer = NULL;
1081c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1082c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        return ERROR_IO;
1083c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    }
1084c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1085c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    uint32_t flags = U32_AT(buffer);
1086c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1087c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    uint32_t metadataKey = 0;
1088c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    switch (mPath[4]) {
1089c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC(0xa9, 'a', 'l', 'b'):
1090c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1091c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            metadataKey = kKeyAlbum;
1092c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1093c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1094c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC(0xa9, 'A', 'R', 'T'):
1095c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1096c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            metadataKey = kKeyArtist;
1097c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1098c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1099c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen        case FOURCC('a', 'A', 'R', 'T'):
1100c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen        {
1101c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen            metadataKey = kKeyAlbumArtist;
1102c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen            break;
1103c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen        }
1104c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC(0xa9, 'd', 'a', 'y'):
1105c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1106c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            metadataKey = kKeyYear;
1107c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1108c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1109c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC(0xa9, 'n', 'a', 'm'):
1110c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1111c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            metadataKey = kKeyTitle;
1112c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1113c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1114c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC(0xa9, 'w', 'r', 't'):
1115c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1116c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            metadataKey = kKeyWriter;
1117c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1118c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1119c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('c', 'o', 'v', 'r'):
1120c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1121c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            metadataKey = kKeyAlbumArt;
1122c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1123c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1124c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('g', 'n', 'r', 'e'):
1125c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1126c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            metadataKey = kKeyGenre;
1127c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1128c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1129fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen        case FOURCC(0xa9, 'g', 'e', 'n'):
1130fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen        {
1131fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen            metadataKey = kKeyGenre;
1132fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen            break;
1133fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen        }
1134c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('t', 'r', 'k', 'n'):
1135c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1136c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (size == 16 && flags == 0) {
1137c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                char tmp[16];
1138c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                sprintf(tmp, "%d/%d",
1139c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                        (int)buffer[size - 5], (int)buffer[size - 3]);
1140c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1141c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
1142c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
1143c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1144c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1145fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen        case FOURCC('d', 'i', 's', 'k'):
1146fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen        {
1147fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen            if (size == 14 && flags == 0) {
1148fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                char tmp[16];
1149fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                sprintf(tmp, "%d/%d",
1150fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                        (int)buffer[size - 3], (int)buffer[size - 1]);
1151fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen
1152fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                mFileMetaData->setCString(kKeyDiscNumber, tmp);
1153fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen            }
1154fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen            break;
1155fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen        }
1156fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen
1157c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        default:
1158c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1159c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    }
1160c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1161c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    if (size >= 8 && metadataKey) {
1162c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        if (metadataKey == kKeyAlbumArt) {
1163c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            mFileMetaData->setData(
1164c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                    kKeyAlbumArt, MetaData::TYPE_NONE,
1165c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                    buffer + 8, size - 8);
1166c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        } else if (metadataKey == kKeyGenre) {
1167c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (flags == 0) {
1168fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                // uint8_t genre code, iTunes genre codes are
1169fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                // the standard id3 codes, except they start
1170fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                // at 1 instead of 0 (e.g. Pop is 14, not 13)
1171fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                // We use standard id3 numbering, so subtract 1.
1172fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                int genrecode = (int)buffer[size - 1];
1173fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                genrecode--;
1174fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                if (genrecode < 0) {
1175fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                    genrecode = 255; // reserved for 'unknown genre'
1176fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                }
1177c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                char genre[10];
1178fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                sprintf(genre, "%d", genrecode);
1179c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1180c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                mFileMetaData->setCString(metadataKey, genre);
1181fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen            } else if (flags == 1) {
1182fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                // custom genre string
1183fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                buffer[size] = '\0';
1184fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen
1185fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                mFileMetaData->setCString(
1186fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                        metadataKey, (const char *)buffer + 8);
1187c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
1188c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        } else {
1189c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            buffer[size] = '\0';
1190c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1191c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            mFileMetaData->setCString(
1192c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                    metadataKey, (const char *)buffer + 8);
1193c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1194c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    }
1195c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1196c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    delete[] buffer;
1197c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    buffer = NULL;
1198c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1199c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    return OK;
1200c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber}
1201c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1202be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
1203e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    status_t err;
1204e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if ((err = readMetaData()) != OK) {
1205be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber        return NULL;
1206e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1207e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1208e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    Track *track = mFirstTrack;
1209e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    while (index > 0) {
1210e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (track == NULL) {
1211be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber            return NULL;
1212e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
1213e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1214e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        track = track->next;
1215e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        --index;
1216e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1217e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
12182a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber    if (track == NULL) {
12192a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber        return NULL;
12202a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber    }
12212a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber
1222be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber    return new MPEG4Source(
1223fa8de752507feaca695123911915070c1ce463b2Andreas Huber            track->meta, mDataSource, track->timescale, track->sampleTable);
1224e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1225e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
12265ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber// static
12275ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huberstatus_t MPEG4Extractor::verifyTrack(Track *track) {
12285ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber    const char *mime;
12295ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber    CHECK(track->meta->findCString(kKeyMIMEType, &mime));
12305ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
12315ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber    uint32_t type;
12325ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber    const void *data;
12335ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber    size_t size;
12345ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
12355ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber        if (!track->meta->findData(kKeyAVCC, &type, &data, &size)
12365ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                || type != kTypeAVCC) {
12375ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            return ERROR_MALFORMED;
12385ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber        }
12395ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
12405ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
12415ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber        if (!track->meta->findData(kKeyESDS, &type, &data, &size)
12425ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber                || type != kTypeESDS) {
12435ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber            return ERROR_MALFORMED;
12445ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber        }
12455ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber    }
12465ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
12475ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber    return OK;
12485ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber}
12495ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber
1250d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huberstatus_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(
1251d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        const void *esds_data, size_t esds_size) {
1252d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    ESDS esds(esds_data, esds_size);
1253d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber
1254d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber    uint8_t objectTypeIndication;
1255d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber    if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) {
1256d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber        return ERROR_MALFORMED;
1257d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber    }
1258d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber
1259d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber    if (objectTypeIndication == 0xe1) {
1260d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber        // This isn't MPEG4 audio at all, it's QCELP 14k...
1261d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber        mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
1262d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber        return OK;
1263d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber    }
1264d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber
1265d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    const uint8_t *csd;
1266d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    size_t csd_size;
1267d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    if (esds.getCodecSpecificInfo(
1268d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                (const void **)&csd, &csd_size) != OK) {
1269d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        return ERROR_MALFORMED;
1270d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    }
1271d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1272d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber#if 0
1273d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    printf("ESD of size %d\n", csd_size);
1274d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    hexdump(csd, csd_size);
1275d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber#endif
1276d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1277d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    if (csd_size < 2) {
1278d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        return ERROR_MALFORMED;
1279d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    }
1280d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1281d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    uint32_t objectType = csd[0] >> 3;
1282d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1283d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    if (objectType == 31) {
1284d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        return ERROR_UNSUPPORTED;
1285d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    }
1286d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1287d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    uint32_t freqIndex = (csd[0] & 7) << 1 | (csd[1] >> 7);
1288d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    int32_t sampleRate = 0;
1289d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    int32_t numChannels = 0;
1290d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    if (freqIndex == 15) {
1291d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        if (csd_size < 5) {
1292d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber            return ERROR_MALFORMED;
1293d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        }
1294d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1295d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        sampleRate = (csd[1] & 0x7f) << 17
1296d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                        | csd[2] << 9
1297d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                        | csd[3] << 1
1298d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                        | (csd[4] >> 7);
1299d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1300d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        numChannels = (csd[4] >> 3) & 15;
1301d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    } else {
1302cc14a8393b92cd1ed6cba74829396045605ab211Andreas Huber        static uint32_t kSamplingRate[] = {
1303cc14a8393b92cd1ed6cba74829396045605ab211Andreas Huber            96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
1304cc14a8393b92cd1ed6cba74829396045605ab211Andreas Huber            16000, 12000, 11025, 8000, 7350
1305cc14a8393b92cd1ed6cba74829396045605ab211Andreas Huber        };
1306d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1307d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        if (freqIndex == 13 || freqIndex == 14) {
1308d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber            return ERROR_MALFORMED;
1309d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        }
1310d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1311d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        sampleRate = kSamplingRate[freqIndex];
1312d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        numChannels = (csd[1] >> 3) & 15;
1313d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    }
1314d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1315d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    if (numChannels == 0) {
1316d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        return ERROR_UNSUPPORTED;
1317d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    }
1318d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1319d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    int32_t prevSampleRate;
1320d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));
1321d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1322d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    if (prevSampleRate != sampleRate) {
13234a9375ef2a06fc36ec308835ef9e7e4eea2ba69fAndreas Huber        LOGV("mpeg4 audio sample rate different from previous setting. "
1324d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber             "was: %d, now: %d", prevSampleRate, sampleRate);
1325d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    }
1326d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1327d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
1328d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1329d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    int32_t prevChannelCount;
1330d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount));
1331d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1332d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    if (prevChannelCount != numChannels) {
13334a9375ef2a06fc36ec308835ef9e7e4eea2ba69fAndreas Huber        LOGV("mpeg4 audio channel count different from previous setting. "
1334d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber             "was: %d, now: %d", prevChannelCount, numChannels);
1335d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    }
1336d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1337d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    mLastTrack->meta->setInt32(kKeyChannelCount, numChannels);
1338d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1339d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    return OK;
1340d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber}
1341d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1342e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber////////////////////////////////////////////////////////////////////////////////
1343e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1344e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberMPEG4Source::MPEG4Source(
1345e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        const sp<MetaData> &format,
1346be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber        const sp<DataSource> &dataSource,
1347fa8de752507feaca695123911915070c1ce463b2Andreas Huber        int32_t timeScale,
1348be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber        const sp<SampleTable> &sampleTable)
1349e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    : mFormat(format),
1350e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mDataSource(dataSource),
1351fa8de752507feaca695123911915070c1ce463b2Andreas Huber      mTimescale(timeScale),
1352e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mSampleTable(sampleTable),
1353e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mCurrentSampleIndex(0),
1354e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mIsAVC(false),
1355db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber      mNALLengthSize(0),
1356e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mStarted(false),
1357e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mGroup(NULL),
1358e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mBuffer(NULL),
13594f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber      mWantsNALFragments(false),
13608a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber      mSrcBuffer(NULL) {
1361e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    const char *mime;
1362e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    bool success = mFormat->findCString(kKeyMIMEType, &mime);
13634f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    CHECK(success);
1364e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1365e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber    mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
1366db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
1367db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    if (mIsAVC) {
1368db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        uint32_t type;
1369db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        const void *data;
1370db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        size_t size;
1371db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        CHECK(format->findData(kKeyAVCC, &type, &data, &size));
1372db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
1373db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        const uint8_t *ptr = (const uint8_t *)data;
1374db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
1375db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        CHECK(size >= 7);
1376db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        CHECK_EQ(ptr[0], 1);  // configurationVersion == 1
1377db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
1378db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        // The number of bytes used to encode the length of a NAL unit.
1379db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        mNALLengthSize = 1 + (ptr[4] & 3);
1380db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    }
1381e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1382e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1383e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberMPEG4Source::~MPEG4Source() {
1384e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (mStarted) {
1385e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        stop();
1386e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1387e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1388e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1389e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Source::start(MetaData *params) {
1390ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber    Mutex::Autolock autoLock(mLock);
1391ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber
13924f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    CHECK(!mStarted);
1393e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1394e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    int32_t val;
13954f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    if (params && params->findInt32(kKeyWantsNALFragments, &val)
1396e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        && val != 0) {
13974f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        mWantsNALFragments = true;
1398e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    } else {
13994f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        mWantsNALFragments = false;
1400e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1401e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1402e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mGroup = new MediaBufferGroup;
1403e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
14041bceff916a72246fa208605d50615823d7f1688bAndreas Huber    int32_t max_size;
14051bceff916a72246fa208605d50615823d7f1688bAndreas Huber    CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size));
1406e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
14071bceff916a72246fa208605d50615823d7f1688bAndreas Huber    mGroup->add_buffer(new MediaBuffer(max_size));
14088a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber
14098a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    mSrcBuffer = new uint8_t[max_size];
1410e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1411e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mStarted = true;
1412e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1413e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return OK;
1414e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1415e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1416e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Source::stop() {
1417ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber    Mutex::Autolock autoLock(mLock);
1418ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber
14194f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    CHECK(mStarted);
1420e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1421e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (mBuffer != NULL) {
1422e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        mBuffer->release();
1423e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        mBuffer = NULL;
1424e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1425e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
14268a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    delete[] mSrcBuffer;
14278a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    mSrcBuffer = NULL;
14288a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber
1429e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    delete mGroup;
1430e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mGroup = NULL;
1431e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1432e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mStarted = false;
1433e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mCurrentSampleIndex = 0;
1434e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1435e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return OK;
1436e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1437e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1438e46b7be812d68e49710b34048662cbf18e2a6550Andreas Hubersp<MetaData> MPEG4Source::getFormat() {
1439ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber    Mutex::Autolock autoLock(mLock);
1440ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber
1441e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return mFormat;
1442e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1443e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1444db5d662254f2ed788d32e2466739adc8d655c732Andreas Hubersize_t MPEG4Source::parseNALSize(const uint8_t *data) const {
1445db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    switch (mNALLengthSize) {
1446db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        case 1:
1447db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber            return *data;
1448db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        case 2:
1449db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber            return U16_AT(data);
1450db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        case 3:
1451db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber            return ((size_t)data[0] << 16) | U16_AT(&data[1]);
1452db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        case 4:
1453db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber            return U32_AT(data);
1454db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    }
1455db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
1456db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    // This cannot happen, mNALLengthSize springs to life by adding 1 to
1457db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    // a 2-bit integer.
1458db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    CHECK(!"Should not be here.");
1459db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
1460db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    return 0;
1461db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber}
1462db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
1463e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Source::read(
1464e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        MediaBuffer **out, const ReadOptions *options) {
1465ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber    Mutex::Autolock autoLock(mLock);
1466ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber
14674f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    CHECK(mStarted);
1468e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1469e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    *out = NULL;
1470e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1471e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    int64_t seekTimeUs;
1472e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (options && options->getSeekTo(&seekTimeUs)) {
1473e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        uint32_t sampleIndex;
1474e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        status_t err = mSampleTable->findClosestSample(
1475e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                seekTimeUs * mTimescale / 1000000,
1476e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                &sampleIndex, SampleTable::kSyncSample_Flag);
1477e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1478e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (err != OK) {
1479d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber            if (err == ERROR_OUT_OF_RANGE) {
1480d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber                // An attempt to seek past the end of the stream would
1481d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber                // normally cause this ERROR_OUT_OF_RANGE error. Propagating
1482d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber                // this all the way to the MediaPlayer would cause abnormal
1483d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber                // termination. Legacy behaviour appears to be to behave as if
1484d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber                // we had seeked to the end of stream, ending normally.
1485d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber                err = ERROR_END_OF_STREAM;
1486d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber            }
1487e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            return err;
1488e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
1489e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1490e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        mCurrentSampleIndex = sampleIndex;
1491e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (mBuffer != NULL) {
1492e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mBuffer->release();
1493e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mBuffer = NULL;
1494e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
1495e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1496e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        // fall through
1497e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1498e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
14998a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    off_t offset;
15008a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    size_t size;
15014f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    uint32_t dts;
15024f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    bool newBuffer = false;
15034f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    if (mBuffer == NULL) {
15044f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        newBuffer = true;
1505e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
15061faa92a1e93f311e86dca483ed7702091137de66Andreas Huber        status_t err =
15071faa92a1e93f311e86dca483ed7702091137de66Andreas Huber            mSampleTable->getMetaDataForSample(
15081faa92a1e93f311e86dca483ed7702091137de66Andreas Huber                    mCurrentSampleIndex, &offset, &size, &dts);
1509e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
15104f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        if (err != OK) {
15114f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            return err;
15124f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
15134f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
15144f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        err = mGroup->acquire_buffer(&mBuffer);
15151faa92a1e93f311e86dca483ed7702091137de66Andreas Huber
15164f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        if (err != OK) {
15174f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            CHECK_EQ(mBuffer, NULL);
15184f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            return err;
15194f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
15208a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    }
1521e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
15224f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    if (!mIsAVC || mWantsNALFragments) {
15234f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        if (newBuffer) {
15244f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            ssize_t num_bytes_read =
15259a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
15264f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
15274f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            if (num_bytes_read < (ssize_t)size) {
15284f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber                mBuffer->release();
15294f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber                mBuffer = NULL;
15304f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
15314f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber                return ERROR_IO;
15324f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            }
15334f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
1534ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber            CHECK(mBuffer != NULL);
15354f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            mBuffer->set_range(0, size);
15364f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            mBuffer->meta_data()->clear();
1537fa8de752507feaca695123911915070c1ce463b2Andreas Huber            mBuffer->meta_data()->setInt64(
1538fa8de752507feaca695123911915070c1ce463b2Andreas Huber                    kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
15394f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            ++mCurrentSampleIndex;
15404f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
15414f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
15424f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        if (!mIsAVC) {
15434f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            *out = mBuffer;
15444f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            mBuffer = NULL;
15454f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
15464f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            return OK;
15474f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
15484f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
15494f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        // Each NAL unit is split up into its constituent fragments and
15504f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        // each one of them returned in its own buffer.
15514f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
1552db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        CHECK(mBuffer->range_length() >= mNALLengthSize);
15534f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
15544f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        const uint8_t *src =
15554f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
15564f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
1557db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        size_t nal_size = parseNALSize(src);
1558909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
1559909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber            LOGE("incomplete NAL unit.");
1560909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber
1561909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber            mBuffer->release();
1562909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber            mBuffer = NULL;
1563909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber
1564909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber            return ERROR_MALFORMED;
1565909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber        }
15664f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
15674f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        MediaBuffer *clone = mBuffer->clone();
1568ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber        CHECK(clone != NULL);
1569db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
15704f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
1571ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber        CHECK(mBuffer != NULL);
15724f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        mBuffer->set_range(
1573db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber                mBuffer->range_offset() + mNALLengthSize + nal_size,
1574db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber                mBuffer->range_length() - mNALLengthSize - nal_size);
15754f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
15764f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        if (mBuffer->range_length() == 0) {
15774f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            mBuffer->release();
15784f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            mBuffer = NULL;
15794f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
15804f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
15814f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        *out = clone;
15824f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
15834f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        return OK;
15844f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    } else {
15854f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        // Whole NAL units are returned but each fragment is prefixed by
15864f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        // the start code (0x00 00 00 01).
15874f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
1588e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        ssize_t num_bytes_read =
15899a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            mDataSource->readAt(offset, mSrcBuffer, size);
1590e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1591e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (num_bytes_read < (ssize_t)size) {
1592e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mBuffer->release();
1593e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mBuffer = NULL;
1594e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
15954f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            return ERROR_IO;
1596e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
1597e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
15984f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        uint8_t *dstData = (uint8_t *)mBuffer->data();
15994f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        size_t srcOffset = 0;
16004f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        size_t dstOffset = 0;
1601db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
16024f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        while (srcOffset < size) {
1603db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber            CHECK(srcOffset + mNALLengthSize <= size);
1604db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber            size_t nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
1605db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber            srcOffset += mNALLengthSize;
1606909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber
1607909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber            if (srcOffset + nalLength > size) {
1608909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber                mBuffer->release();
1609909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber                mBuffer = NULL;
1610909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber
1611909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber                return ERROR_MALFORMED;
1612909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber            }
16134f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
16144f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            if (nalLength == 0) {
16154f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber                continue;
16164f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            }
16174f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
16184f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            CHECK(dstOffset + 4 <= mBuffer->size());
16194f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
16204f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            dstData[dstOffset++] = 0;
16214f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            dstData[dstOffset++] = 0;
16224f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            dstData[dstOffset++] = 0;
16234f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            dstData[dstOffset++] = 1;
16244f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
16254f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            srcOffset += nalLength;
16264f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            dstOffset += nalLength;
16274f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
1628db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        CHECK_EQ(srcOffset, size);
16294f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
1630ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber        CHECK(mBuffer != NULL);
16314f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        mBuffer->set_range(0, dstOffset);
1632e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        mBuffer->meta_data()->clear();
1633fa8de752507feaca695123911915070c1ce463b2Andreas Huber        mBuffer->meta_data()->setInt64(
1634fa8de752507feaca695123911915070c1ce463b2Andreas Huber                kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
1635e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        ++mCurrentSampleIndex;
1636e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1637e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        *out = mBuffer;
1638e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        mBuffer = NULL;
1639e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1640e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return OK;
1641e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1642e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1643e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1644261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huberstatic bool LegacySniffMPEG4(
1645be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
1646e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    uint8_t header[8];
1647e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
16489a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber    ssize_t n = source->readAt(4, header, sizeof(header));
1649e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (n < (ssize_t)sizeof(header)) {
1650e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return false;
1651e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1652e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1653e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
1654e1130662d0455231853e7d6880bb84d8547d7229James Dong        || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8)
1655e1130662d0455231853e7d6880bb84d8547d7229James Dong        || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8)
16566bce6d87b3fd98e68fb54328fb4dc8e40cd2c293Andreas Huber        || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
1657dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber        || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)
1658eea1eefeada90ec54488e1742e81e4226fc6ace5Andreas Huber        || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) {
1659e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber        *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
1660e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        *confidence = 0.1;
1661e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1662e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return true;
1663e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1664e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1665e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return false;
1666e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1667e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1668261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huberstatic bool isCompatibleBrand(uint32_t fourcc) {
1669261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    static const uint32_t kCompatibleBrands[] = {
1670261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        FOURCC('i', 's', 'o', 'm'),
1671261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        FOURCC('i', 's', 'o', '2'),
1672261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        FOURCC('a', 'v', 'c', '1'),
1673261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        FOURCC('3', 'g', 'p', '4'),
1674261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        FOURCC('m', 'p', '4', '1'),
1675261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        FOURCC('m', 'p', '4', '2'),
1676261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    };
1677261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
1678261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    for (size_t i = 0;
1679261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber         i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]);
1680261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber         ++i) {
1681261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        if (kCompatibleBrands[i] == fourcc) {
1682261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber            return true;
1683261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        }
1684261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    }
1685261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
1686261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    return false;
1687261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber}
1688261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
1689261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber// Attempt to actually parse the 'ftyp' atom and determine if a suitable
1690261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber// compatible brand is present.
1691261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huberstatic bool BetterSniffMPEG4(
1692261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
1693261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    uint8_t header[12];
1694261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    if (source->readAt(0, header, 12) != 12
1695261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber            || memcmp("ftyp", &header[4], 4)) {
1696261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        return false;
1697261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    }
1698261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
1699261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    size_t atomSize = U32_AT(&header[0]);
1700261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    if (atomSize < 16 || (atomSize % 4) != 0) {
1701261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        return false;
1702261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    }
1703261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
1704261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    bool success = false;
1705261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    if (isCompatibleBrand(U32_AT(&header[8]))) {
1706261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        success = true;
1707261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    } else {
1708261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        size_t numCompatibleBrands = (atomSize - 16) / 4;
1709261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        for (size_t i = 0; i < numCompatibleBrands; ++i) {
1710261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber            uint8_t tmp[4];
1711261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber            if (source->readAt(16 + i * 4, tmp, 4) != 4) {
1712261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber                return false;
1713261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber            }
1714261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
1715261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber            if (isCompatibleBrand(U32_AT(&tmp[0]))) {
1716261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber                success = true;
1717261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber                break;
1718261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber            }
1719261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        }
1720261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    }
1721261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
1722261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    if (!success) {
1723261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        return false;
1724261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    }
1725261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
1726261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
1727261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    *confidence = 0.3f;
1728261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
1729261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    return true;
1730261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber}
1731261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
1732261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huberbool SniffMPEG4(
1733261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
1734261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    if (BetterSniffMPEG4(source, mimeType, confidence)) {
1735261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        return true;
1736261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    }
1737261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
1738261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    if (LegacySniffMPEG4(source, mimeType, confidence)) {
1739261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        LOGW("Identified supported mpeg4 through LegacySniffMPEG4.");
1740261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber        return true;
1741261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    }
1742261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
1743261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber    return false;
1744261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber}
1745261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber
1746e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}  // namespace android
1747e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1748