MPEG4Extractor.cpp revision 66326a5ee0869f1ee4d136a477e6effba428b3cb
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
2066326a5ee0869f1ee4d136a477e6effba428b3cbAndreas Huber#include "include/MPEG4Extractor.h"
2189e69da4d86348409994c9dafbbb2634ccd7c196Andreas Huber#include "include/SampleTable.h"
2289e69da4d86348409994c9dafbbb2634ccd7c196Andreas Huber
2320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <arpa/inet.h>
2420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <ctype.h>
2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <stdint.h>
2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <stdlib.h>
2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <string.h>
2920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/DataSource.h>
3120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h>
3220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBufferGroup.h>
33dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber#include <media/stagefright/MediaDebug.h>
3418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
3520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h>
3620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
3720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h>
3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/String8.h>
3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Source : public MediaSource {
4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Caller retains ownership of both "dataSource" and "sampleTable".
45693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    MPEG4Source(const sp<MetaData> &format,
46693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber                const sp<DataSource> &dataSource,
4748c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                int32_t timeScale,
48693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber                const sp<SampleTable> &sampleTable);
4920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t start(MetaData *params = NULL);
5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t stop();
5220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual sp<MetaData> getFormat();
5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t read(
5620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            MediaBuffer **buffer, const ReadOptions *options = NULL);
5720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
58693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huberprotected:
59693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    virtual ~MPEG4Source();
60693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber
6120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
6220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mFormat;
63693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<DataSource> mDataSource;
6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t mTimescale;
65693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<SampleTable> mSampleTable;
6620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t mCurrentSampleIndex;
6720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool mIsAVC;
6920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool mStarted;
7020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBufferGroup *mGroup;
7220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *mBuffer;
7420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
75dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool mWantsNALFragments;
7620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
770024245e134467d120b40099da16c467dc365e76Andreas Huber    uint8_t *mSrcBuffer;
780024245e134467d120b40099da16c467dc365e76Andreas Huber
7920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source(const MPEG4Source &);
8020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source &operator=(const MPEG4Source &);
8120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
8220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatic void hexdump(const void *_data, size_t size) {
8420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const uint8_t *data = (const uint8_t *)_data;
8520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t offset = 0;
8620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (offset < size) {
8720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf("0x%04x  ", offset);
8820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        size_t n = size - offset;
9020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (n > 16) {
9120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            n = 16;
9220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
9320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        for (size_t i = 0; i < 16; ++i) {
9520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (i == 8) {
9620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf(" ");
9720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
9820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (offset + i < size) {
10020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("%02x ", data[offset + i]);
10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("   ");
10320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
10420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
10520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf(" ");
10720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        for (size_t i = 0; i < n; ++i) {
10920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (isprint(data[offset + i])) {
11020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("%c", data[offset + i]);
11120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
11220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf(".");
11320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
11420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
11520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf("\n");
11720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        offset += 16;
11920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
12020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
12120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huberstatic const char *FourCC2MIME(uint32_t fourcc) {
12320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    switch (fourcc) {
12420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
12518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AAC;
12620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
12818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_NB;
12920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
130371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
13118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_WB;
132371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
13320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
13418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_MPEG4;
13520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
13718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_H263;
13820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
14018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_AVC;
14120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
143dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK(!"should not be here.");
14420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return NULL;
14520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
14620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
14720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
148693d271e62a3726689ff68f4505ba49228eb94b2Andreas HuberMPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
14920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mDataSource(source),
15020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mHaveMetadata(false),
15120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mFirstTrack(NULL),
15220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mLastTrack(NULL) {
15320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
15420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Extractor::~MPEG4Extractor() {
15620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
15720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (track) {
15820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        Track *next = track->next;
15920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
16020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete track;
16120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = next;
16220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
16320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFirstTrack = mLastTrack = NULL;
16420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
16520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
166693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersize_t MPEG4Extractor::countTracks() {
16720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
16820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
169693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return 0;
17020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
17120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
172693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    size_t n = 0;
17320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
17420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (track) {
175693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        ++n;
17620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
17720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
17820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
179693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    return n;
18020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
18120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1827e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Hubersp<MetaData> MPEG4Extractor::getTrackMetaData(
1837e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        size_t index, uint32_t flags) {
18420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
18520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
18620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return NULL;
18720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
18820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
18920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
19020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
19120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
19220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return NULL;
19320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
19420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
19520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
19620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
19720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
19820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
199371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
200371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
201371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
202371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
2037e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    if ((flags & kIncludeExtensiveMetaData)
2047e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            && !track->includes_expensive_metadata) {
2057e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        track->includes_expensive_metadata = true;
2067e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
2077e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        const char *mime;
2087e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        CHECK(track->meta->findCString(kKeyMIMEType, &mime));
2097e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        if (!strncasecmp("video/", mime, 6)) {
2107e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            uint32_t sampleIndex;
2117e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            uint32_t sampleTime;
2127e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK
2137e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                    && track->sampleTable->getDecodingTime(
2147e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                        sampleIndex, &sampleTime) == OK) {
2157e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                track->meta->setInt64(
2167e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                        kKeyThumbnailTime,
2177e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                        ((int64_t)sampleTime * 1000000) / track->timescale);
2187e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            }
2197e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        }
2207e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    }
2217e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
22220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return track->meta;
22320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
22420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Extractor::readMetaData() {
22620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mHaveMetadata) {
22720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return OK;
22820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
22920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t offset = 0;
23120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
23220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while ((err = parseChunk(&offset, 0)) == OK) {
23320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
23420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mHaveMetadata) {
23620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return OK;
23720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
23820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return err;
24020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
24120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatic void MakeFourCCString(uint32_t x, char *s) {
24320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    s[0] = x >> 24;
24420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    s[1] = (x >> 16) & 0xff;
24520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    s[2] = (x >> 8) & 0xff;
24620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    s[3] = x & 0xff;
24720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    s[4] = '\0';
24820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
24920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
25020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
25120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t hdr[2];
25220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDataSource->read_at(*offset, hdr, 8) < 8) {
25320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_IO;
25420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
25520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint64_t chunk_size = ntohl(hdr[0]);
25620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t chunk_type = ntohl(hdr[1]);
25720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t data_offset = *offset + 8;
25820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
25920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (chunk_size == 1) {
26020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mDataSource->read_at(*offset + 8, &chunk_size, 8) < 8) {
26120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_IO;
26220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
26320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        chunk_size = ntoh64(chunk_size);
26420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        data_offset += 8;
26520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
26620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    char chunk[5];
26820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MakeFourCCString(chunk_type, chunk);
26920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#if 0
27120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static const char kWhitespace[] = "                                        ";
27220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth];
27320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    printf("%sfound chunk '%s' of size %lld\n", indent, chunk, chunk_size);
27420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    char buffer[256];
27620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (chunk_size <= sizeof(buffer)) {
27720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mDataSource->read_at(*offset, buffer, chunk_size) < chunk_size) {
27820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_IO;
27920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
28020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        hexdump(buffer, chunk_size);
28220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
28320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#endif
28420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t chunk_data_size = *offset + chunk_size - data_offset;
28620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    switch(chunk_type) {
28820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'v'):
28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'k'):
29020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'i', 'a'):
29120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'i', 'n', 'f'):
29220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('d', 'i', 'n', 'f'):
29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'b', 'l'):
29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'v', 'e', 'x'):
29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'f'):
29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'f'):
29720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'f', 'r', 'a'):
29820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'k', 'i' ,'p'):
29920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
30020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            off_t stop_offset = *offset + chunk_size;
30120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset;
30220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
30320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
30420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
30520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
30620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
30720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
308dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK_EQ(*offset, stop_offset);
30920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
31120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mHaveMetadata = true;
31220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return UNKNOWN_ERROR;  // Return a dummy error.
31420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
31520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
31620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
31720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'k', 'h', 'd'):
31920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
320dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK(chunk_data_size >= 4);
32120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t version;
32320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (mDataSource->read_at(data_offset, &version, 1) < 1) {
32420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
32520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
32620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint64_t ctime, mtime, duration;
32820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int32_t id;
32920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t width, height;
33020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
33220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (chunk_data_size != 36 + 60) {
33320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_MALFORMED;
33420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
33520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                uint8_t buffer[36 + 60];
33720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (mDataSource->read_at(
33820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
33920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
34020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
34120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
34220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                ctime = U64_AT(&buffer[4]);
34320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mtime = U64_AT(&buffer[12]);
34420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                id = U32_AT(&buffer[20]);
34520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                duration = U64_AT(&buffer[28]);
34620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                width = U32_AT(&buffer[88]);
34720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                height = U32_AT(&buffer[92]);
34820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else if (version == 0) {
34920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (chunk_data_size != 24 + 60) {
35020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_MALFORMED;
35120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
35220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                uint8_t buffer[24 + 60];
35420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (mDataSource->read_at(
35520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
35620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                ctime = U32_AT(&buffer[4]);
35920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mtime = U32_AT(&buffer[8]);
36020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                id = U32_AT(&buffer[12]);
36120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                duration = U32_AT(&buffer[20]);
36220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                width = U32_AT(&buffer[76]);
36320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                height = U32_AT(&buffer[80]);
36420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
36520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            Track *track = new Track;
36720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            track->next = NULL;
36820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (mLastTrack) {
36920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->next = track;
37020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
37120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mFirstTrack = track;
37220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
37320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack = track;
37420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            track->meta = new MetaData;
3767e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            track->includes_expensive_metadata = false;
37720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            track->timescale = 0;
37820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            track->sampleTable = new SampleTable(mDataSource);
37920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            track->meta->setCString(kKeyMIMEType, "application/octet-stream");
38020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
38120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
38220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
38320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
38420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
38520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'h', 'd'):
38620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
38720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
38820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
38920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
39020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
39120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t version;
39220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (mDataSource->read_at(
39320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, &version, sizeof(version))
39420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(version)) {
39520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
39620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
39720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
39820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            off_t timescale_offset;
39920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
40020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
40120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 16;
40220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else if (version == 0) {
40320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 8;
40420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
40520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
40620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
40720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
40820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t timescale;
40920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (mDataSource->read_at(
41020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        timescale_offset, &timescale, sizeof(timescale))
41120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(timescale)) {
41220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
41320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
41420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
41520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->timescale = ntohl(timescale);
41620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
41720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int64_t duration;
41820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
41920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (mDataSource->read_at(
42020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration, sizeof(duration))
42120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration)) {
42220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
42320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
42420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                duration = ntoh64(duration);
42520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
42620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                int32_t duration32;
42720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (mDataSource->read_at(
42820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration32, sizeof(duration32))
42920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration32)) {
43020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
43120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
43220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                duration = ntohl(duration32);
43320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
43448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            mLastTrack->meta->setInt64(
43548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                    kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
43620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
43820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
43920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
44020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
44120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('h', 'd', 'l', 'r'):
44220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
44320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 25) {
44420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
44520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
44620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
44720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[24];
44820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (mDataSource->read_at(data_offset, buffer, 24) < 24) {
44920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
45020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
45120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
45220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
45320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
45420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
45520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
45620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
45720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(&buffer[4]) != 0) {
45820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // pre_defined should be 0.
45920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
46020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
46120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
46220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mHandlerType = U32_AT(&buffer[8]);
46320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
46420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
46520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
46620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
46720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'd'):
46820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
46920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 8) {
47020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
47120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
47220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
47320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8];
474dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK(chunk_data_size >= (off_t)sizeof(buffer));
47520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (mDataSource->read_at(
47620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, 8) < 8) {
47720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
47820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
47920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
48020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
48120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
48220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
48320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
48420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
48520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t entry_count = U32_AT(&buffer[4]);
48620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
48720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (entry_count > 1) {
48820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // For now we only support a single type of media per track.
48920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_UNSUPPORTED;
49020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
49120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
49220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            off_t stop_offset = *offset + chunk_size;
49320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + 8;
49420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            for (uint32_t i = 0; i < entry_count; ++i) {
49520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
49620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
49720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
49820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
49920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
500dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK_EQ(*offset, stop_offset);
50120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
50220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
50320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
50420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
50520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
506371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
50720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
50820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (mHandlerType != FOURCC('s', 'o', 'u', 'n')) {
50920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
51020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
51120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
51220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8 + 20];
51320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
51420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic AudioSampleEntry size.
51520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
51620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
51720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
51820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (mDataSource->read_at(
51920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
52020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
52120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
52220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
52320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
52420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t num_channels = U16_AT(&buffer[16]);
52520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
52618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB,
52718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                            FourCC2MIME(chunk_type))
52818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                || !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB,
52918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                               FourCC2MIME(chunk_type))) {
53020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // AMR audio is always mono.
53120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                num_channels = 1;
53220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
53320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
53420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t sample_size = U16_AT(&buffer[18]);
53520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
53620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
53720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            printf("*** coding='%s' %d channels, size %d, rate %d\n",
53820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                   chunk, num_channels, sample_size, sample_rate);
53920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
54020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
54120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
54220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
54320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
54420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            off_t stop_offset = *offset + chunk_size;
54520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
54620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
54720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
54820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
54920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
55020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
55120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
552dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK_EQ(*offset, stop_offset);
55320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
55420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
55520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
55620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
55720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
55820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
55920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
56020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (mHandlerType != FOURCC('v', 'i', 'd', 'e')) {
56120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
56220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
56320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
56420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[78];
56520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
56620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic VideoSampleEntry size.
56720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
56820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
56920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
57020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (mDataSource->read_at(
57120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
57220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
57320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
57420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
57520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
57620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t width = U16_AT(&buffer[6 + 18]);
57720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t height = U16_AT(&buffer[6 + 20]);
57820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
57920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            printf("*** coding='%s' width=%d height=%d\n",
58020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                   chunk, width, height);
58120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
58220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
58320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyWidth, width);
58420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyHeight, height);
58520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
58620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            off_t stop_offset = *offset + chunk_size;
58720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
58820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
58920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
59020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
59120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
59220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
59320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
594dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK_EQ(*offset, stop_offset);
59520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
59620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
59720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
59820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'c', 'o'):
59920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('c', 'o', '6', '4'):
60020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
60120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
60220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setChunkOffsetParams(
60320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
60420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
60520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
60620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
60720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
60820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
60920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
61020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
61120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
61220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
61320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'c'):
61420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
61520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
61620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleToChunkParams(
61720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
61820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
61920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
62020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
62120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
62220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
62320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
62420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
62520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
62620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
62720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'z'):
62820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'z', '2'):
62920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
63020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
63120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleSizeParams(
63220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
63320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
63520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
63620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
63720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
63920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
64020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
64120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 't', 's'):
64320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
64420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
64520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setTimeToSampleParams(
64620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
64720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
64920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
65020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
65120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
65220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
65320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
65420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
65520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
65620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 's'):
65720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
65820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
65920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSyncSampleParams(
66020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
66120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
66220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
66320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
66420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
66520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
66620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
66720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
66820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
66920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
67020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('e', 's', 'd', 's'):
67120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
67220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
67320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
67420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
67520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
67620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[256];
67720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size > (off_t)sizeof(buffer)) {
67820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
67920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
68020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
68120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (mDataSource->read_at(
68220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
68320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
68420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
68520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
68620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
68720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
68820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
68920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
69020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
69120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
69220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
69320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
69420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
69520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
69620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
69720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
69820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', 'C'):
69920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
70020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            char buffer[256];
70120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size > (off_t)sizeof(buffer)) {
70220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
70320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
70420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
70520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (mDataSource->read_at(
70620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
70720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
70820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
70920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
71020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
71120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    kKeyAVCC, kTypeAVCC, buffer, chunk_data_size);
71220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
71320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
71420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
71520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
71620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
71720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
71820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
71920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
72020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
72120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
72220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
72320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
72420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
72520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
72620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
727693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
72820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
72920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
730693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return NULL;
73120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
73220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
73320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
73420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
73520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
736693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber            return NULL;
73720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
73820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
73920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
74020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
74120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
74220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
743371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
744371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
745371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
746371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
747693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    return new MPEG4Source(
74848c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            track->meta, mDataSource, track->timescale, track->sampleTable);
74920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
75020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
75120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
75220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
75320111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::MPEG4Source(
75420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        const sp<MetaData> &format,
755693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &dataSource,
75648c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        int32_t timeScale,
757693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<SampleTable> &sampleTable)
75820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mFormat(format),
75920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDataSource(dataSource),
76048c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber      mTimescale(timeScale),
76120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSampleTable(sampleTable),
76220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCurrentSampleIndex(0),
76320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mIsAVC(false),
76420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mStarted(false),
76520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mGroup(NULL),
76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mBuffer(NULL),
767dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber      mWantsNALFragments(false),
7680024245e134467d120b40099da16c467dc365e76Andreas Huber      mSrcBuffer(NULL) {
76920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
77020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mFormat->findCString(kKeyMIMEType, &mime);
771dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(success);
77220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber    mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
77420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
77520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77620111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::~MPEG4Source() {
77720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mStarted) {
77820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        stop();
77920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
78020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
78120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
78220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::start(MetaData *params) {
783dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(!mStarted);
78420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
78520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t val;
786dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (params && params->findInt32(kKeyWantsNALFragments, &val)
78720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        && val != 0) {
788dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = true;
78920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    } else {
790dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = false;
79120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
79220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
79320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = new MediaBufferGroup;
79420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
79520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t max_size;
79620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err = mSampleTable->getMaxSampleSize(&max_size);
797dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK_EQ(err, OK);
79820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7990024245e134467d120b40099da16c467dc365e76Andreas Huber    // Assume that a given buffer only contains at most 10 fragments,
8000024245e134467d120b40099da16c467dc365e76Andreas Huber    // each fragment originally prefixed with a 2 byte length will
8010024245e134467d120b40099da16c467dc365e76Andreas Huber    // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
8020024245e134467d120b40099da16c467dc365e76Andreas Huber    // and thus will grow by 2 bytes per fragment.
8030024245e134467d120b40099da16c467dc365e76Andreas Huber    mGroup->add_buffer(new MediaBuffer(max_size + 10 * 2));
8040024245e134467d120b40099da16c467dc365e76Andreas Huber
8050024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = new uint8_t[max_size];
80620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
80720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = true;
80820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
80920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
81020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
81120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
81220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::stop() {
813dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
81420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
81520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mBuffer != NULL) {
81620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->release();
81720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
81820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
81920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8200024245e134467d120b40099da16c467dc365e76Andreas Huber    delete[] mSrcBuffer;
8210024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = NULL;
8220024245e134467d120b40099da16c467dc365e76Andreas Huber
82320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    delete mGroup;
82420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = NULL;
82520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
82620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = false;
82720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mCurrentSampleIndex = 0;
82820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
82920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
83020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
83120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
83220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> MPEG4Source::getFormat() {
83320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return mFormat;
83420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
83520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
83620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::read(
83720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        MediaBuffer **out, const ReadOptions *options) {
838dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
83920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
84020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *out = NULL;
84120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
84220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t seekTimeUs;
84320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (options && options->getSeekTo(&seekTimeUs)) {
84420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        uint32_t sampleIndex;
84520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        status_t err = mSampleTable->findClosestSample(
84620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                seekTimeUs * mTimescale / 1000000,
84720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                &sampleIndex, SampleTable::kSyncSample_Flag);
84820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
84920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (err != OK) {
85020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return err;
85120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
85220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
85320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCurrentSampleIndex = sampleIndex;
85420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mBuffer != NULL) {
85520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
85620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
85720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
85820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
85920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // fall through
86020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
86120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8620024245e134467d120b40099da16c467dc365e76Andreas Huber    off_t offset;
8630024245e134467d120b40099da16c467dc365e76Andreas Huber    size_t size;
864dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    uint32_t dts;
865dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool newBuffer = false;
866dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (mBuffer == NULL) {
867dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        newBuffer = true;
86820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
869dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        status_t err = mSampleTable->getSampleOffsetAndSize(
870dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mCurrentSampleIndex, &offset, &size);
87120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
872dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
873dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
874dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
87520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
876dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        err = mSampleTable->getDecodingTime(mCurrentSampleIndex, &dts);
87720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
878dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
879dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
880dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
881dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
882dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        err = mGroup->acquire_buffer(&mBuffer);
883dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
884dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK_EQ(mBuffer, NULL);
885dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
886dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
8870024245e134467d120b40099da16c467dc365e76Andreas Huber    }
88820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
889dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (!mIsAVC || mWantsNALFragments) {
890dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (newBuffer) {
891dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ssize_t num_bytes_read =
892dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mDataSource->read_at(offset, (uint8_t *)mBuffer->data(), size);
893dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
894dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            if (num_bytes_read < (ssize_t)size) {
895dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer->release();
896dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer = NULL;
897dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
898dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                return ERROR_IO;
899dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            }
900dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
901dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->set_range(0, size);
902dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->meta_data()->clear();
90348c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            mBuffer->meta_data()->setInt64(
90448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                    kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
905dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ++mCurrentSampleIndex;
906dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
907dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
908dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (!mIsAVC) {
909dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            *out = mBuffer;
910dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
911dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
912dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return OK;
913dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
914dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
915dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Each NAL unit is split up into its constituent fragments and
916dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // each one of them returned in its own buffer.
917dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
918dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        CHECK(mBuffer->range_length() >= 2);
919dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
920dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        const uint8_t *src =
921dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
922dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
923dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        size_t nal_size = U16_AT(src);
924dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
925dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        CHECK(mBuffer->range_length() >= 2 + nal_size);
926dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
927dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        MediaBuffer *clone = mBuffer->clone();
928dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        clone->set_range(mBuffer->range_offset() + 2, nal_size);
929dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
930dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mBuffer->set_range(
931dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer->range_offset() + 2 + nal_size,
932dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer->range_length() - 2 - nal_size);
933dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
934dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (mBuffer->range_length() == 0) {
935dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->release();
936dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
937dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
938dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
939dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        *out = clone;
940dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
941dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        return OK;
942dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    } else {
943dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Whole NAL units are returned but each fragment is prefixed by
944dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // the start code (0x00 00 00 01).
945dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
94620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        ssize_t num_bytes_read =
947dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mDataSource->read_at(offset, mSrcBuffer, size);
94820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
94920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (num_bytes_read < (ssize_t)size) {
95020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
95120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
95220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
953dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return ERROR_IO;
95420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
95520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
956dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        uint8_t *dstData = (uint8_t *)mBuffer->data();
957dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        size_t srcOffset = 0;
958dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        size_t dstOffset = 0;
959dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        while (srcOffset < size) {
960dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK(srcOffset + 1 < size);
961dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            size_t nalLength =
962dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                (mSrcBuffer[srcOffset] << 8) | mSrcBuffer[srcOffset + 1];
963dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK(srcOffset + 1 + nalLength < size);
964dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            srcOffset += 2;
965dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
966dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            if (nalLength == 0) {
967dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                continue;
968dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            }
969dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
970dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK(dstOffset + 4 <= mBuffer->size());
971dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
972dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            dstData[dstOffset++] = 0;
973dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            dstData[dstOffset++] = 0;
974dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            dstData[dstOffset++] = 0;
975dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            dstData[dstOffset++] = 1;
976dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
977dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            srcOffset += nalLength;
978dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            dstOffset += nalLength;
979dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
980dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
981dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mBuffer->set_range(0, dstOffset);
98220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->meta_data()->clear();
98348c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        mBuffer->meta_data()->setInt64(
98448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
98520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        ++mCurrentSampleIndex;
98620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
98720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        *out = mBuffer;
98820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
98920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
99020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return OK;
99120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
99220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
99320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
994693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huberbool SniffMPEG4(
995693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
99620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint8_t header[8];
99720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
99820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ssize_t n = source->read_at(4, header, sizeof(header));
99920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (n < (ssize_t)sizeof(header)) {
100020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return false;
100120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
100220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
100320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
100420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)) {
100518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
100620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        *confidence = 0.1;
100720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
100820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return true;
100920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
101020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
101120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return false;
101220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
101320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
101420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
101520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1016