MPEG4Extractor.cpp revision 18291bc20e55e8f3fd5feb786771a8ed32c19c59
120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber/*
220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Copyright (C) 2009 The Android Open Source Project
320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * you may not use this file except in compliance with the License.
620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * You may obtain a copy of the License at
720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
1020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Unless required by applicable law or agreed to in writing, software
1120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * See the License for the specific language governing permissions and
1420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * limitations under the License.
1520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber */
1620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#define LOG_TAG "MPEG4Extractor"
1820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/Log.h>
1920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <arpa/inet.h>
2120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <ctype.h>
2320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <stdint.h>
2420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <stdlib.h>
2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <string.h>
2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/DataSource.h>
2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Extractor.h>
2920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h>
3020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBufferGroup.h>
31dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber#include <media/stagefright/MediaDebug.h>
3218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
3320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h>
3420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
3520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/SampleTable.h>
3620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h>
3720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/String8.h>
3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Source : public MediaSource {
4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Caller retains ownership of both "dataSource" and "sampleTable".
44693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    MPEG4Source(const sp<MetaData> &format,
45693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber                const sp<DataSource> &dataSource,
46693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber                const sp<SampleTable> &sampleTable);
4720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t start(MetaData *params = NULL);
4920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t stop();
5020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual sp<MetaData> getFormat();
5220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t read(
5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            MediaBuffer **buffer, const ReadOptions *options = NULL);
5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
56693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huberprotected:
57693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    virtual ~MPEG4Source();
58693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber
5920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
6020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mFormat;
61693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<DataSource> mDataSource;
6220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t mTimescale;
63693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<SampleTable> mSampleTable;
6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t mCurrentSampleIndex;
6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool mIsAVC;
6720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool mStarted;
6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBufferGroup *mGroup;
7020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *mBuffer;
7220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
73dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool mWantsNALFragments;
7420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
750024245e134467d120b40099da16c467dc365e76Andreas Huber    uint8_t *mSrcBuffer;
760024245e134467d120b40099da16c467dc365e76Andreas Huber
7720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source(const MPEG4Source &);
7820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source &operator=(const MPEG4Source &);
7920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
8020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatic void hexdump(const void *_data, size_t size) {
8220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const uint8_t *data = (const uint8_t *)_data;
8320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t offset = 0;
8420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (offset < size) {
8520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf("0x%04x  ", offset);
8620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        size_t n = size - offset;
8820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (n > 16) {
8920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            n = 16;
9020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
9120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        for (size_t i = 0; i < 16; ++i) {
9320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (i == 8) {
9420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf(" ");
9520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
9620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (offset + i < size) {
9820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("%02x ", data[offset + i]);
9920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
10020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("   ");
10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
10320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf(" ");
10520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        for (size_t i = 0; i < n; ++i) {
10720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (isprint(data[offset + i])) {
10820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("%c", data[offset + i]);
10920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
11020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf(".");
11120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
11220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
11320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf("\n");
11520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        offset += 16;
11720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
11820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
11920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huberstatic const char *FourCC2MIME(uint32_t fourcc) {
12120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    switch (fourcc) {
12220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
12318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AAC;
12420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
12618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_NB;
12720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
128371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
12918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_WB;
130371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
13120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
13218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_MPEG4;
13320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
13518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_H263;
13620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
13818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_AVC;
13920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
141dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK(!"should not be here.");
14220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return NULL;
14320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
14420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
14520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
146693d271e62a3726689ff68f4505ba49228eb94b2Andreas HuberMPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
14720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mDataSource(source),
14820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mHaveMetadata(false),
14920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mFirstTrack(NULL),
15020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mLastTrack(NULL) {
15120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
15220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15320111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Extractor::~MPEG4Extractor() {
15420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
15520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (track) {
15620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        Track *next = track->next;
15720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete track;
15920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = next;
16020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
16120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFirstTrack = mLastTrack = NULL;
16220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
16320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
164693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersize_t MPEG4Extractor::countTracks() {
16520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
16620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
167693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return 0;
16820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
16920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
170693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    size_t n = 0;
17120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
17220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (track) {
173693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        ++n;
17420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
17520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
17620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
177693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    return n;
17820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
17920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
180693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersp<MetaData> MPEG4Extractor::getTrackMetaData(size_t index) {
18120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
18220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
18320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return NULL;
18420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
18520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
18620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
18720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
18820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
18920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return NULL;
19020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
19120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
19220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
19320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
19420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
19520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
196371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
197371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
198371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
199371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
20020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return track->meta;
20120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
20220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Extractor::readMetaData() {
20420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mHaveMetadata) {
20520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return OK;
20620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
20720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t offset = 0;
20920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
21020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while ((err = parseChunk(&offset, 0)) == OK) {
21120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
21220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mHaveMetadata) {
21420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return OK;
21520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
21620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return err;
21820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
21920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatic void MakeFourCCString(uint32_t x, char *s) {
22120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    s[0] = x >> 24;
22220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    s[1] = (x >> 16) & 0xff;
22320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    s[2] = (x >> 8) & 0xff;
22420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    s[3] = x & 0xff;
22520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    s[4] = '\0';
22620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
22720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
22920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t hdr[2];
23020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDataSource->read_at(*offset, hdr, 8) < 8) {
23120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_IO;
23220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
23320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint64_t chunk_size = ntohl(hdr[0]);
23420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t chunk_type = ntohl(hdr[1]);
23520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t data_offset = *offset + 8;
23620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (chunk_size == 1) {
23820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mDataSource->read_at(*offset + 8, &chunk_size, 8) < 8) {
23920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_IO;
24020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
24120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        chunk_size = ntoh64(chunk_size);
24220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        data_offset += 8;
24320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
24420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    char chunk[5];
24620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MakeFourCCString(chunk_type, chunk);
24720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#if 0
24920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static const char kWhitespace[] = "                                        ";
25020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth];
25120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    printf("%sfound chunk '%s' of size %lld\n", indent, chunk, chunk_size);
25220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
25320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    char buffer[256];
25420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (chunk_size <= sizeof(buffer)) {
25520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mDataSource->read_at(*offset, buffer, chunk_size) < chunk_size) {
25620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_IO;
25720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
25820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
25920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        hexdump(buffer, chunk_size);
26020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
26120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#endif
26220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t chunk_data_size = *offset + chunk_size - data_offset;
26420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    switch(chunk_type) {
26620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'v'):
26720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'k'):
26820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'i', 'a'):
26920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'i', 'n', 'f'):
27020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('d', 'i', 'n', 'f'):
27120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'b', 'l'):
27220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'v', 'e', 'x'):
27320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'f'):
27420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'f'):
27520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'f', 'r', 'a'):
27620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'k', 'i' ,'p'):
27720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
27820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            off_t stop_offset = *offset + chunk_size;
27920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset;
28020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
28120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
28220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
28320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
28420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
286dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK_EQ(*offset, stop_offset);
28720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mHaveMetadata = true;
29020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return UNKNOWN_ERROR;  // Return a dummy error.
29220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'k', 'h', 'd'):
29720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
298dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK(chunk_data_size >= 4);
29920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t version;
30120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (mDataSource->read_at(data_offset, &version, 1) < 1) {
30220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
30320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
30420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint64_t ctime, mtime, duration;
30620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int32_t id;
30720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t width, height;
30820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
31020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (chunk_data_size != 36 + 60) {
31120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_MALFORMED;
31220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
31320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                uint8_t buffer[36 + 60];
31520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (mDataSource->read_at(
31620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
31720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
31820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
31920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                ctime = U64_AT(&buffer[4]);
32120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mtime = U64_AT(&buffer[12]);
32220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                id = U32_AT(&buffer[20]);
32320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                duration = U64_AT(&buffer[28]);
32420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                width = U32_AT(&buffer[88]);
32520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                height = U32_AT(&buffer[92]);
32620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else if (version == 0) {
32720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (chunk_data_size != 24 + 60) {
32820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_MALFORMED;
32920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
33020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                uint8_t buffer[24 + 60];
33220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (mDataSource->read_at(
33320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
33420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
33520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
33620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                ctime = U32_AT(&buffer[4]);
33720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mtime = U32_AT(&buffer[8]);
33820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                id = U32_AT(&buffer[12]);
33920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                duration = U32_AT(&buffer[20]);
34020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                width = U32_AT(&buffer[76]);
34120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                height = U32_AT(&buffer[80]);
34220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
34320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
34420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            Track *track = new Track;
34520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            track->next = NULL;
34620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (mLastTrack) {
34720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->next = track;
34820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
34920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mFirstTrack = track;
35020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
35120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack = track;
35220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            track->meta = new MetaData;
35420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            track->timescale = 0;
35520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            track->sampleTable = new SampleTable(mDataSource);
35620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            track->meta->setCString(kKeyMIMEType, "application/octet-stream");
35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
35920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
36020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
36120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'h', 'd'):
36320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
36420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
36520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
36620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
36720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t version;
36920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (mDataSource->read_at(
37020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, &version, sizeof(version))
37120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(version)) {
37220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
37320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
37420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            off_t timescale_offset;
37620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
37820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 16;
37920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else if (version == 0) {
38020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 8;
38120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
38220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
38320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
38420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
38520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t timescale;
38620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (mDataSource->read_at(
38720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        timescale_offset, &timescale, sizeof(timescale))
38820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(timescale)) {
38920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
39020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
39120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
39220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->timescale = ntohl(timescale);
39320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyTimeScale, mLastTrack->timescale);
39420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
39520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int64_t duration;
39620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
39720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (mDataSource->read_at(
39820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration, sizeof(duration))
39920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration)) {
40020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
40120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
40220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                duration = ntoh64(duration);
40320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
40420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                int32_t duration32;
40520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (mDataSource->read_at(
40620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration32, sizeof(duration32))
40720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration32)) {
40820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
40920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
41020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                duration = ntohl(duration32);
41120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
41220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyDuration, duration);
41320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
41420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
41520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
41620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
41720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
41820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('h', 'd', 'l', 'r'):
41920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
42020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 25) {
42120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
42220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
42320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
42420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[24];
42520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (mDataSource->read_at(data_offset, buffer, 24) < 24) {
42620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
42720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
42820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
42920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
43020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
43120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
43220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
43320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(&buffer[4]) != 0) {
43520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // pre_defined should be 0.
43620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
43720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
43820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mHandlerType = U32_AT(&buffer[8]);
44020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
44120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
44220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
44320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
44420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'd'):
44520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
44620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 8) {
44720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
44820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
44920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
45020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8];
451dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK(chunk_data_size >= (off_t)sizeof(buffer));
45220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (mDataSource->read_at(
45320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, 8) < 8) {
45420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
45520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
45620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
45720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
45820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
45920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
46020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
46120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
46220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t entry_count = U32_AT(&buffer[4]);
46320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
46420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (entry_count > 1) {
46520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // For now we only support a single type of media per track.
46620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_UNSUPPORTED;
46720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
46820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
46920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            off_t stop_offset = *offset + chunk_size;
47020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + 8;
47120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            for (uint32_t i = 0; i < entry_count; ++i) {
47220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
47320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
47420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
47520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
47620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
477dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK_EQ(*offset, stop_offset);
47820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
47920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
48020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
48120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
48220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
483371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
48420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
48520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (mHandlerType != FOURCC('s', 'o', 'u', 'n')) {
48620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
48720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
48820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
48920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8 + 20];
49020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
49120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic AudioSampleEntry size.
49220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
49320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
49420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
49520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (mDataSource->read_at(
49620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
49720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
49820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
49920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
50020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
50120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t num_channels = U16_AT(&buffer[16]);
50220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
50318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB,
50418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                            FourCC2MIME(chunk_type))
50518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                || !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB,
50618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                               FourCC2MIME(chunk_type))) {
50720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // AMR audio is always mono.
50820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                num_channels = 1;
50920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
51020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
51120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t sample_size = U16_AT(&buffer[18]);
51220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
51320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
51420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            printf("*** coding='%s' %d channels, size %d, rate %d\n",
51520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                   chunk, num_channels, sample_size, sample_rate);
51620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
51720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
51820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
51920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
52020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
52120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            off_t stop_offset = *offset + chunk_size;
52220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
52320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
52420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
52520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
52620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
52720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
52820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
529dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK_EQ(*offset, stop_offset);
53020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
53120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
53220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
53320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
53420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
53520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
53620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
53720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (mHandlerType != FOURCC('v', 'i', 'd', 'e')) {
53820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
53920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
54020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
54120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[78];
54220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
54320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic VideoSampleEntry size.
54420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
54520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
54620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
54720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (mDataSource->read_at(
54820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
54920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
55020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
55120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
55220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
55320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t width = U16_AT(&buffer[6 + 18]);
55420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t height = U16_AT(&buffer[6 + 20]);
55520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
55620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            printf("*** coding='%s' width=%d height=%d\n",
55720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                   chunk, width, height);
55820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
55920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
56020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyWidth, width);
56120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyHeight, height);
56220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
56320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            off_t stop_offset = *offset + chunk_size;
56420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
56520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
56620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
56720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
56820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
56920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
57020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
571dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK_EQ(*offset, stop_offset);
57220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
57320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
57420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
57520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'c', 'o'):
57620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('c', 'o', '6', '4'):
57720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
57820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
57920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setChunkOffsetParams(
58020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
58120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
58220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
58320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
58420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
58520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
58620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
58720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
58820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
58920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
59020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'c'):
59120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
59220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
59320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleToChunkParams(
59420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
59520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
59620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
59720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
59820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
59920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
60020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
60120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
60220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
60320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
60420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'z'):
60520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'z', '2'):
60620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
60720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
60820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleSizeParams(
60920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
61020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
61120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
61220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
61320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
61420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
61520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
61620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
61720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
61820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
61920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 't', 's'):
62020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
62120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
62220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setTimeToSampleParams(
62320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
62420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
62520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
62620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
62720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
62820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
62920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
63020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
63120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
63220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 's'):
63420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
63520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
63620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSyncSampleParams(
63720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
63820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
64020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
64120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
64220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
64420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
64520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
64620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('e', 's', 'd', 's'):
64820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
64920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
65020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
65120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
65220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
65320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[256];
65420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size > (off_t)sizeof(buffer)) {
65520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
65620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
65720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
65820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (mDataSource->read_at(
65920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
66020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
66120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
66220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
66320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
66420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
66520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
66620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
66720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
66820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
66920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
67020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
67120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
67220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
67320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
67420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
67520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', 'C'):
67620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
67720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            char buffer[256];
67820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size > (off_t)sizeof(buffer)) {
67920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
68020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
68120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
68220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (mDataSource->read_at(
68320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
68420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
68520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
68620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
68720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
68820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    kKeyAVCC, kTypeAVCC, buffer, chunk_data_size);
68920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
69020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
69120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
69220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
69320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
69420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
69520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
69620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
69720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
69820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
69920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
70020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
70120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
70220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
70320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
704693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
70520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
70620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
707693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return NULL;
70820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
70920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
71020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
71120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
71220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
713693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber            return NULL;
71420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
71520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
71620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
71720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
71820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
71920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
720371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
721371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
722371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
723371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
724693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    return new MPEG4Source(
72520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            track->meta, mDataSource, track->sampleTable);
72620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
72720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
72820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
72920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
73020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::MPEG4Source(
73120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        const sp<MetaData> &format,
732693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &dataSource,
733693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<SampleTable> &sampleTable)
73420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mFormat(format),
73520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDataSource(dataSource),
73620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mTimescale(0),
73720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSampleTable(sampleTable),
73820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCurrentSampleIndex(0),
73920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mIsAVC(false),
74020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mStarted(false),
74120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mGroup(NULL),
74220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mBuffer(NULL),
743dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber      mWantsNALFragments(false),
7440024245e134467d120b40099da16c467dc365e76Andreas Huber      mSrcBuffer(NULL) {
74520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
74620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mFormat->findCString(kKeyMIMEType, &mime);
747dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(success);
74820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
74920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    success = mFormat->findInt32(kKeyTimeScale, &mTimescale);
750dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(success);
75120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
75218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber    mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
75320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
75420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
75520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::~MPEG4Source() {
75620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mStarted) {
75720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        stop();
75820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
75920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
76020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
76120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::start(MetaData *params) {
762dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(!mStarted);
76320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
76420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t val;
765dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (params && params->findInt32(kKeyWantsNALFragments, &val)
76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        && val != 0) {
767dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = true;
76820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    } else {
769dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = false;
77020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
77120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = new MediaBufferGroup;
77320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t max_size;
77520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err = mSampleTable->getMaxSampleSize(&max_size);
776dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK_EQ(err, OK);
77720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7780024245e134467d120b40099da16c467dc365e76Andreas Huber    // Assume that a given buffer only contains at most 10 fragments,
7790024245e134467d120b40099da16c467dc365e76Andreas Huber    // each fragment originally prefixed with a 2 byte length will
7800024245e134467d120b40099da16c467dc365e76Andreas Huber    // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
7810024245e134467d120b40099da16c467dc365e76Andreas Huber    // and thus will grow by 2 bytes per fragment.
7820024245e134467d120b40099da16c467dc365e76Andreas Huber    mGroup->add_buffer(new MediaBuffer(max_size + 10 * 2));
7830024245e134467d120b40099da16c467dc365e76Andreas Huber
7840024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = new uint8_t[max_size];
78520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
78620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = true;
78720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
78820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
78920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
79020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
79120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::stop() {
792dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
79320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
79420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mBuffer != NULL) {
79520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->release();
79620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
79720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
79820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7990024245e134467d120b40099da16c467dc365e76Andreas Huber    delete[] mSrcBuffer;
8000024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = NULL;
8010024245e134467d120b40099da16c467dc365e76Andreas Huber
80220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    delete mGroup;
80320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = NULL;
80420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
80520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = false;
80620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mCurrentSampleIndex = 0;
80720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
80820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
80920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
81020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
81120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> MPEG4Source::getFormat() {
81220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return mFormat;
81320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
81420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
81520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::read(
81620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        MediaBuffer **out, const ReadOptions *options) {
817dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
81820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
81920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *out = NULL;
82020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
82120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t seekTimeUs;
82220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (options && options->getSeekTo(&seekTimeUs)) {
82320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        uint32_t sampleIndex;
82420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        status_t err = mSampleTable->findClosestSample(
82520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                seekTimeUs * mTimescale / 1000000,
82620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                &sampleIndex, SampleTable::kSyncSample_Flag);
82720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
82820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (err != OK) {
82920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return err;
83020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
83120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
83220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCurrentSampleIndex = sampleIndex;
83320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mBuffer != NULL) {
83420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
83520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
83620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
83720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
83820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // fall through
83920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
84020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8410024245e134467d120b40099da16c467dc365e76Andreas Huber    off_t offset;
8420024245e134467d120b40099da16c467dc365e76Andreas Huber    size_t size;
843dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    uint32_t dts;
844dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool newBuffer = false;
845dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (mBuffer == NULL) {
846dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        newBuffer = true;
84720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
848dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        status_t err = mSampleTable->getSampleOffsetAndSize(
849dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mCurrentSampleIndex, &offset, &size);
85020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
851dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
852dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
853dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
85420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
855dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        err = mSampleTable->getDecodingTime(mCurrentSampleIndex, &dts);
85620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
857dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
858dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
859dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
860dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
861dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        err = mGroup->acquire_buffer(&mBuffer);
862dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
863dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK_EQ(mBuffer, NULL);
864dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
865dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
8660024245e134467d120b40099da16c467dc365e76Andreas Huber    }
86720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
868dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (!mIsAVC || mWantsNALFragments) {
869dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (newBuffer) {
870dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ssize_t num_bytes_read =
871dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mDataSource->read_at(offset, (uint8_t *)mBuffer->data(), size);
872dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
873dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            if (num_bytes_read < (ssize_t)size) {
874dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer->release();
875dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer = NULL;
876dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
877dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                return ERROR_IO;
878dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            }
879dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
880dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->set_range(0, size);
881dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->meta_data()->clear();
882dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->meta_data()->setInt32(kKeyTimeUnits, dts);
883dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->meta_data()->setInt32(kKeyTimeScale, mTimescale);
884dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ++mCurrentSampleIndex;
885dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
886dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
887dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (!mIsAVC) {
888dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            *out = mBuffer;
889dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
890dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
891dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return OK;
892dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
893dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
894dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Each NAL unit is split up into its constituent fragments and
895dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // each one of them returned in its own buffer.
896dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
897dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        CHECK(mBuffer->range_length() >= 2);
898dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
899dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        const uint8_t *src =
900dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
901dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
902dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        size_t nal_size = U16_AT(src);
903dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
904dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        CHECK(mBuffer->range_length() >= 2 + nal_size);
905dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
906dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        MediaBuffer *clone = mBuffer->clone();
907dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        clone->set_range(mBuffer->range_offset() + 2, nal_size);
908dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
909dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mBuffer->set_range(
910dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer->range_offset() + 2 + nal_size,
911dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer->range_length() - 2 - nal_size);
912dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
913dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (mBuffer->range_length() == 0) {
914dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->release();
915dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
916dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
917dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
918dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        *out = clone;
919dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
920dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        return OK;
921dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    } else {
922dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Whole NAL units are returned but each fragment is prefixed by
923dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // the start code (0x00 00 00 01).
924dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
92520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        ssize_t num_bytes_read =
926dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mDataSource->read_at(offset, mSrcBuffer, size);
92720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
92820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (num_bytes_read < (ssize_t)size) {
92920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
93020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
93120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
932dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return ERROR_IO;
93320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
93420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
935dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        uint8_t *dstData = (uint8_t *)mBuffer->data();
936dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        size_t srcOffset = 0;
937dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        size_t dstOffset = 0;
938dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        while (srcOffset < size) {
939dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK(srcOffset + 1 < size);
940dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            size_t nalLength =
941dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                (mSrcBuffer[srcOffset] << 8) | mSrcBuffer[srcOffset + 1];
942dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK(srcOffset + 1 + nalLength < size);
943dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            srcOffset += 2;
944dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
945dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            if (nalLength == 0) {
946dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                continue;
947dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            }
948dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
949dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK(dstOffset + 4 <= mBuffer->size());
950dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
951dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            dstData[dstOffset++] = 0;
952dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            dstData[dstOffset++] = 0;
953dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            dstData[dstOffset++] = 0;
954dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            dstData[dstOffset++] = 1;
955dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
956dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            srcOffset += nalLength;
957dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            dstOffset += nalLength;
958dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
959dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
960dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mBuffer->set_range(0, dstOffset);
96120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->meta_data()->clear();
96220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->meta_data()->setInt32(kKeyTimeUnits, dts);
96320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->meta_data()->setInt32(kKeyTimeScale, mTimescale);
96420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        ++mCurrentSampleIndex;
96520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
96620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        *out = mBuffer;
96720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
96820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
96920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return OK;
97020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
97120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
97220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
973693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huberbool SniffMPEG4(
974693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
97520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint8_t header[8];
97620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
97720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ssize_t n = source->read_at(4, header, sizeof(header));
97820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (n < (ssize_t)sizeof(header)) {
97920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return false;
98020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
98120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
98220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
98320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)) {
98418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
98520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        *confidence = 0.1;
98620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
98720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return true;
98820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
98920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
99020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return false;
99120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
99220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
99320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
99420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
995