MPEG4Extractor.cpp revision 57515f334bcc1f66f95e342bfcaa13bf9ca802ad
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>
31e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaBuffer.h>
32e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaBufferGroup.h>
334f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber#include <media/stagefright/MediaDebug.h>
34e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber#include <media/stagefright/MediaDefs.h>
35e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaSource.h>
36e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MetaData.h>
37e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/Utils.h>
38e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <utils/String8.h>
39e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
40e46b7be812d68e49710b34048662cbf18e2a6550Andreas Hubernamespace android {
41e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
42e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberclass MPEG4Source : public MediaSource {
43e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberpublic:
44e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    // Caller retains ownership of both "dataSource" and "sampleTable".
45be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber    MPEG4Source(const sp<MetaData> &format,
46be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber                const sp<DataSource> &dataSource,
47fa8de752507feaca695123911915070c1ce463b2Andreas Huber                int32_t timeScale,
48be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber                const sp<SampleTable> &sampleTable);
49e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
50e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    virtual status_t start(MetaData *params = NULL);
51e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    virtual status_t stop();
52e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
53e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    virtual sp<MetaData> getFormat();
54e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
55e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    virtual status_t read(
56e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            MediaBuffer **buffer, const ReadOptions *options = NULL);
57e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
58be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huberprotected:
59be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber    virtual ~MPEG4Source();
60be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber
61e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberprivate:
62e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    sp<MetaData> mFormat;
63be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber    sp<DataSource> mDataSource;
64e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    int32_t mTimescale;
65be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber    sp<SampleTable> mSampleTable;
66e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    uint32_t mCurrentSampleIndex;
67e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
68e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    bool mIsAVC;
69e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    bool mStarted;
70e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
71e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    MediaBufferGroup *mGroup;
72e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
73e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    MediaBuffer *mBuffer;
74e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
754f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    bool mWantsNALFragments;
76e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
778a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    uint8_t *mSrcBuffer;
788a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber
79e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    MPEG4Source(const MPEG4Source &);
80e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    MPEG4Source &operator=(const MPEG4Source &);
81e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber};
82e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
83e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatic void hexdump(const void *_data, size_t size) {
84e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    const uint8_t *data = (const uint8_t *)_data;
85e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    size_t offset = 0;
86e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    while (offset < size) {
87e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        printf("0x%04x  ", offset);
88e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
89e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        size_t n = size - offset;
90e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (n > 16) {
91e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            n = 16;
92e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
93e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
94e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        for (size_t i = 0; i < 16; ++i) {
95e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (i == 8) {
96e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                printf(" ");
97e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
98e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
99e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (offset + i < size) {
100e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                printf("%02x ", data[offset + i]);
101e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            } else {
102e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                printf("   ");
103e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
104e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
105e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
106e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        printf(" ");
107e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
108e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        for (size_t i = 0; i < n; ++i) {
109e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (isprint(data[offset + i])) {
110e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                printf("%c", data[offset + i]);
111e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            } else {
112e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                printf(".");
113e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
114e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
115e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
116e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        printf("\n");
117e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
118e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        offset += 16;
119e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
120e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
121e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
122e6c409632f773e41f33188272a0072be9fcb783fAndreas Huberstatic const char *FourCC2MIME(uint32_t fourcc) {
123e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    switch (fourcc) {
124e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
125e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber            return MEDIA_MIMETYPE_AUDIO_AAC;
126e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
127e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
128e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_NB;
129e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1302a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber        case FOURCC('s', 'a', 'w', 'b'):
131e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_WB;
1322a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber
133e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
134e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber            return MEDIA_MIMETYPE_VIDEO_MPEG4;
135e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
136e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', '2', '6', '3'):
137e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber            return MEDIA_MIMETYPE_VIDEO_H263;
138e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
139e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
140e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber            return MEDIA_MIMETYPE_VIDEO_AVC;
141e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
142e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        default:
1434f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            CHECK(!"should not be here.");
144e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            return NULL;
145e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
146e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
147e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
148be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas HuberMPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
149e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    : mDataSource(source),
150e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mHaveMetadata(false),
151e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mFirstTrack(NULL),
152e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mLastTrack(NULL) {
153e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
154e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
155e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberMPEG4Extractor::~MPEG4Extractor() {
156e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    Track *track = mFirstTrack;
157e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    while (track) {
158e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        Track *next = track->next;
159e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
160e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        delete track;
161e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        track = next;
162e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
163e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mFirstTrack = mLastTrack = NULL;
164e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
165e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
166be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Hubersize_t MPEG4Extractor::countTracks() {
167e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    status_t err;
168e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if ((err = readMetaData()) != OK) {
169be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber        return 0;
170e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
171e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
172be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber    size_t n = 0;
173e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    Track *track = mFirstTrack;
174e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    while (track) {
175be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber        ++n;
176e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        track = track->next;
177e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
178e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
179be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber    return n;
180e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
181e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
182e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Hubersp<MetaData> MPEG4Extractor::getTrackMetaData(
183e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber        size_t index, uint32_t flags) {
184e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    status_t err;
185e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if ((err = readMetaData()) != OK) {
186e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return NULL;
187e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
188e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
189e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    Track *track = mFirstTrack;
190e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    while (index > 0) {
191e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (track == NULL) {
192e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            return NULL;
193e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
194e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
195e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        track = track->next;
196e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        --index;
197e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
198e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1992a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber    if (track == NULL) {
2002a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber        return NULL;
2012a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber    }
2022a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber
203e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber    if ((flags & kIncludeExtensiveMetaData)
204e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber            && !track->includes_expensive_metadata) {
205e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber        track->includes_expensive_metadata = true;
206e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber
207e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber        const char *mime;
208e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber        CHECK(track->meta->findCString(kKeyMIMEType, &mime));
209e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber        if (!strncasecmp("video/", mime, 6)) {
210e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber            uint32_t sampleIndex;
211e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber            uint32_t sampleTime;
212e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber            if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK
213e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber                    && track->sampleTable->getDecodingTime(
214e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber                        sampleIndex, &sampleTime) == OK) {
215e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber                track->meta->setInt64(
216e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber                        kKeyThumbnailTime,
217e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber                        ((int64_t)sampleTime * 1000000) / track->timescale);
218e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber            }
219e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber        }
220e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber    }
221e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber
222e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return track->meta;
223e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
224e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
225e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Extractor::readMetaData() {
226e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (mHaveMetadata) {
227e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return OK;
228e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
229e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
230e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    off_t offset = 0;
231e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    status_t err;
232e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    while ((err = parseChunk(&offset, 0)) == OK) {
233e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
234e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
235e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (mHaveMetadata) {
236e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return OK;
237e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
238e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
239e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return err;
240e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
241e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
242e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatic void MakeFourCCString(uint32_t x, char *s) {
243e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    s[0] = x >> 24;
244e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    s[1] = (x >> 16) & 0xff;
245e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    s[2] = (x >> 8) & 0xff;
246e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    s[3] = x & 0xff;
247e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    s[4] = '\0';
248e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
249e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
250e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
251e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    uint32_t hdr[2];
252e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (mDataSource->read_at(*offset, hdr, 8) < 8) {
253e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return ERROR_IO;
254e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
255e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    uint64_t chunk_size = ntohl(hdr[0]);
256e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    uint32_t chunk_type = ntohl(hdr[1]);
257e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    off_t data_offset = *offset + 8;
258e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
259e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (chunk_size == 1) {
260e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (mDataSource->read_at(*offset + 8, &chunk_size, 8) < 8) {
261e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            return ERROR_IO;
262e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
263e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        chunk_size = ntoh64(chunk_size);
264e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        data_offset += 8;
265e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
266e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
267e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    char chunk[5];
268e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    MakeFourCCString(chunk_type, chunk);
269e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
270e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#if 0
271e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    static const char kWhitespace[] = "                                        ";
272e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth];
273e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    printf("%sfound chunk '%s' of size %lld\n", indent, chunk, chunk_size);
274e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
275e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    char buffer[256];
276e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (chunk_size <= sizeof(buffer)) {
277e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (mDataSource->read_at(*offset, buffer, chunk_size) < chunk_size) {
278e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            return ERROR_IO;
279e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
280e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
281e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        hexdump(buffer, chunk_size);
282e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
283e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#endif
284e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
285e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    off_t chunk_data_size = *offset + chunk_size - data_offset;
286e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
287e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    switch(chunk_type) {
288e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'o', 'o', 'v'):
289e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('t', 'r', 'a', 'k'):
290e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'd', 'i', 'a'):
291e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'i', 'n', 'f'):
292e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('d', 'i', 'n', 'f'):
293e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 'b', 'l'):
294e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'v', 'e', 'x'):
295e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'o', 'o', 'f'):
296e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('t', 'r', 'a', 'f'):
297e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'f', 'r', 'a'):
298e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 'k', 'i' ,'p'):
299e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
300e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            off_t stop_offset = *offset + chunk_size;
301e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset = data_offset;
302e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            while (*offset < stop_offset) {
303e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                status_t err = parseChunk(offset, depth + 1);
304e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (err != OK) {
305e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return err;
306e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
307e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
3084f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            CHECK_EQ(*offset, stop_offset);
309e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
310e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
311e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mHaveMetadata = true;
312e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
313e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return UNKNOWN_ERROR;  // Return a dummy error.
314e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
315e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
316e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
317e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
318e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('t', 'k', 'h', 'd'):
319e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
3204f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            CHECK(chunk_data_size >= 4);
321e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
322e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t version;
323e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (mDataSource->read_at(data_offset, &version, 1) < 1) {
324e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
325e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
326e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
327e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint64_t ctime, mtime, duration;
328e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            int32_t id;
329e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint32_t width, height;
330e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
331e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (version == 1) {
332e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (chunk_data_size != 36 + 60) {
333e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return ERROR_MALFORMED;
334e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
335e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
336e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                uint8_t buffer[36 + 60];
337e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (mDataSource->read_at(
338e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                            data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
339e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return ERROR_IO;
340e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
341e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
342e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                ctime = U64_AT(&buffer[4]);
343e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mtime = U64_AT(&buffer[12]);
344e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                id = U32_AT(&buffer[20]);
345e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                duration = U64_AT(&buffer[28]);
346e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                width = U32_AT(&buffer[88]);
347e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                height = U32_AT(&buffer[92]);
348e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            } else if (version == 0) {
349e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (chunk_data_size != 24 + 60) {
350e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return ERROR_MALFORMED;
351e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
352e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
353e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                uint8_t buffer[24 + 60];
354e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (mDataSource->read_at(
355e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                            data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
356e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return ERROR_IO;
357e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
358e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                ctime = U32_AT(&buffer[4]);
359e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mtime = U32_AT(&buffer[8]);
360e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                id = U32_AT(&buffer[12]);
361e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                duration = U32_AT(&buffer[20]);
362e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                width = U32_AT(&buffer[76]);
363e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                height = U32_AT(&buffer[80]);
364e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
365e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
366e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            Track *track = new Track;
367e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            track->next = NULL;
368e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (mLastTrack) {
369e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mLastTrack->next = track;
370e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            } else {
371e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mFirstTrack = track;
372e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
373e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack = track;
374e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
375e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            track->meta = new MetaData;
376e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber            track->includes_expensive_metadata = false;
377e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            track->timescale = 0;
378e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            track->sampleTable = new SampleTable(mDataSource);
379e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            track->meta->setCString(kKeyMIMEType, "application/octet-stream");
380e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
381e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
382e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
383e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
384e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
385e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'd', 'h', 'd'):
386e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
387e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size < 4) {
388e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
389e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
390e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
391e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t version;
392e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (mDataSource->read_at(
393e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, &version, sizeof(version))
394e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    < (ssize_t)sizeof(version)) {
395e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
396e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
397e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
398e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            off_t timescale_offset;
399e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
400e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (version == 1) {
401e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                timescale_offset = data_offset + 4 + 16;
402e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            } else if (version == 0) {
403e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                timescale_offset = data_offset + 4 + 8;
404e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            } else {
405e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
406e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
407e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
408e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint32_t timescale;
409e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (mDataSource->read_at(
410e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        timescale_offset, &timescale, sizeof(timescale))
411e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    < (ssize_t)sizeof(timescale)) {
412e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
413e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
414e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
415e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->timescale = ntohl(timescale);
416e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
417e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            int64_t duration;
418e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (version == 1) {
419e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (mDataSource->read_at(
420e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                            timescale_offset + 4, &duration, sizeof(duration))
421e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        < (ssize_t)sizeof(duration)) {
422e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return ERROR_IO;
423e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
424e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                duration = ntoh64(duration);
425e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            } else {
426e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                int32_t duration32;
427e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (mDataSource->read_at(
428e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                            timescale_offset + 4, &duration32, sizeof(duration32))
429e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        < (ssize_t)sizeof(duration32)) {
430e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return ERROR_IO;
431e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
432e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                duration = ntohl(duration32);
433e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
434fa8de752507feaca695123911915070c1ce463b2Andreas Huber            mLastTrack->meta->setInt64(
435fa8de752507feaca695123911915070c1ce463b2Andreas Huber                    kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
436e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
437e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
438e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
439e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
440e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
441e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('h', 'd', 'l', 'r'):
442e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
443e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size < 25) {
444e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
445e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
446e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
447e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t buffer[24];
448e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (mDataSource->read_at(data_offset, buffer, 24) < 24) {
449e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
450e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
451e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
452e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (U32_AT(buffer) != 0) {
453e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // Should be version 0, flags 0.
454e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
455e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
456e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
457e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (U32_AT(&buffer[4]) != 0) {
458e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // pre_defined should be 0.
459e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
460e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
461e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
462e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mHandlerType = U32_AT(&buffer[8]);
463e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
464e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
465e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
466e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
467e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 's', 'd'):
468e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
469e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size < 8) {
470e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
471e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
472e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
473e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t buffer[8];
4744f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            CHECK(chunk_data_size >= (off_t)sizeof(buffer));
475e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (mDataSource->read_at(
476e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, buffer, 8) < 8) {
477e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
478e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
479e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
480e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (U32_AT(buffer) != 0) {
481e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // Should be version 0, flags 0.
482e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
483e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
484e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
485e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint32_t entry_count = U32_AT(&buffer[4]);
486e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
487e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (entry_count > 1) {
488e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // For now we only support a single type of media per track.
489e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_UNSUPPORTED;
490e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
491e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
492e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            off_t stop_offset = *offset + chunk_size;
493e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset = data_offset + 8;
494e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            for (uint32_t i = 0; i < entry_count; ++i) {
495e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                status_t err = parseChunk(offset, depth + 1);
496e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (err != OK) {
497e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return err;
498e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
499e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
5004f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            CHECK_EQ(*offset, stop_offset);
501e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
502e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
503e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
504e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
505e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
5062a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber        case FOURCC('s', 'a', 'w', 'b'):
507e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
508e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (mHandlerType != FOURCC('s', 'o', 'u', 'n')) {
509e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
510e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
511e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
512e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t buffer[8 + 20];
513e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
514e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // Basic AudioSampleEntry size.
515e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
516e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
517e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
518e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (mDataSource->read_at(
519e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
520e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
521e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
522e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
523e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
524e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint16_t num_channels = U16_AT(&buffer[16]);
525e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
526e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber            if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB,
527e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber                            FourCC2MIME(chunk_type))
528e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber                || !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB,
529e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber                               FourCC2MIME(chunk_type))) {
530e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // AMR audio is always mono.
531e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                num_channels = 1;
532e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
533e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
534e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint16_t sample_size = U16_AT(&buffer[18]);
535e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
536e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
537e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            printf("*** coding='%s' %d channels, size %d, rate %d\n",
538e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                   chunk, num_channels, sample_size, sample_rate);
539e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
540e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
541e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
542e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
543e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
544e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            off_t stop_offset = *offset + chunk_size;
545e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset = data_offset + sizeof(buffer);
546e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            while (*offset < stop_offset) {
547e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                status_t err = parseChunk(offset, depth + 1);
548e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (err != OK) {
549e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return err;
550e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
551e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
5524f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            CHECK_EQ(*offset, stop_offset);
553e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
554e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
555e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
556e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
557e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', '2', '6', '3'):
558e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
559e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
560e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (mHandlerType != FOURCC('v', 'i', 'd', 'e')) {
561e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
562e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
563e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
564e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t buffer[78];
565e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
566e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // Basic VideoSampleEntry size.
567e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
568e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
569e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
570e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (mDataSource->read_at(
571e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
572e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
573e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
574e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
575e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
576e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint16_t width = U16_AT(&buffer[6 + 18]);
577e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint16_t height = U16_AT(&buffer[6 + 20]);
578e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
579e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            printf("*** coding='%s' width=%d height=%d\n",
580e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                   chunk, width, height);
581e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
582e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
583e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setInt32(kKeyWidth, width);
584e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setInt32(kKeyHeight, height);
585e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
586e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            off_t stop_offset = *offset + chunk_size;
587e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset = data_offset + sizeof(buffer);
588e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            while (*offset < stop_offset) {
589e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                status_t err = parseChunk(offset, depth + 1);
590e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                if (err != OK) {
591e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    return err;
592e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                }
593e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
5944f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            CHECK_EQ(*offset, stop_offset);
595e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
596e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
597e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
598e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 'c', 'o'):
599e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('c', 'o', '6', '4'):
600e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
601e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            status_t err =
602e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mLastTrack->sampleTable->setChunkOffsetParams(
603e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        chunk_type, data_offset, chunk_data_size);
604e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
605e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (err != OK) {
606e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return err;
607e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
608e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
609e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
610e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
611e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
612e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
613e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 's', 'c'):
614e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
615e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            status_t err =
616e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mLastTrack->sampleTable->setSampleToChunkParams(
617e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, chunk_data_size);
618e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
619e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (err != OK) {
620e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return err;
621e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
622e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
623e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
624e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
625e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
626e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
627e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 's', 'z'):
628e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 'z', '2'):
629e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
630e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            status_t err =
631e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mLastTrack->sampleTable->setSampleSizeParams(
632e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        chunk_type, data_offset, chunk_data_size);
633e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
634e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (err != OK) {
635e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return err;
636e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
637e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
638e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
639e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
640e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
641e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
642e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 't', 's'):
643e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
644e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            status_t err =
645e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mLastTrack->sampleTable->setTimeToSampleParams(
646e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, chunk_data_size);
647e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
648e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (err != OK) {
649e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return err;
650e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
651e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
652e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
653e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
654e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
655e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
656e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('s', 't', 's', 's'):
657e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
658e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            status_t err =
659e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                mLastTrack->sampleTable->setSyncSampleParams(
660e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, chunk_data_size);
661e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
662e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (err != OK) {
663e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return err;
664e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
665e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
666e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
667e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
668e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
669e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
670e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('e', 's', 'd', 's'):
671e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
672e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size < 4) {
673e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
674e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
675e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
676e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            uint8_t buffer[256];
677e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size > (off_t)sizeof(buffer)) {
678e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
679e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
680e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
681e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (mDataSource->read_at(
682e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
683e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
684e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
685e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
686e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (U32_AT(buffer) != 0) {
687e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                // Should be version 0, flags 0.
688e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_MALFORMED;
689e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
690e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
691e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setData(
692e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
693e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
694e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
695e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
696e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
697e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
698e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        case FOURCC('a', 'v', 'c', 'C'):
699e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
700e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            char buffer[256];
701e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (chunk_data_size > (off_t)sizeof(buffer)) {
702e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
703e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
704e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
705e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (mDataSource->read_at(
706e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
707e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                return ERROR_IO;
708e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
709e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
710e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mLastTrack->meta->setData(
711e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                    kKeyAVCC, kTypeAVCC, buffer, chunk_data_size);
712e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
713e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
714e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
715e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
716e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
717e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        default:
718e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        {
719e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            *offset += chunk_size;
720e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
721e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
722e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
723e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
724e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return OK;
725e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
726e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
727be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
728e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    status_t err;
729e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if ((err = readMetaData()) != OK) {
730be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber        return NULL;
731e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
732e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
733e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    Track *track = mFirstTrack;
734e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    while (index > 0) {
735e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (track == NULL) {
736be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber            return NULL;
737e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
738e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
739e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        track = track->next;
740e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        --index;
741e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
742e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
7432a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber    if (track == NULL) {
7442a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber        return NULL;
7452a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber    }
7462a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber
747be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber    return new MPEG4Source(
748fa8de752507feaca695123911915070c1ce463b2Andreas Huber            track->meta, mDataSource, track->timescale, track->sampleTable);
749e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
750e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
751e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber////////////////////////////////////////////////////////////////////////////////
752e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
753e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberMPEG4Source::MPEG4Source(
754e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        const sp<MetaData> &format,
755be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber        const sp<DataSource> &dataSource,
756fa8de752507feaca695123911915070c1ce463b2Andreas Huber        int32_t timeScale,
757be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber        const sp<SampleTable> &sampleTable)
758e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    : mFormat(format),
759e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mDataSource(dataSource),
760fa8de752507feaca695123911915070c1ce463b2Andreas Huber      mTimescale(timeScale),
761e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mSampleTable(sampleTable),
762e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mCurrentSampleIndex(0),
763e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mIsAVC(false),
764e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mStarted(false),
765e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mGroup(NULL),
766e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mBuffer(NULL),
7674f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber      mWantsNALFragments(false),
7688a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber      mSrcBuffer(NULL) {
769e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    const char *mime;
770e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    bool success = mFormat->findCString(kKeyMIMEType, &mime);
7714f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    CHECK(success);
772e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
773e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber    mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
774e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
775e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
776e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberMPEG4Source::~MPEG4Source() {
777e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (mStarted) {
778e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        stop();
779e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
780e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
781e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
782e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Source::start(MetaData *params) {
7834f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    CHECK(!mStarted);
784e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
785e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    int32_t val;
7864f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    if (params && params->findInt32(kKeyWantsNALFragments, &val)
787e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        && val != 0) {
7884f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        mWantsNALFragments = true;
789e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    } else {
7904f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        mWantsNALFragments = false;
791e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
792e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
793e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mGroup = new MediaBufferGroup;
794e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
795e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    size_t max_size;
796e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    status_t err = mSampleTable->getMaxSampleSize(&max_size);
7974f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    CHECK_EQ(err, OK);
798e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
7998a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    // Assume that a given buffer only contains at most 10 fragments,
8008a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    // each fragment originally prefixed with a 2 byte length will
8018a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
8028a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    // and thus will grow by 2 bytes per fragment.
8038a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    mGroup->add_buffer(new MediaBuffer(max_size + 10 * 2));
8048a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber
8058a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    mSrcBuffer = new uint8_t[max_size];
806e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
807e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mStarted = true;
808e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
809e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return OK;
810e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
811e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
812e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Source::stop() {
8134f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    CHECK(mStarted);
814e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
815e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (mBuffer != NULL) {
816e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        mBuffer->release();
817e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        mBuffer = NULL;
818e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
819e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
8208a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    delete[] mSrcBuffer;
8218a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    mSrcBuffer = NULL;
8228a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber
823e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    delete mGroup;
824e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mGroup = NULL;
825e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
826e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mStarted = false;
827e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mCurrentSampleIndex = 0;
828e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
829e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return OK;
830e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
831e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
832e46b7be812d68e49710b34048662cbf18e2a6550Andreas Hubersp<MetaData> MPEG4Source::getFormat() {
833e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return mFormat;
834e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
835e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
836e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Source::read(
837e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        MediaBuffer **out, const ReadOptions *options) {
8384f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    CHECK(mStarted);
839e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
840e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    *out = NULL;
841e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
842e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    int64_t seekTimeUs;
843e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (options && options->getSeekTo(&seekTimeUs)) {
844e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        uint32_t sampleIndex;
845e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        status_t err = mSampleTable->findClosestSample(
846e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                seekTimeUs * mTimescale / 1000000,
847e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                &sampleIndex, SampleTable::kSyncSample_Flag);
848e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
849e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (err != OK) {
850e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            return err;
851e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
852e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
853e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        mCurrentSampleIndex = sampleIndex;
854e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (mBuffer != NULL) {
855e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mBuffer->release();
856e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mBuffer = NULL;
857e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
858e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
859e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        // fall through
860e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
861e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
8628a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    off_t offset;
8638a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    size_t size;
8644f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    uint32_t dts;
8654f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    bool newBuffer = false;
8664f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    if (mBuffer == NULL) {
8674f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        newBuffer = true;
868e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
8694f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        status_t err = mSampleTable->getSampleOffsetAndSize(
8704f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber                mCurrentSampleIndex, &offset, &size);
871e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
8724f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        if (err != OK) {
8734f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            return err;
8744f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
875e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
8764f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        err = mSampleTable->getDecodingTime(mCurrentSampleIndex, &dts);
877e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
8784f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        if (err != OK) {
8794f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            return err;
8804f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
8814f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
8824f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        err = mGroup->acquire_buffer(&mBuffer);
8834f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        if (err != OK) {
8844f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            CHECK_EQ(mBuffer, NULL);
8854f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            return err;
8864f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
8878a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber    }
888e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
8894f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    if (!mIsAVC || mWantsNALFragments) {
8904f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        if (newBuffer) {
8914f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            ssize_t num_bytes_read =
8924f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber                mDataSource->read_at(offset, (uint8_t *)mBuffer->data(), size);
8934f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
8944f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            if (num_bytes_read < (ssize_t)size) {
8954f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber                mBuffer->release();
8964f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber                mBuffer = NULL;
8974f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
8984f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber                return ERROR_IO;
8994f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            }
9004f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
9014f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            mBuffer->set_range(0, size);
9024f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            mBuffer->meta_data()->clear();
903fa8de752507feaca695123911915070c1ce463b2Andreas Huber            mBuffer->meta_data()->setInt64(
904fa8de752507feaca695123911915070c1ce463b2Andreas Huber                    kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
9054f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            ++mCurrentSampleIndex;
9064f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
9074f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
9084f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        if (!mIsAVC) {
9094f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            *out = mBuffer;
9104f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            mBuffer = NULL;
9114f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
9124f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            return OK;
9134f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
9144f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
9154f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        // Each NAL unit is split up into its constituent fragments and
9164f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        // each one of them returned in its own buffer.
9174f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
9184f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        CHECK(mBuffer->range_length() >= 2);
9194f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
9204f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        const uint8_t *src =
9214f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
9224f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
9234f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        size_t nal_size = U16_AT(src);
9244f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
9254f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        CHECK(mBuffer->range_length() >= 2 + nal_size);
9264f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
9274f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        MediaBuffer *clone = mBuffer->clone();
9284f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        clone->set_range(mBuffer->range_offset() + 2, nal_size);
9294f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
9304f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        mBuffer->set_range(
9314f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber                mBuffer->range_offset() + 2 + nal_size,
9324f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber                mBuffer->range_length() - 2 - nal_size);
9334f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
9344f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        if (mBuffer->range_length() == 0) {
9354f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            mBuffer->release();
9364f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            mBuffer = NULL;
9374f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
9384f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
9394f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        *out = clone;
9404f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
9414f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        return OK;
9424f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber    } else {
9434f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        // Whole NAL units are returned but each fragment is prefixed by
9444f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        // the start code (0x00 00 00 01).
9454f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
946e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        ssize_t num_bytes_read =
9474f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            mDataSource->read_at(offset, mSrcBuffer, size);
948e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
949e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (num_bytes_read < (ssize_t)size) {
950e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mBuffer->release();
951e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            mBuffer = NULL;
952e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
9534f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            return ERROR_IO;
954e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
955e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
9564f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        uint8_t *dstData = (uint8_t *)mBuffer->data();
9574f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        size_t srcOffset = 0;
9584f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        size_t dstOffset = 0;
9594f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        while (srcOffset < size) {
9604f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            CHECK(srcOffset + 1 < size);
9614f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            size_t nalLength =
9624f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber                (mSrcBuffer[srcOffset] << 8) | mSrcBuffer[srcOffset + 1];
9634f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            CHECK(srcOffset + 1 + nalLength < size);
9644f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            srcOffset += 2;
9654f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
9664f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            if (nalLength == 0) {
9674f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber                continue;
9684f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            }
9694f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
9704f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            CHECK(dstOffset + 4 <= mBuffer->size());
9714f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
9724f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            dstData[dstOffset++] = 0;
9734f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            dstData[dstOffset++] = 0;
9744f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            dstData[dstOffset++] = 0;
9754f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            dstData[dstOffset++] = 1;
9764f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
9774f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            srcOffset += nalLength;
9784f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber            dstOffset += nalLength;
9794f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        }
9804f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber
9814f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber        mBuffer->set_range(0, dstOffset);
982e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        mBuffer->meta_data()->clear();
983fa8de752507feaca695123911915070c1ce463b2Andreas Huber        mBuffer->meta_data()->setInt64(
984fa8de752507feaca695123911915070c1ce463b2Andreas Huber                kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
985e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        ++mCurrentSampleIndex;
986e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
987e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        *out = mBuffer;
988e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        mBuffer = NULL;
989e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
990e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return OK;
991e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
992e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
993e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
994be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huberbool SniffMPEG4(
995be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
996e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    uint8_t header[8];
997e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
998e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    ssize_t n = source->read_at(4, header, sizeof(header));
999e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (n < (ssize_t)sizeof(header)) {
1000e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return false;
1001e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1002e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1003e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
1004e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)) {
1005e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber        *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
1006e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        *confidence = 0.1;
1007e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1008e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return true;
1009e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
1010e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1011e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return false;
1012e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
1013e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1014e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}  // namespace android
1015e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1016