MPEG4Extractor.cpp revision ba7ec917ea91364598de1ba7a29910cec08fd5de
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;
431e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
432e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
433e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    char chunk[5];
434e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    MakeFourCCString(chunk_type, chunk);
435e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
436e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#if 0
437e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    static const char kWhitespace[] = "                                        ";
438e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth];
439e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    printf("%sfound chunk '%s' of size %lld\n", indent, chunk, chunk_size);
440e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
441e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    char buffer[256];
442e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (chunk_size <= sizeof(buffer)) {
443c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        if (mDataSource->readAt(*offset, buffer, chunk_size)
444c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                < (ssize_t)chunk_size) {
445e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            return ERROR_IO;
446e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
447e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
448e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        hexdump(buffer, chunk_size);
449e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
450e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#endif
451e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
452c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    PathAdder autoAdder(&mPath, chunk_type);
453c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
454e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    off_t chunk_data_size = *offset + chunk_size - data_offset;
455e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
456c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    if (chunk_type != FOURCC('c', 'p', 'r', 't')
457c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            && mPath.size() == 5 && underMetaDataPath(mPath)) {
458c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        off_t stop_offset = *offset + chunk_size;
459c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        *offset = data_offset;
460c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        while (*offset < stop_offset) {
461c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            status_t err = parseChunk(offset, depth + 1);
462c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (err != OK) {
463c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                return err;
464c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
465c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
466c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        CHECK_EQ(*offset, stop_offset);
467c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
468c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        return OK;
469c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    }
470c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
471e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    switch(chunk_type) {
472e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'o', 'o', 'v'):
473e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('t', 'r', 'a', 'k'):
474e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'd', 'i', 'a'):
475e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'i', 'n', 'f'):
476e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('d', 'i', 'n', 'f'):
477e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 'b', 'l'):
478e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'v', 'e', 'x'):
479e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'o', 'o', 'f'):
480e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('t', 'r', 'a', 'f'):
481e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'f', 'r', 'a'):
482e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 'k', 'i' ,'p'):
483c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('u', 'd', 't', 'a'):
484c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('i', 'l', 's', 't'):
485e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
486affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber            if (chunk_type == FOURCC('s', 't', 'b', 'l')) {
487affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                LOGV("sampleTable chunk is %d bytes long.", (size_t)chunk_size);
488affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
489affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                if (mDataSource->flags() & DataSource::kWantsPrefetching) {
490affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                    sp<MPEG4DataSource> cachedSource =
491affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                        new MPEG4DataSource(mDataSource);
492affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
493affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                    if (cachedSource->setCachedRange(*offset, chunk_size) == OK) {
494affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                        mDataSource = cachedSource;
495affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                    }
496affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber                }
497affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber            }
498affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber
499e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            off_t stop_offset = *offset + chunk_size;
500e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset = data_offset;
501e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            while (*offset < stop_offset) {
502e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                status_t err = parseChunk(offset, depth + 1);
503e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (err != OK) {
504e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return err;
505e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
506e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
5074f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            CHECK_EQ(*offset, stop_offset);
508e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
509e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
510e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mHaveMetadata = true;
511e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
512e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return UNKNOWN_ERROR;  // Return a dummy error.
513e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
514e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
515e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
516e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
517e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('t', 'k', 'h', 'd'):
518e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
5194f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            CHECK(chunk_data_size >= 4);
520e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
521e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t version;
5229a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(data_offset, &version, 1) < 1) {
523e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
524e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
525e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
526e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint64_t ctime, mtime, duration;
527e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            int32_t id;
528e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint32_t width, height;
529e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
530e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (version == 1) {
531e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (chunk_data_size != 36 + 60) {
532e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return ERROR_MALFORMED;
533e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
534e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
535e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                uint8_t buffer[36 + 60];
5369a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber                if (mDataSource->readAt(
537e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                            data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
538e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return ERROR_IO;
539e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
540e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
541e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                ctime = U64_AT(&buffer[4]);
542e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mtime = U64_AT(&buffer[12]);
543e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                id = U32_AT(&buffer[20]);
544e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                duration = U64_AT(&buffer[28]);
545e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                width = U32_AT(&buffer[88]);
546e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                height = U32_AT(&buffer[92]);
547e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            } else if (version == 0) {
548e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (chunk_data_size != 24 + 60) {
549e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return ERROR_MALFORMED;
550e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
551e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
552e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                uint8_t buffer[24 + 60];
5539a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber                if (mDataSource->readAt(
554e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                            data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
555e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return ERROR_IO;
556e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
557e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                ctime = U32_AT(&buffer[4]);
558e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mtime = U32_AT(&buffer[8]);
559e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                id = U32_AT(&buffer[12]);
560e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                duration = U32_AT(&buffer[20]);
561e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                width = U32_AT(&buffer[76]);
562e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                height = U32_AT(&buffer[80]);
563e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
564e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
565e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            Track *track = new Track;
566e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            track->next = NULL;
567e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (mLastTrack) {
568e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mLastTrack->next = track;
569e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            } else {
570e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mFirstTrack = track;
571e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
572e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack = track;
573e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
574e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            track->meta = new MetaData;
575e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber            track->includes_expensive_metadata = false;
576e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            track->timescale = 0;
577e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            track->sampleTable = new SampleTable(mDataSource);
578e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            track->meta->setCString(kKeyMIMEType, "application/octet-stream");
579e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
580e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
581e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
582e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
583e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
584e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'd', 'h', 'd'):
585e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
586e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size < 4) {
587e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
588e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
589e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
590e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t version;
5919a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(
592e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, &version, sizeof(version))
593e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    < (ssize_t)sizeof(version)) {
594e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
595e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
596e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
597e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            off_t timescale_offset;
598e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
599e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (version == 1) {
600e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                timescale_offset = data_offset + 4 + 16;
601e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            } else if (version == 0) {
602e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                timescale_offset = data_offset + 4 + 8;
603e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            } else {
604e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
605e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
606e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
607e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint32_t timescale;
6089a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(
609e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        timescale_offset, &timescale, sizeof(timescale))
610e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    < (ssize_t)sizeof(timescale)) {
611e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
612e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
613e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
614e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->timescale = ntohl(timescale);
615e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
616e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            int64_t duration;
617e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (version == 1) {
6189a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber                if (mDataSource->readAt(
619e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                            timescale_offset + 4, &duration, sizeof(duration))
620e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        < (ssize_t)sizeof(duration)) {
621e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return ERROR_IO;
622e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
623e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                duration = ntoh64(duration);
624e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            } else {
625e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                int32_t duration32;
6269a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber                if (mDataSource->readAt(
627e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                            timescale_offset + 4, &duration32, sizeof(duration32))
628e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        < (ssize_t)sizeof(duration32)) {
629e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return ERROR_IO;
630e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
631e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                duration = ntohl(duration32);
632e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
633fa8de752507feaca695123911915070c1ce463b2Andreas Huber            mLastTrack->meta->setInt64(
634fa8de752507feaca695123911915070c1ce463b2Andreas Huber                    kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
635e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
636e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
637e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
638e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
639e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
640e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('h', 'd', 'l', 'r'):
641e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
642e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size < 25) {
643e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
644e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
645e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
646e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t buffer[24];
6479a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(data_offset, buffer, 24) < 24) {
648e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
649e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
650e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
651e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (U32_AT(buffer) != 0) {
652e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // Should be version 0, flags 0.
653e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
654e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
655e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
656e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (U32_AT(&buffer[4]) != 0) {
657e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // pre_defined should be 0.
658e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
659e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
660e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
661e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mHandlerType = U32_AT(&buffer[8]);
662e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
663e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
664e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
665e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
666e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 's', 'd'):
667e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
668e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size < 8) {
669e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
670e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
671e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
672e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t buffer[8];
6734f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            CHECK(chunk_data_size >= (off_t)sizeof(buffer));
6749a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(
675e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, buffer, 8) < 8) {
676e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
677e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
678e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
679e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (U32_AT(buffer) != 0) {
680e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // Should be version 0, flags 0.
681e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
682e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
683e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
684e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint32_t entry_count = U32_AT(&buffer[4]);
685e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
686e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (entry_count > 1) {
687e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // For now we only support a single type of media per track.
688e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_UNSUPPORTED;
689e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
690e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
691e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            off_t stop_offset = *offset + chunk_size;
692e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset = data_offset + 8;
693e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            for (uint32_t i = 0; i < entry_count; ++i) {
694e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                status_t err = parseChunk(offset, depth + 1);
695e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (err != OK) {
696e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return err;
697e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
698e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
6994f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            CHECK_EQ(*offset, stop_offset);
700e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
701e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
702e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
703e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
704e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
7052a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber        case FOURCC('s', 'a', 'w', 'b'):
706e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
707e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (mHandlerType != FOURCC('s', 'o', 'u', 'n')) {
708e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
709e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
710e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
711e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t buffer[8 + 20];
712e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
713e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // Basic AudioSampleEntry size.
714e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
715e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
716e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
7179a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(
718e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
719e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
720e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
721e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
722e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
723e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint16_t num_channels = U16_AT(&buffer[16]);
724e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
725e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber            if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB,
726e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber                            FourCC2MIME(chunk_type))
727e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber                || !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB,
728e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber                               FourCC2MIME(chunk_type))) {
729e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // AMR audio is always mono.
730e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                num_channels = 1;
731e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
732e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
733e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint16_t sample_size = U16_AT(&buffer[18]);
734e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
735e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
7362ea14e231945afb6581fa8f54015b33bc74a19e5Andreas Huber            // printf("*** coding='%s' %d channels, size %d, rate %d\n",
7372ea14e231945afb6581fa8f54015b33bc74a19e5Andreas Huber            //        chunk, num_channels, sample_size, sample_rate);
738e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
739e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
740e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
741e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
742e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
743e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            off_t stop_offset = *offset + chunk_size;
744e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset = data_offset + sizeof(buffer);
745e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            while (*offset < stop_offset) {
746e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                status_t err = parseChunk(offset, depth + 1);
747e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (err != OK) {
748e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return err;
749e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
750e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
7514f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            CHECK_EQ(*offset, stop_offset);
752e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
753e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
754e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
755e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
756e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', '2', '6', '3'):
757e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
758e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
7591cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber            mHasVideo = true;
7601cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber
761e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (mHandlerType != FOURCC('v', 'i', 'd', 'e')) {
762e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
763e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
764e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
765e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t buffer[78];
766e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
767e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // Basic VideoSampleEntry size.
768e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
769e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
770e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
7719a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(
772e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
773e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
774e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
775e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
776e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
777e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint16_t width = U16_AT(&buffer[6 + 18]);
778e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint16_t height = U16_AT(&buffer[6 + 20]);
779e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
7802ea14e231945afb6581fa8f54015b33bc74a19e5Andreas Huber            // printf("*** coding='%s' width=%d height=%d\n",
7812ea14e231945afb6581fa8f54015b33bc74a19e5Andreas Huber            //        chunk, width, height);
782e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
783e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
784e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setInt32(kKeyWidth, width);
785e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setInt32(kKeyHeight, height);
786e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
787e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            off_t stop_offset = *offset + chunk_size;
788e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset = data_offset + sizeof(buffer);
789e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            while (*offset < stop_offset) {
790e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                status_t err = parseChunk(offset, depth + 1);
791e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (err != OK) {
792e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return err;
793e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
794e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
7954f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            CHECK_EQ(*offset, stop_offset);
796e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
797e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
798e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
799e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 'c', 'o'):
800e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('c', 'o', '6', '4'):
801e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
802e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            status_t err =
803e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mLastTrack->sampleTable->setChunkOffsetParams(
804e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        chunk_type, data_offset, chunk_data_size);
805e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
806e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (err != OK) {
807e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return err;
808e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
809e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
810e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
811e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
812e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
813e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
814e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 's', 'c'):
815e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
816e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            status_t err =
817e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mLastTrack->sampleTable->setSampleToChunkParams(
818e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, chunk_data_size);
819e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
820e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (err != OK) {
821e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return err;
822e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
823e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
824e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
825e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
826e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
827e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
828e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 's', 'z'):
829e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 'z', '2'):
830e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
831e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            status_t err =
832e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mLastTrack->sampleTable->setSampleSizeParams(
833e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        chunk_type, data_offset, chunk_data_size);
834e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
835e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (err != OK) {
836e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return err;
837e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
838e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
8391bceff916a72246fa208605d50615823d7f1688bAndreas Huber            size_t max_size;
8401bceff916a72246fa208605d50615823d7f1688bAndreas Huber            CHECK_EQ(mLastTrack->sampleTable->getMaxSampleSize(&max_size), OK);
8411bceff916a72246fa208605d50615823d7f1688bAndreas Huber
8421bceff916a72246fa208605d50615823d7f1688bAndreas Huber            // Assume that a given buffer only contains at most 10 fragments,
8431bceff916a72246fa208605d50615823d7f1688bAndreas Huber            // each fragment originally prefixed with a 2 byte length will
8441bceff916a72246fa208605d50615823d7f1688bAndreas Huber            // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
8451bceff916a72246fa208605d50615823d7f1688bAndreas Huber            // and thus will grow by 2 bytes per fragment.
8461bceff916a72246fa208605d50615823d7f1688bAndreas Huber            mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
8471bceff916a72246fa208605d50615823d7f1688bAndreas Huber
848e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
849e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
850e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
851e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
852e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 't', 's'):
853e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
854e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            status_t err =
855e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mLastTrack->sampleTable->setTimeToSampleParams(
856e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, chunk_data_size);
857e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
858e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (err != OK) {
859e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return err;
860e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
861e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
862e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
863e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
864e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
865e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
866e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 's', 's'):
867e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
868e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            status_t err =
869e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mLastTrack->sampleTable->setSyncSampleParams(
870e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, chunk_data_size);
871e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
872e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (err != OK) {
873e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return err;
874e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
875e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
876e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
877e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
878e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
879e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
880e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('e', 's', 'd', 's'):
881e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
882e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size < 4) {
883e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
884e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
885e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
886e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t buffer[256];
887e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size > (off_t)sizeof(buffer)) {
888e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
889e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
890e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
8919a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(
892e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
893e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
894e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
895e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
896e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (U32_AT(buffer) != 0) {
897e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // Should be version 0, flags 0.
898e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
899e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
900e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
901e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setData(
902e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
903e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
904d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber            if (mPath.size() >= 2
905d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                    && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) {
906d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                // Information from the ESDS must be relied on for proper
907d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                // setup of sample rate and channel count for MPEG4 Audio.
908d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                // The generic header appears to only contain generic
909d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                // information...
910d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
911d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio(
912d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                        &buffer[4], chunk_data_size - 4);
913d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
914d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                if (err != OK) {
915d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                    return err;
916d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                }
917d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber            }
918d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
919e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
920e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
921e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
922e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
923e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('a', 'v', 'c', 'C'):
924e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
925e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            char buffer[256];
926e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size > (off_t)sizeof(buffer)) {
927e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
928e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
929e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
9309a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (mDataSource->readAt(
931e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
932e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
933e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
934e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
935e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setData(
936e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    kKeyAVCC, kTypeAVCC, buffer, chunk_data_size);
937e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
938e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
939e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
940e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
941e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
942c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('m', 'e', 't', 'a'):
943c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
944c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            uint8_t buffer[4];
945c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            CHECK(chunk_data_size >= (off_t)sizeof(buffer));
946c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (mDataSource->readAt(
947c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                        data_offset, buffer, 4) < 4) {
948c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                return ERROR_IO;
949c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
950c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
951c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (U32_AT(buffer) != 0) {
952c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                // Should be version 0, flags 0.
953c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                return ERROR_MALFORMED;
954c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
955c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
956c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            off_t stop_offset = *offset + chunk_size;
957c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            *offset = data_offset + sizeof(buffer);
958c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            while (*offset < stop_offset) {
959c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                status_t err = parseChunk(offset, depth + 1);
960c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                if (err != OK) {
961c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                    return err;
962c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                }
963c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
964c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            CHECK_EQ(*offset, stop_offset);
965c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
966c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
967c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
968c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('d', 'a', 't', 'a'):
969c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
970c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (mPath.size() == 6 && underMetaDataPath(mPath)) {
971c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                status_t err = parseMetaData(data_offset, chunk_data_size);
972c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
973c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                if (err != OK) {
974c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                    return err;
975c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                }
976c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
977c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
978c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            *offset += chunk_size;
979c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
980c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
981c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
982c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('m', 'v', 'h', 'd'):
983c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
984c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (chunk_data_size < 12) {
985c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                return ERROR_MALFORMED;
986c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
987c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
988c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            uint8_t header[12];
989c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (mDataSource->readAt(
990c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                        data_offset, header, sizeof(header))
991c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                    < (ssize_t)sizeof(header)) {
992c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                return ERROR_IO;
993c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
994c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
995c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            int64_t creationTime;
996c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (header[0] == 1) {
997c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                creationTime = U64_AT(&header[4]);
998c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            } else {
999c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                CHECK_EQ(header[0], 0);
1000c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                creationTime = U32_AT(&header[4]);
1001c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
1002c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1003c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            String8 s;
1004c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            convertTimeToDate(creationTime, &s);
1005c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1006c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            mFileMetaData->setCString(kKeyDate, s.string());
1007c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1008c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            *offset += chunk_size;
1009c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1010c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1011c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1012e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        default:
1013e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
1014e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
1015e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
1016e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
1017e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1018e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1019e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return OK;
1020e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1021e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1022c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huberstatus_t MPEG4Extractor::parseMetaData(off_t offset, size_t size) {
1023c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    if (size < 4) {
1024c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        return ERROR_MALFORMED;
1025c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    }
1026c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1027c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    uint8_t *buffer = new uint8_t[size + 1];
1028c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    if (mDataSource->readAt(
1029c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                offset, buffer, size) != (ssize_t)size) {
1030c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        delete[] buffer;
1031c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        buffer = NULL;
1032c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1033c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        return ERROR_IO;
1034c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    }
1035c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1036c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    uint32_t flags = U32_AT(buffer);
1037c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1038c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    uint32_t metadataKey = 0;
1039c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    switch (mPath[4]) {
1040c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC(0xa9, 'a', 'l', 'b'):
1041c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1042c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            metadataKey = kKeyAlbum;
1043c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1044c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1045c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC(0xa9, 'A', 'R', 'T'):
1046c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1047c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            metadataKey = kKeyArtist;
1048c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1049c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1050c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen        case FOURCC('a', 'A', 'R', 'T'):
1051c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen        {
1052c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen            metadataKey = kKeyAlbumArtist;
1053c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen            break;
1054c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen        }
1055c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC(0xa9, 'd', 'a', 'y'):
1056c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1057c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            metadataKey = kKeyYear;
1058c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1059c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1060c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC(0xa9, 'n', 'a', 'm'):
1061c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1062c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            metadataKey = kKeyTitle;
1063c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1064c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1065c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC(0xa9, 'w', 'r', 't'):
1066c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1067c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            metadataKey = kKeyWriter;
1068c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1069c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1070c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('c', 'o', 'v', 'r'):
1071c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1072c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            metadataKey = kKeyAlbumArt;
1073c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1074c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1075c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('g', 'n', 'r', 'e'):
1076c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1077c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            metadataKey = kKeyGenre;
1078c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1079c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1080fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen        case FOURCC(0xa9, 'g', 'e', 'n'):
1081fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen        {
1082fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen            metadataKey = kKeyGenre;
1083fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen            break;
1084fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen        }
1085c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        case FOURCC('t', 'r', 'k', 'n'):
1086c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        {
1087c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (size == 16 && flags == 0) {
1088c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                char tmp[16];
1089c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                sprintf(tmp, "%d/%d",
1090c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                        (int)buffer[size - 5], (int)buffer[size - 3]);
1091c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1092c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
1093c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
1094c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1095c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1096fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen        case FOURCC('d', 'i', 's', 'k'):
1097fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen        {
1098fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen            if (size == 14 && flags == 0) {
1099fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                char tmp[16];
1100fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                sprintf(tmp, "%d/%d",
1101fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                        (int)buffer[size - 3], (int)buffer[size - 1]);
1102fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen
1103fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                mFileMetaData->setCString(kKeyDiscNumber, tmp);
1104fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen            }
1105fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen            break;
1106fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen        }
1107fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen
1108c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        default:
1109c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            break;
1110c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    }
1111c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1112c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    if (size >= 8 && metadataKey) {
1113c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        if (metadataKey == kKeyAlbumArt) {
1114c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            mFileMetaData->setData(
1115c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                    kKeyAlbumArt, MetaData::TYPE_NONE,
1116c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                    buffer + 8, size - 8);
1117c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        } else if (metadataKey == kKeyGenre) {
1118c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            if (flags == 0) {
1119fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                // uint8_t genre code, iTunes genre codes are
1120fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                // the standard id3 codes, except they start
1121fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                // at 1 instead of 0 (e.g. Pop is 14, not 13)
1122fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                // We use standard id3 numbering, so subtract 1.
1123fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                int genrecode = (int)buffer[size - 1];
1124fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                genrecode--;
1125fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                if (genrecode < 0) {
1126fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                    genrecode = 255; // reserved for 'unknown genre'
1127fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                }
1128c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                char genre[10];
1129fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                sprintf(genre, "%d", genrecode);
1130c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1131c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                mFileMetaData->setCString(metadataKey, genre);
1132fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen            } else if (flags == 1) {
1133fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                // custom genre string
1134fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                buffer[size] = '\0';
1135fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen
1136fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                mFileMetaData->setCString(
1137fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen                        metadataKey, (const char *)buffer + 8);
1138c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            }
1139c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        } else {
1140c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            buffer[size] = '\0';
1141c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1142c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber            mFileMetaData->setCString(
1143c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber                    metadataKey, (const char *)buffer + 8);
1144c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        }
1145c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    }
1146c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1147c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    delete[] buffer;
1148c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    buffer = NULL;
1149c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1150c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber    return OK;
1151c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber}
1152c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber
1153be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
1154e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    status_t err;
1155e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if ((err = readMetaData()) != OK) {
1156be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber        return NULL;
1157e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1158e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1159e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    Track *track = mFirstTrack;
1160e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    while (index > 0) {
1161e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (track == NULL) {
1162be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber            return NULL;
1163e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
1164e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1165e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        track = track->next;
1166e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        --index;
1167e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1168e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
11692a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber    if (track == NULL) {
11702a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber        return NULL;
11712a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber    }
11722a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber
1173be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber    return new MPEG4Source(
1174fa8de752507feaca695123911915070c1ce463b2Andreas Huber            track->meta, mDataSource, track->timescale, track->sampleTable);
1175e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1176e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1177d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huberstatus_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(
1178d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        const void *esds_data, size_t esds_size) {
1179d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    ESDS esds(esds_data, esds_size);
1180d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    const uint8_t *csd;
1181d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    size_t csd_size;
1182d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    if (esds.getCodecSpecificInfo(
1183d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                (const void **)&csd, &csd_size) != OK) {
1184d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        return ERROR_MALFORMED;
1185d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    }
1186d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1187d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber#if 0
1188d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    printf("ESD of size %d\n", csd_size);
1189d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    hexdump(csd, csd_size);
1190d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber#endif
1191d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1192d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    if (csd_size < 2) {
1193d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        return ERROR_MALFORMED;
1194d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    }
1195d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1196d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    uint32_t objectType = csd[0] >> 3;
1197d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1198d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    if (objectType == 31) {
1199d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        return ERROR_UNSUPPORTED;
1200d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    }
1201d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1202d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    uint32_t freqIndex = (csd[0] & 7) << 1 | (csd[1] >> 7);
1203d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    int32_t sampleRate = 0;
1204d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    int32_t numChannels = 0;
1205d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    if (freqIndex == 15) {
1206d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        if (csd_size < 5) {
1207d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber            return ERROR_MALFORMED;
1208d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        }
1209d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1210d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        sampleRate = (csd[1] & 0x7f) << 17
1211d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                        | csd[2] << 9
1212d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                        | csd[3] << 1
1213d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber                        | (csd[4] >> 7);
1214d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1215d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        numChannels = (csd[4] >> 3) & 15;
1216d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    } else {
1217d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        static uint32_t kSamplingRate[] = {
1218d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber            96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
1219d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber            16000, 12000, 11025, 8000, 7350
1220d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        };
1221d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1222d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        if (freqIndex == 13 || freqIndex == 14) {
1223d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber            return ERROR_MALFORMED;
1224d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        }
1225d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1226d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        sampleRate = kSamplingRate[freqIndex];
1227d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        numChannels = (csd[1] >> 3) & 15;
1228d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    }
1229d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1230d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    if (numChannels == 0) {
1231d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber        return ERROR_UNSUPPORTED;
1232d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    }
1233d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1234d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    int32_t prevSampleRate;
1235d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));
1236d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1237d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    if (prevSampleRate != sampleRate) {
12384a9375ef2a06fc36ec308835ef9e7e4eea2ba69fAndreas Huber        LOGV("mpeg4 audio sample rate different from previous setting. "
1239d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber             "was: %d, now: %d", prevSampleRate, sampleRate);
1240d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    }
1241d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1242d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
1243d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1244d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    int32_t prevChannelCount;
1245d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount));
1246d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1247d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    if (prevChannelCount != numChannels) {
12484a9375ef2a06fc36ec308835ef9e7e4eea2ba69fAndreas Huber        LOGV("mpeg4 audio channel count different from previous setting. "
1249d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber             "was: %d, now: %d", prevChannelCount, numChannels);
1250d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    }
1251d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1252d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    mLastTrack->meta->setInt32(kKeyChannelCount, numChannels);
1253d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1254d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber    return OK;
1255d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber}
1256d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber
1257e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber////////////////////////////////////////////////////////////////////////////////
1258e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1259e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberMPEG4Source::MPEG4Source(
1260e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        const sp<MetaData> &format,
1261be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber        const sp<DataSource> &dataSource,
1262fa8de752507feaca695123911915070c1ce463b2Andreas Huber        int32_t timeScale,
1263be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber        const sp<SampleTable> &sampleTable)
1264e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    : mFormat(format),
1265e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mDataSource(dataSource),
1266fa8de752507feaca695123911915070c1ce463b2Andreas Huber      mTimescale(timeScale),
1267e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mSampleTable(sampleTable),
1268e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mCurrentSampleIndex(0),
1269e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mIsAVC(false),
1270db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber      mNALLengthSize(0),
1271e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mStarted(false),
1272e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mGroup(NULL),
1273e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mBuffer(NULL),
12744f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber      mWantsNALFragments(false),
12758a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber      mSrcBuffer(NULL) {
1276e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    const char *mime;
1277e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    bool success = mFormat->findCString(kKeyMIMEType, &mime);
12784f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    CHECK(success);
1279e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1280e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber    mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
1281db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
1282db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    if (mIsAVC) {
1283db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        uint32_t type;
1284db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        const void *data;
1285db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        size_t size;
1286db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        CHECK(format->findData(kKeyAVCC, &type, &data, &size));
1287db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
1288db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        const uint8_t *ptr = (const uint8_t *)data;
1289db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
1290db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        CHECK(size >= 7);
1291db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        CHECK_EQ(ptr[0], 1);  // configurationVersion == 1
1292db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
1293db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        // The number of bytes used to encode the length of a NAL unit.
1294db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        mNALLengthSize = 1 + (ptr[4] & 3);
1295db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    }
1296e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1297e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1298e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberMPEG4Source::~MPEG4Source() {
1299e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (mStarted) {
1300e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        stop();
1301e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1302e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1303e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1304e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Source::start(MetaData *params) {
1305ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber    Mutex::Autolock autoLock(mLock);
1306ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber
13074f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    CHECK(!mStarted);
1308e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1309e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    int32_t val;
13104f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    if (params && params->findInt32(kKeyWantsNALFragments, &val)
1311e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        && val != 0) {
13124f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        mWantsNALFragments = true;
1313e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    } else {
13144f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        mWantsNALFragments = false;
1315e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1316e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1317e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mGroup = new MediaBufferGroup;
1318e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
13191bceff916a72246fa208605d50615823d7f1688bAndreas Huber    int32_t max_size;
13201bceff916a72246fa208605d50615823d7f1688bAndreas Huber    CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size));
1321e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
13221bceff916a72246fa208605d50615823d7f1688bAndreas Huber    mGroup->add_buffer(new MediaBuffer(max_size));
13238a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber
13248a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    mSrcBuffer = new uint8_t[max_size];
1325e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1326e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mStarted = true;
1327e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1328e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return OK;
1329e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1330e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1331e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Source::stop() {
1332ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber    Mutex::Autolock autoLock(mLock);
1333ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber
13344f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    CHECK(mStarted);
1335e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1336e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (mBuffer != NULL) {
1337e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        mBuffer->release();
1338e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        mBuffer = NULL;
1339e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1340e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
13418a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    delete[] mSrcBuffer;
13428a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    mSrcBuffer = NULL;
13438a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber
1344e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    delete mGroup;
1345e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mGroup = NULL;
1346e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1347e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mStarted = false;
1348e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mCurrentSampleIndex = 0;
1349e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1350e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return OK;
1351e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1352e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1353e46b7be812d68e49710b34048662cbf18e2a6550Andreas Hubersp<MetaData> MPEG4Source::getFormat() {
1354ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber    Mutex::Autolock autoLock(mLock);
1355ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber
1356e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return mFormat;
1357e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1358e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1359db5d662254f2ed788d32e2466739adc8d655c732Andreas Hubersize_t MPEG4Source::parseNALSize(const uint8_t *data) const {
1360db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    switch (mNALLengthSize) {
1361db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        case 1:
1362db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber            return *data;
1363db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        case 2:
1364db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber            return U16_AT(data);
1365db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        case 3:
1366db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber            return ((size_t)data[0] << 16) | U16_AT(&data[1]);
1367db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        case 4:
1368db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber            return U32_AT(data);
1369db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    }
1370db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
1371db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    // This cannot happen, mNALLengthSize springs to life by adding 1 to
1372db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    // a 2-bit integer.
1373db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    CHECK(!"Should not be here.");
1374db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
1375db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber    return 0;
1376db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber}
1377db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
1378e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Source::read(
1379e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        MediaBuffer **out, const ReadOptions *options) {
1380ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber    Mutex::Autolock autoLock(mLock);
1381ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber
13824f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    CHECK(mStarted);
1383e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1384e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    *out = NULL;
1385e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1386e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    int64_t seekTimeUs;
1387e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (options && options->getSeekTo(&seekTimeUs)) {
1388e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        uint32_t sampleIndex;
1389e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        status_t err = mSampleTable->findClosestSample(
1390e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                seekTimeUs * mTimescale / 1000000,
1391e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                &sampleIndex, SampleTable::kSyncSample_Flag);
1392e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1393e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (err != OK) {
1394e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            return err;
1395e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
1396e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1397e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        mCurrentSampleIndex = sampleIndex;
1398e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (mBuffer != NULL) {
1399e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mBuffer->release();
1400e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mBuffer = NULL;
1401e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
1402e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1403e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        // fall through
1404e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1405e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
14068a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    off_t offset;
14078a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    size_t size;
14084f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    uint32_t dts;
14094f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    bool newBuffer = false;
14104f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    if (mBuffer == NULL) {
14114f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        newBuffer = true;
1412e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
14131faa92a1e93f311e86dca483ed7702091137de66Andreas Huber        status_t err =
14141faa92a1e93f311e86dca483ed7702091137de66Andreas Huber            mSampleTable->getMetaDataForSample(
14151faa92a1e93f311e86dca483ed7702091137de66Andreas Huber                    mCurrentSampleIndex, &offset, &size, &dts);
1416e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
14174f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        if (err != OK) {
14184f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            return err;
14194f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
14204f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
14214f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        err = mGroup->acquire_buffer(&mBuffer);
14221faa92a1e93f311e86dca483ed7702091137de66Andreas Huber
14234f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        if (err != OK) {
14244f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            CHECK_EQ(mBuffer, NULL);
14254f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            return err;
14264f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
14278a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    }
1428e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
14294f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    if (!mIsAVC || mWantsNALFragments) {
14304f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        if (newBuffer) {
14314f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            ssize_t num_bytes_read =
14329a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
14334f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
14344f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            if (num_bytes_read < (ssize_t)size) {
14354f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber                mBuffer->release();
14364f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber                mBuffer = NULL;
14374f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
14384f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber                return ERROR_IO;
14394f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            }
14404f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
1441ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber            CHECK(mBuffer != NULL);
14424f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            mBuffer->set_range(0, size);
14434f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            mBuffer->meta_data()->clear();
1444fa8de752507feaca695123911915070c1ce463b2Andreas Huber            mBuffer->meta_data()->setInt64(
1445fa8de752507feaca695123911915070c1ce463b2Andreas Huber                    kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
14464f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            ++mCurrentSampleIndex;
14474f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
14484f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
14494f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        if (!mIsAVC) {
14504f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            *out = mBuffer;
14514f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            mBuffer = NULL;
14524f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
14534f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            return OK;
14544f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
14554f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
14564f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        // Each NAL unit is split up into its constituent fragments and
14574f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        // each one of them returned in its own buffer.
14584f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
1459db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        CHECK(mBuffer->range_length() >= mNALLengthSize);
14604f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
14614f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        const uint8_t *src =
14624f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
14634f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
1464db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        size_t nal_size = parseNALSize(src);
1465909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
1466909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber            LOGE("incomplete NAL unit.");
1467909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber
1468909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber            mBuffer->release();
1469909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber            mBuffer = NULL;
1470909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber
1471909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber            return ERROR_MALFORMED;
1472909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber        }
14734f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
14744f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        MediaBuffer *clone = mBuffer->clone();
1475ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber        CHECK(clone != NULL);
1476db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
14774f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
1478ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber        CHECK(mBuffer != NULL);
14794f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        mBuffer->set_range(
1480db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber                mBuffer->range_offset() + mNALLengthSize + nal_size,
1481db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber                mBuffer->range_length() - mNALLengthSize - nal_size);
14824f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
14834f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        if (mBuffer->range_length() == 0) {
14844f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            mBuffer->release();
14854f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            mBuffer = NULL;
14864f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
14874f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
14884f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        *out = clone;
14894f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
14904f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        return OK;
14914f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    } else {
14924f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        // Whole NAL units are returned but each fragment is prefixed by
14934f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        // the start code (0x00 00 00 01).
14944f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
1495e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        ssize_t num_bytes_read =
14969a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            mDataSource->readAt(offset, mSrcBuffer, size);
1497e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1498e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (num_bytes_read < (ssize_t)size) {
1499e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mBuffer->release();
1500e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mBuffer = NULL;
1501e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
15024f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            return ERROR_IO;
1503e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
1504e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
15054f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        uint8_t *dstData = (uint8_t *)mBuffer->data();
15064f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        size_t srcOffset = 0;
15074f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        size_t dstOffset = 0;
1508db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber
15094f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        while (srcOffset < size) {
1510db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber            CHECK(srcOffset + mNALLengthSize <= size);
1511db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber            size_t nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
1512db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber            srcOffset += mNALLengthSize;
1513909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber
1514909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber            if (srcOffset + nalLength > size) {
1515909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber                mBuffer->release();
1516909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber                mBuffer = NULL;
1517909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber
1518909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber                return ERROR_MALFORMED;
1519909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber            }
15204f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
15214f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            if (nalLength == 0) {
15224f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber                continue;
15234f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            }
15244f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
15254f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            CHECK(dstOffset + 4 <= mBuffer->size());
15264f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
15274f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            dstData[dstOffset++] = 0;
15284f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            dstData[dstOffset++] = 0;
15294f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            dstData[dstOffset++] = 0;
15304f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            dstData[dstOffset++] = 1;
15314f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
15324f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            srcOffset += nalLength;
15334f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            dstOffset += nalLength;
15344f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
1535db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber        CHECK_EQ(srcOffset, size);
15364f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
1537ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber        CHECK(mBuffer != NULL);
15384f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        mBuffer->set_range(0, dstOffset);
1539e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        mBuffer->meta_data()->clear();
1540fa8de752507feaca695123911915070c1ce463b2Andreas Huber        mBuffer->meta_data()->setInt64(
1541fa8de752507feaca695123911915070c1ce463b2Andreas Huber                kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
1542e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        ++mCurrentSampleIndex;
1543e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1544e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        *out = mBuffer;
1545e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        mBuffer = NULL;
1546e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1547e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return OK;
1548e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1549e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1550e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1551be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huberbool SniffMPEG4(
1552be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
1553e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    uint8_t header[8];
1554e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
15559a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber    ssize_t n = source->readAt(4, header, sizeof(header));
1556e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (n < (ssize_t)sizeof(header)) {
1557e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return false;
1558e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1559e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1560e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
15616bce6d87b3fd98e68fb54328fb4dc8e40cd2c293Andreas Huber        || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
156201830a0814ae2db9141f49720d9e5aa2457854f0Andreas Huber        || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)) {
1563e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber        *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
1564e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        *confidence = 0.1;
1565e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1566e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return true;
1567e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1568e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1569e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return false;
1570e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1571e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1572e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}  // namespace android
1573e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1574