MPEG4Extractor.cpp revision e8a084958c27327b0aca749f69095605d2a21309
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;
696064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    size_t mNALLengthSize;
706064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
7120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool mStarted;
7220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBufferGroup *mGroup;
7420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *mBuffer;
7620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool mWantsNALFragments;
7820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
790024245e134467d120b40099da16c467dc365e76Andreas Huber    uint8_t *mSrcBuffer;
800024245e134467d120b40099da16c467dc365e76Andreas Huber
816064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    size_t parseNALSize(const uint8_t *data) const;
826064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
8320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source(const MPEG4Source &);
8420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source &operator=(const MPEG4Source &);
8520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
8620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatic void hexdump(const void *_data, size_t size) {
8820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const uint8_t *data = (const uint8_t *)_data;
8920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t offset = 0;
9020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (offset < size) {
9120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf("0x%04x  ", offset);
9220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        size_t n = size - offset;
9420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (n > 16) {
9520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            n = 16;
9620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
9720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        for (size_t i = 0; i < 16; ++i) {
9920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (i == 8) {
10020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf(" ");
10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (offset + i < size) {
10420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("%02x ", data[offset + i]);
10520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
10620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("   ");
10720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
10820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
10920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf(" ");
11120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        for (size_t i = 0; i < n; ++i) {
11320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (isprint(data[offset + i])) {
11420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("%c", data[offset + i]);
11520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
11620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf(".");
11720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
11820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
11920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf("\n");
12120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        offset += 16;
12320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
12420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
12520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huberstatic const char *FourCC2MIME(uint32_t fourcc) {
12720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    switch (fourcc) {
12820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
12918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AAC;
13020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
13218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_NB;
13320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
134371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
13518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_WB;
136371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
13720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
13818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_MPEG4;
13920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
14118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_H263;
14220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
14418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_AVC;
14520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
147dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK(!"should not be here.");
14820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return NULL;
14920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
15020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
15120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
152693d271e62a3726689ff68f4505ba49228eb94b2Andreas HuberMPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
15320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mDataSource(source),
15420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mHaveMetadata(false),
1557be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber      mHasVideo(false),
15620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mFirstTrack(NULL),
15720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mLastTrack(NULL) {
15820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
15920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
16020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Extractor::~MPEG4Extractor() {
16120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
16220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (track) {
16320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        Track *next = track->next;
16420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
16520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete track;
16620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = next;
16720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
16820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFirstTrack = mLastTrack = NULL;
16920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
17020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1717be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Hubersp<MetaData> MPEG4Extractor::getMetaData() {
1727be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    sp<MetaData> meta = new MetaData;
1737be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
1747be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    status_t err;
1757be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    if ((err = readMetaData()) != OK) {
1767be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber        return meta;
1777be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    }
1787be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
1797be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    if (mHasVideo) {
1807be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber        meta->setCString(kKeyMIMEType, "video/mp4");
1817be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    } else {
1827be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber        meta->setCString(kKeyMIMEType, "audio/mp4");
1837be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    }
1847be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
1857be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    return meta;
1867be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber}
1877be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
188693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersize_t MPEG4Extractor::countTracks() {
18920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
19020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
191693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return 0;
19220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
19320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
194693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    size_t n = 0;
19520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
19620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (track) {
197693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        ++n;
19820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
19920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
20020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
201693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    return n;
20220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
20320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2047e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Hubersp<MetaData> MPEG4Extractor::getTrackMetaData(
2057e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        size_t index, uint32_t flags) {
20620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
20720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
20820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return NULL;
20920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
21020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
21220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
21320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
21420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return NULL;
21520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
21620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
21820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
21920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
22020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
221371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
222371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
223371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
224371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
2257e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    if ((flags & kIncludeExtensiveMetaData)
2267e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            && !track->includes_expensive_metadata) {
2277e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        track->includes_expensive_metadata = true;
2287e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
2297e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        const char *mime;
2307e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        CHECK(track->meta->findCString(kKeyMIMEType, &mime));
2317e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        if (!strncasecmp("video/", mime, 6)) {
2327e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            uint32_t sampleIndex;
2337e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            uint32_t sampleTime;
2347e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK
2357e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                    && track->sampleTable->getDecodingTime(
2367e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                        sampleIndex, &sampleTime) == OK) {
2377e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                track->meta->setInt64(
2387e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                        kKeyThumbnailTime,
2397e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                        ((int64_t)sampleTime * 1000000) / track->timescale);
2407e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            }
2417e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        }
2427e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    }
2437e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
24420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return track->meta;
24520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
24620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Extractor::readMetaData() {
24820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mHaveMetadata) {
24920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return OK;
25020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
25120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
25220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t offset = 0;
25320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
25420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while ((err = parseChunk(&offset, 0)) == OK) {
25520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
2567be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
25720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mHaveMetadata) {
25820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return OK;
25920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
26020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return err;
26220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
26320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatic void MakeFourCCString(uint32_t x, char *s) {
26520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    s[0] = x >> 24;
26620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    s[1] = (x >> 16) & 0xff;
26720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    s[2] = (x >> 8) & 0xff;
26820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    s[3] = x & 0xff;
26920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    s[4] = '\0';
27020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
27120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
27320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t hdr[2];
27434769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
27520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_IO;
27620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
27720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint64_t chunk_size = ntohl(hdr[0]);
27820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t chunk_type = ntohl(hdr[1]);
27920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t data_offset = *offset + 8;
28020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (chunk_size == 1) {
28234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
28320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_IO;
28420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        chunk_size = ntoh64(chunk_size);
28620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        data_offset += 8;
28720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
28820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    char chunk[5];
29020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MakeFourCCString(chunk_type, chunk);
29120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#if 0
29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static const char kWhitespace[] = "                                        ";
29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth];
29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    printf("%sfound chunk '%s' of size %lld\n", indent, chunk, chunk_size);
29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    char buffer[256];
29820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (chunk_size <= sizeof(buffer)) {
29934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber        if (mDataSource->readAt(*offset, buffer, chunk_size) < chunk_size) {
30020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_IO;
30120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
30220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        hexdump(buffer, chunk_size);
30420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
30520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#endif
30620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t chunk_data_size = *offset + chunk_size - data_offset;
30820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    switch(chunk_type) {
31020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'v'):
31120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'k'):
31220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'i', 'a'):
31320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'i', 'n', 'f'):
31420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('d', 'i', 'n', 'f'):
31520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'b', 'l'):
31620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'v', 'e', 'x'):
31720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'f'):
31820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'f'):
31920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'f', 'r', 'a'):
32020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'k', 'i' ,'p'):
32120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
32220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            off_t stop_offset = *offset + chunk_size;
32320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset;
32420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
32520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
32620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
32720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
32820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
32920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
330dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK_EQ(*offset, stop_offset);
33120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
33320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mHaveMetadata = true;
33420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return UNKNOWN_ERROR;  // Return a dummy error.
33620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
33720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
33820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
33920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
34020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'k', 'h', 'd'):
34120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
342dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK(chunk_data_size >= 4);
34320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
34420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t version;
34534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(data_offset, &version, 1) < 1) {
34620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
34720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
34820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
34920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint64_t ctime, mtime, duration;
35020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int32_t id;
35120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t width, height;
35220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
35420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (chunk_data_size != 36 + 60) {
35520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_MALFORMED;
35620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                uint8_t buffer[36 + 60];
35934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
36020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
36120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
36220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
36320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                ctime = U64_AT(&buffer[4]);
36520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mtime = U64_AT(&buffer[12]);
36620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                id = U32_AT(&buffer[20]);
36720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                duration = U64_AT(&buffer[28]);
36820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                width = U32_AT(&buffer[88]);
36920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                height = U32_AT(&buffer[92]);
37020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else if (version == 0) {
37120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (chunk_data_size != 24 + 60) {
37220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_MALFORMED;
37320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
37420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                uint8_t buffer[24 + 60];
37634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
37720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
37820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
37920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
38020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                ctime = U32_AT(&buffer[4]);
38120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mtime = U32_AT(&buffer[8]);
38220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                id = U32_AT(&buffer[12]);
38320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                duration = U32_AT(&buffer[20]);
38420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                width = U32_AT(&buffer[76]);
38520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                height = U32_AT(&buffer[80]);
38620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
38720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
38820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            Track *track = new Track;
38920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            track->next = NULL;
39020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (mLastTrack) {
39120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->next = track;
39220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
39320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mFirstTrack = track;
39420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
39520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack = track;
39620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
39720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            track->meta = new MetaData;
3987e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            track->includes_expensive_metadata = false;
39920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            track->timescale = 0;
40020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            track->sampleTable = new SampleTable(mDataSource);
40120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            track->meta->setCString(kKeyMIMEType, "application/octet-stream");
40220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
40320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
40420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
40520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
40620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
40720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'h', 'd'):
40820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
40920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
41020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
41120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
41220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
41320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t version;
41434769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
41520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, &version, sizeof(version))
41620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(version)) {
41720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
41820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
41920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
42020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            off_t timescale_offset;
42120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
42220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
42320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 16;
42420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else if (version == 0) {
42520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 8;
42620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
42720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
42820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
42920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t timescale;
43134769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
43220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        timescale_offset, &timescale, sizeof(timescale))
43320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(timescale)) {
43420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
43520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
43620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->timescale = ntohl(timescale);
43820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int64_t duration;
44020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
44134769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
44220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration, sizeof(duration))
44320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration)) {
44420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
44520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
44620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                duration = ntoh64(duration);
44720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
44820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                int32_t duration32;
44934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
45020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration32, sizeof(duration32))
45120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration32)) {
45220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
45320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
45420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                duration = ntohl(duration32);
45520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
45648c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            mLastTrack->meta->setInt64(
45748c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                    kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
45820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
45920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
46020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
46120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
46220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
46320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('h', 'd', 'l', 'r'):
46420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
46520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 25) {
46620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
46720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
46820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
46920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[24];
47034769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(data_offset, buffer, 24) < 24) {
47120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
47220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
47320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
47420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
47520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
47620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
47720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
47820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
47920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(&buffer[4]) != 0) {
48020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // pre_defined should be 0.
48120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
48220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
48320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
48420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mHandlerType = U32_AT(&buffer[8]);
48520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
48620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
48720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
48820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
48920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'd'):
49020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
49120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 8) {
49220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
49320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
49420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
49520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8];
496dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK(chunk_data_size >= (off_t)sizeof(buffer));
49734769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
49820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, 8) < 8) {
49920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
50020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
50120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
50220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
50320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
50420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
50520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
50620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
50720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t entry_count = U32_AT(&buffer[4]);
50820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
50920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (entry_count > 1) {
51020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // For now we only support a single type of media per track.
51120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_UNSUPPORTED;
51220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
51320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
51420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            off_t stop_offset = *offset + chunk_size;
51520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + 8;
51620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            for (uint32_t i = 0; i < entry_count; ++i) {
51720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
51820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
51920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
52020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
52120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
522dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK_EQ(*offset, stop_offset);
52320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
52420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
52520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
52620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
52720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
528371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
52920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
53020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (mHandlerType != FOURCC('s', 'o', 'u', 'n')) {
53120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
53220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
53320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
53420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8 + 20];
53520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
53620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic AudioSampleEntry size.
53720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
53820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
53920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
54034769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
54120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
54220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
54320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
54420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
54520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
54620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t num_channels = U16_AT(&buffer[16]);
54720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
54818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB,
54918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                            FourCC2MIME(chunk_type))
55018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                || !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB,
55118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                               FourCC2MIME(chunk_type))) {
55220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // AMR audio is always mono.
55320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                num_channels = 1;
55420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
55520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
55620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t sample_size = U16_AT(&buffer[18]);
55720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
55820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
559134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            // printf("*** coding='%s' %d channels, size %d, rate %d\n",
560134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            //        chunk, num_channels, sample_size, sample_rate);
56120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
56220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
56320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
56420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
56520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
56620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            off_t stop_offset = *offset + chunk_size;
56720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
56820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
56920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
57020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
57120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
57220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
57320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
574dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK_EQ(*offset, stop_offset);
57520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
57620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
57720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
57820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
57920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
58020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
58120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
5827be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber            mHasVideo = true;
5837be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
58420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (mHandlerType != FOURCC('v', 'i', 'd', 'e')) {
58520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
58620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
58720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
58820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[78];
58920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
59020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic VideoSampleEntry size.
59120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
59220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
59320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
59434769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
59520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
59620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
59720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
59820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
59920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
60020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t width = U16_AT(&buffer[6 + 18]);
60120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t height = U16_AT(&buffer[6 + 20]);
60220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
603134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            // printf("*** coding='%s' width=%d height=%d\n",
604134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            //        chunk, width, height);
60520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
60620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
60720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyWidth, width);
60820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyHeight, height);
60920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
61020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            off_t stop_offset = *offset + chunk_size;
61120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
61220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
61320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
61420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
61520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
61620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
61720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
618dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK_EQ(*offset, stop_offset);
61920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
62020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
62120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
62220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'c', 'o'):
62320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('c', 'o', '6', '4'):
62420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
62520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
62620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setChunkOffsetParams(
62720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
62820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
62920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
63020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
63120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
63220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
63420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
63520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
63620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'c'):
63820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
63920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
64020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleToChunkParams(
64120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
64220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
64420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
64520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
64620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
64820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
64920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
65020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
65120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'z'):
65220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'z', '2'):
65320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
65420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
65520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleSizeParams(
65620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
65720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
65820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
65920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
66020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
66120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
662738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            size_t max_size;
663738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            CHECK_EQ(mLastTrack->sampleTable->getMaxSampleSize(&max_size), OK);
664738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber
665738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            // Assume that a given buffer only contains at most 10 fragments,
666738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            // each fragment originally prefixed with a 2 byte length will
667738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
668738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            // and thus will grow by 2 bytes per fragment.
669738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
670738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber
67120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
67220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
67320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
67420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
67520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 't', 's'):
67620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
67720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
67820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setTimeToSampleParams(
67920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
68020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
68120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
68220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
68320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
68420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
68520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
68620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
68720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
68820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
68920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 's'):
69020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
69120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
69220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSyncSampleParams(
69320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
69420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
69520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
69620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
69720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
69820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
69920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
70020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
70120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
70220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
70320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('e', 's', 'd', 's'):
70420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
70520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
70620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
70720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
70820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
70920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[256];
71020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size > (off_t)sizeof(buffer)) {
71120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
71220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
71320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
71434769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
71520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
71620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
71720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
71820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
71920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
72020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
72120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
72220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
72320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
72420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
72520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
72620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
72720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
72820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
72920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
73020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
73120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', 'C'):
73220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
73320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            char buffer[256];
73420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size > (off_t)sizeof(buffer)) {
73520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
73620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
73720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
73834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
73920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
74020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
74120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
74220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
74320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
74420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    kKeyAVCC, kTypeAVCC, buffer, chunk_data_size);
74520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
74620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
74720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
74820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
74920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
75020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
75120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
75220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
75320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
75420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
75520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
75620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
75720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
75820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
75920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
760693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
76120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
76220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
763693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return NULL;
76420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
76520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
76720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
76820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
769693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber            return NULL;
77020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
77120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
77320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
77420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
77520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
776371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
777371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
778371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
779371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
780693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    return new MPEG4Source(
78148c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            track->meta, mDataSource, track->timescale, track->sampleTable);
78220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
78320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
78420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
78520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
78620111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::MPEG4Source(
78720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        const sp<MetaData> &format,
788693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &dataSource,
78948c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        int32_t timeScale,
790693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<SampleTable> &sampleTable)
79120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mFormat(format),
79220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDataSource(dataSource),
79348c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber      mTimescale(timeScale),
79420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSampleTable(sampleTable),
79520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCurrentSampleIndex(0),
79620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mIsAVC(false),
7976064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber      mNALLengthSize(0),
79820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mStarted(false),
79920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mGroup(NULL),
80020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mBuffer(NULL),
801dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber      mWantsNALFragments(false),
8020024245e134467d120b40099da16c467dc365e76Andreas Huber      mSrcBuffer(NULL) {
80320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
80420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mFormat->findCString(kKeyMIMEType, &mime);
805dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(success);
80620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
80718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber    mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
8086064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
8096064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    if (mIsAVC) {
8106064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        uint32_t type;
8116064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const void *data;
8126064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t size;
8136064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(format->findData(kKeyAVCC, &type, &data, &size));
8146064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
8156064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const uint8_t *ptr = (const uint8_t *)data;
8166064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
8176064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(size >= 7);
8186064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK_EQ(ptr[0], 1);  // configurationVersion == 1
8196064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
8206064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        // The number of bytes used to encode the length of a NAL unit.
8216064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        mNALLengthSize = 1 + (ptr[4] & 3);
8226064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
82320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
82420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
82520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::~MPEG4Source() {
82620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mStarted) {
82720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        stop();
82820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
82920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
83020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
83120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::start(MetaData *params) {
832dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(!mStarted);
83320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
83420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t val;
835dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (params && params->findInt32(kKeyWantsNALFragments, &val)
83620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        && val != 0) {
837dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = true;
83820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    } else {
839dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = false;
84020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
84120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
84220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = new MediaBufferGroup;
84320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
844738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    int32_t max_size;
845738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size));
84620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
847738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    mGroup->add_buffer(new MediaBuffer(max_size));
8480024245e134467d120b40099da16c467dc365e76Andreas Huber
8490024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = new uint8_t[max_size];
85020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
85120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = true;
85220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
85320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
85420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
85520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
85620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::stop() {
857dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
85820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
85920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mBuffer != NULL) {
86020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->release();
86120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
86220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
86320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8640024245e134467d120b40099da16c467dc365e76Andreas Huber    delete[] mSrcBuffer;
8650024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = NULL;
8660024245e134467d120b40099da16c467dc365e76Andreas Huber
86720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    delete mGroup;
86820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = NULL;
86920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
87020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = false;
87120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mCurrentSampleIndex = 0;
87220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
87320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
87420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
87520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
87620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> MPEG4Source::getFormat() {
87720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return mFormat;
87820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
87920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8806064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Hubersize_t MPEG4Source::parseNALSize(const uint8_t *data) const {
8816064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    switch (mNALLengthSize) {
8826064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 1:
8836064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return *data;
8846064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 2:
8856064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U16_AT(data);
8866064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 3:
8876064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return ((size_t)data[0] << 16) | U16_AT(&data[1]);
8886064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 4:
8896064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U32_AT(data);
8906064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
8916064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
8926064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // This cannot happen, mNALLengthSize springs to life by adding 1 to
8936064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // a 2-bit integer.
8946064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    CHECK(!"Should not be here.");
8956064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
8966064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    return 0;
8976064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber}
8986064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
89920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::read(
90020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        MediaBuffer **out, const ReadOptions *options) {
901dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
90220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
90320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *out = NULL;
90420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
90520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t seekTimeUs;
90620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (options && options->getSeekTo(&seekTimeUs)) {
90720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        uint32_t sampleIndex;
90820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        status_t err = mSampleTable->findClosestSample(
90920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                seekTimeUs * mTimescale / 1000000,
91020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                &sampleIndex, SampleTable::kSyncSample_Flag);
91120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
91220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (err != OK) {
91320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return err;
91420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
91520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
91620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCurrentSampleIndex = sampleIndex;
91720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mBuffer != NULL) {
91820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
91920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
92020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
92120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
92220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // fall through
92320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
92420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9250024245e134467d120b40099da16c467dc365e76Andreas Huber    off_t offset;
9260024245e134467d120b40099da16c467dc365e76Andreas Huber    size_t size;
927dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    uint32_t dts;
928dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool newBuffer = false;
929dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (mBuffer == NULL) {
930dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        newBuffer = true;
93120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
932dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        status_t err = mSampleTable->getSampleOffsetAndSize(
933dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mCurrentSampleIndex, &offset, &size);
93420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
935dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
936dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
937dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
93820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
939dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        err = mSampleTable->getDecodingTime(mCurrentSampleIndex, &dts);
94020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
941dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
942dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
943dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
944dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
945dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        err = mGroup->acquire_buffer(&mBuffer);
946dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
947dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK_EQ(mBuffer, NULL);
948dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
949dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
9500024245e134467d120b40099da16c467dc365e76Andreas Huber    }
95120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
952dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (!mIsAVC || mWantsNALFragments) {
953dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (newBuffer) {
954dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ssize_t num_bytes_read =
95534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
956dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
957dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            if (num_bytes_read < (ssize_t)size) {
958dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer->release();
959dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer = NULL;
960dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
961dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                return ERROR_IO;
962dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            }
963dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
964dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->set_range(0, size);
965dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->meta_data()->clear();
96648c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            mBuffer->meta_data()->setInt64(
96748c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                    kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
968dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ++mCurrentSampleIndex;
969dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
970dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
971dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (!mIsAVC) {
972dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            *out = mBuffer;
973dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
974dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
975dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return OK;
976dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
977dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
978dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Each NAL unit is split up into its constituent fragments and
979dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // each one of them returned in its own buffer.
980dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
9816064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(mBuffer->range_length() >= mNALLengthSize);
982dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
983dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        const uint8_t *src =
984dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
985dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
9866064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t nal_size = parseNALSize(src);
987e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
988e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            LOGE("incomplete NAL unit.");
989e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
990e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer->release();
991e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer = NULL;
992e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
993e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            return ERROR_MALFORMED;
994e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        }
995dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
996dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        MediaBuffer *clone = mBuffer->clone();
9976064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
998dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
999dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mBuffer->set_range(
10006064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_offset() + mNALLengthSize + nal_size,
10016064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_length() - mNALLengthSize - nal_size);
1002dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1003dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (mBuffer->range_length() == 0) {
1004dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->release();
1005dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
1006dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
1007dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1008dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        *out = clone;
1009dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1010dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        return OK;
1011dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    } else {
1012dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Whole NAL units are returned but each fragment is prefixed by
1013dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // the start code (0x00 00 00 01).
1014dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
101520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        ssize_t num_bytes_read =
101634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            mDataSource->readAt(offset, mSrcBuffer, size);
101720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
101820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (num_bytes_read < (ssize_t)size) {
101920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
102020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
102120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1022dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return ERROR_IO;
102320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
102420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1025dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        uint8_t *dstData = (uint8_t *)mBuffer->data();
1026dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        size_t srcOffset = 0;
1027dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        size_t dstOffset = 0;
10286064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
1029dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        while (srcOffset < size) {
10306064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            CHECK(srcOffset + mNALLengthSize <= size);
10316064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            size_t nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
10326064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            srcOffset += mNALLengthSize;
1033e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
1034e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            if (srcOffset + nalLength > size) {
1035e8a084958c27327b0aca749f69095605d2a21309Andreas Huber                mBuffer->release();
1036e8a084958c27327b0aca749f69095605d2a21309Andreas Huber                mBuffer = NULL;
1037e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
1038e8a084958c27327b0aca749f69095605d2a21309Andreas Huber                return ERROR_MALFORMED;
1039e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            }
1040dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1041dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            if (nalLength == 0) {
1042dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                continue;
1043dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            }
1044dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1045dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK(dstOffset + 4 <= mBuffer->size());
1046dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1047dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            dstData[dstOffset++] = 0;
1048dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            dstData[dstOffset++] = 0;
1049dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            dstData[dstOffset++] = 0;
1050dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            dstData[dstOffset++] = 1;
1051dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
1052dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            srcOffset += nalLength;
1053dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            dstOffset += nalLength;
1054dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
10556064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK_EQ(srcOffset, size);
1056dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1057dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mBuffer->set_range(0, dstOffset);
105820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->meta_data()->clear();
105948c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        mBuffer->meta_data()->setInt64(
106048c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
106120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        ++mCurrentSampleIndex;
106220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
106320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        *out = mBuffer;
106420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
106520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
106620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return OK;
106720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
106820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
106920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1070693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huberbool SniffMPEG4(
1071693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
107220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint8_t header[8];
107320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
107434769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    ssize_t n = source->readAt(4, header, sizeof(header));
107520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (n < (ssize_t)sizeof(header)) {
107620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return false;
107720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
107820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
107920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
10800dba73763a04d39faf999dcc5ef12af3c99535a7Andreas Huber        || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
10810dba73763a04d39faf999dcc5ef12af3c99535a7Andreas Huber        || !memcmp(header, "ftypM4A ", 8)) {
108218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
108320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        *confidence = 0.1;
108420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
108520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return true;
108620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
108720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
108820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return false;
108920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
109020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
109120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
109220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1093