1840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber/*
2840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber * Copyright (C) 2012 The Android Open Source Project
3840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber *
4840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber * you may not use this file except in compliance with the License.
6840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber * You may obtain a copy of the License at
7840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber *
8840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber *
10840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber * Unless required by applicable law or agreed to in writing, software
11840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber * See the License for the specific language governing permissions and
14840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber * limitations under the License.
15840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber */
16840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
17840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber//#define LOG_NDEBUG 0
18cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissen#define LOG_TAG "FragmentedMP4Parser"
19840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber#include <utils/Log.h>
20840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
218c95fa91fff6e8726df03598d52243f22e5ff8e7Marco Nelissen#include "include/avc_utils.h"
22cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissen#include "include/ESDS.h"
2356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen#include "include/FragmentedMP4Parser.h"
24840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber#include "TrackFragment.h"
25840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
26840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
27840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
28840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber#include <media/stagefright/foundation/ADebug.h>
29840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber#include <media/stagefright/foundation/AMessage.h>
30840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber#include <media/stagefright/foundation/hexdump.h>
31840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber#include <media/stagefright/MediaDefs.h>
32840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber#include <media/stagefright/MediaErrors.h>
33840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber#include <media/stagefright/Utils.h>
34840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
3556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
36840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Hubernamespace android {
37840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
38840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huberstatic const char *Fourcc2String(uint32_t fourcc) {
39840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    static char buffer[5];
40840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    buffer[4] = '\0';
41840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    buffer[0] = fourcc >> 24;
42840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    buffer[1] = (fourcc >> 16) & 0xff;
43840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    buffer[2] = (fourcc >> 8) & 0xff;
44840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    buffer[3] = fourcc & 0xff;
45840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
46840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return buffer;
47840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
48840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
49840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huberstatic const char *IndentString(size_t n) {
50840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    static const char kSpace[] = "                              ";
51840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return kSpace + sizeof(kSpace) - 2 * n - 1;
52840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
53840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
54840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber// static
55cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenconst FragmentedMP4Parser::DispatchEntry FragmentedMP4Parser::kDispatchTable[] = {
56840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('m', 'o', 'o', 'v'), 0, NULL },
57840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('t', 'r', 'a', 'k'), FOURCC('m', 'o', 'o', 'v'), NULL },
58840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('u', 'd', 't', 'a'), FOURCC('t', 'r', 'a', 'k'), NULL },
59840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('u', 'd', 't', 'a'), FOURCC('m', 'o', 'o', 'v'), NULL },
60840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('m', 'e', 't', 'a'), FOURCC('u', 'd', 't', 'a'), NULL },
61840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('i', 'l', 's', 't'), FOURCC('m', 'e', 't', 'a'), NULL },
62840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
63840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('t', 'k', 'h', 'd'), FOURCC('t', 'r', 'a', 'k'),
64cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissen        &FragmentedMP4Parser::parseTrackHeader
65840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    },
66840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
67840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('m', 'v', 'e', 'x'), FOURCC('m', 'o', 'o', 'v'), NULL },
68840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
69840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('t', 'r', 'e', 'x'), FOURCC('m', 'v', 'e', 'x'),
70cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissen        &FragmentedMP4Parser::parseTrackExtends
71840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    },
72840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
73840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('e', 'd', 't', 's'), FOURCC('t', 'r', 'a', 'k'), NULL },
74840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('m', 'd', 'i', 'a'), FOURCC('t', 'r', 'a', 'k'), NULL },
75840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
76840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('m', 'd', 'h', 'd'), FOURCC('m', 'd', 'i', 'a'),
77cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissen        &FragmentedMP4Parser::parseMediaHeader
78840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    },
79840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
80840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('h', 'd', 'l', 'r'), FOURCC('m', 'd', 'i', 'a'),
81cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissen        &FragmentedMP4Parser::parseMediaHandler
82840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    },
83840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
84840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('m', 'i', 'n', 'f'), FOURCC('m', 'd', 'i', 'a'), NULL },
85840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('d', 'i', 'n', 'f'), FOURCC('m', 'i', 'n', 'f'), NULL },
86840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('s', 't', 'b', 'l'), FOURCC('m', 'i', 'n', 'f'), NULL },
87840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('s', 't', 's', 'd'), FOURCC('s', 't', 'b', 'l'), NULL },
88840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
89840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('s', 't', 's', 'z'), FOURCC('s', 't', 'b', 'l'),
90cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissen        &FragmentedMP4Parser::parseSampleSizes },
91840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
92840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('s', 't', 'z', '2'), FOURCC('s', 't', 'b', 'l'),
93cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissen        &FragmentedMP4Parser::parseCompactSampleSizes },
94840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
95840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('s', 't', 's', 'c'), FOURCC('s', 't', 'b', 'l'),
96cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissen        &FragmentedMP4Parser::parseSampleToChunk },
97840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
98840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('s', 't', 'c', 'o'), FOURCC('s', 't', 'b', 'l'),
99cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissen        &FragmentedMP4Parser::parseChunkOffsets },
100840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
101840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('c', 'o', '6', '4'), FOURCC('s', 't', 'b', 'l'),
102cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissen        &FragmentedMP4Parser::parseChunkOffsets64 },
103840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
104840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('a', 'v', 'c', 'C'), FOURCC('a', 'v', 'c', '1'),
105cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissen        &FragmentedMP4Parser::parseAVCCodecSpecificData },
106840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
107840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('e', 's', 'd', 's'), FOURCC('m', 'p', '4', 'a'),
108cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissen        &FragmentedMP4Parser::parseESDSCodecSpecificData },
109840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
110840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('e', 's', 'd', 's'), FOURCC('m', 'p', '4', 'v'),
111cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissen        &FragmentedMP4Parser::parseESDSCodecSpecificData },
112840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
113cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissen    { FOURCC('m', 'd', 'a', 't'), 0, &FragmentedMP4Parser::parseMediaData },
114840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
115840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('m', 'o', 'o', 'f'), 0, NULL },
116840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('t', 'r', 'a', 'f'), FOURCC('m', 'o', 'o', 'f'), NULL },
117840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
118840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('t', 'f', 'h', 'd'), FOURCC('t', 'r', 'a', 'f'),
119cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissen        &FragmentedMP4Parser::parseTrackFragmentHeader
120840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    },
121840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('t', 'r', 'u', 'n'), FOURCC('t', 'r', 'a', 'f'),
122cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissen        &FragmentedMP4Parser::parseTrackFragmentRun
123840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    },
124840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
125840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    { FOURCC('m', 'f', 'r', 'a'), 0, NULL },
12656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
12756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    { FOURCC('s', 'i', 'd', 'x'), 0, &FragmentedMP4Parser::parseSegmentIndex },
128840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber};
129840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
130cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenstruct FileSource : public FragmentedMP4Parser::Source {
131840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    FileSource(const char *filename)
132840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        : mFile(fopen(filename, "rb")) {
133840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            CHECK(mFile != NULL);
134840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
135840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
136442d83cfb731bc0a8d1bb2d41ecd242ec498893fYou Kim    virtual ~FileSource() {
137442d83cfb731bc0a8d1bb2d41ecd242ec498893fYou Kim        fclose(mFile);
138442d83cfb731bc0a8d1bb2d41ecd242ec498893fYou Kim    }
139442d83cfb731bc0a8d1bb2d41ecd242ec498893fYou Kim
140840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    virtual ssize_t readAt(off64_t offset, void *data, size_t size) {
141840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        fseek(mFile, offset, SEEK_SET);
142840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return fread(data, 1, size, mFile);
143840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
144840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
14556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    virtual bool isSeekable() {
14656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        return true;
14756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
14856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
149840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    private:
150840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    FILE *mFile;
151840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
152840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(FileSource);
153840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber};
154840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
15556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenstruct ReadTracker : public RefBase {
15656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    ReadTracker(off64_t size) {
15756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        allocSize = 1 + size / 8192; // 1 bit per kilobyte
15856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        bitmap = (char*) calloc(1, allocSize);
15956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
16056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    virtual ~ReadTracker() {
16156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        dumpToLog();
16256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        free(bitmap);
16356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
16456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    void mark(off64_t offset, size_t size) {
16556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        int firstbit = offset / 1024;
16656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        int lastbit = (offset + size - 1) / 1024;
16756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        for (int i = firstbit; i <= lastbit; i++) {
16856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            bitmap[i/8] |= (0x80 >> (i & 7));
16956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        }
17056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
17156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
17256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen private:
17356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    void dumpToLog() {
17456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        // 96 chars per line, each char represents one kilobyte, 1 kb per bit
17556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        int numlines = allocSize / 12;
17656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        char buf[97];
17756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        char *cur = bitmap;
17856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        for (int i = 0; i < numlines; i++ && cur) {
17956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            for (int j = 0; j < 12; j++) {
18056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                for (int k = 0; k < 8; k++) {
18156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                    buf[(j * 8) + k] = (*cur & (0x80 >> k)) ? 'X' : '.';
18256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                }
18356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                cur++;
18456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            }
18556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            buf[96] = '\0';
18656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            ALOGI("%5dk: %s", i * 96, buf);
18756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        }
18856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
18956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
19056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    size_t allocSize;
19156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    char *bitmap;
19256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen};
19356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
19456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenstruct DataSourceSource : public FragmentedMP4Parser::Source {
19556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    DataSourceSource(sp<DataSource> &source)
19656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        : mDataSource(source) {
19756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            CHECK(mDataSource != NULL);
19856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen#if 0
19956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            off64_t size;
20056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            if (source->getSize(&size) == OK) {
20156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                mReadTracker = new ReadTracker(size);
20256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            } else {
20356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                ALOGE("couldn't get data source size");
20456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            }
20556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen#endif
20656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        }
20756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
20856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    virtual ssize_t readAt(off64_t offset, void *data, size_t size) {
20956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        if (mReadTracker != NULL) {
21056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            mReadTracker->mark(offset, size);
21156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        }
21256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        return mDataSource->readAt(offset, data, size);
21356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
21456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
21556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    virtual bool isSeekable() {
21656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        return true;
21756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
21856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
21956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    private:
22056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    sp<DataSource> mDataSource;
22156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    sp<ReadTracker> mReadTracker;
22256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
22356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    DISALLOW_EVIL_CONSTRUCTORS(DataSourceSource);
22456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen};
22556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
226cb1f88c684140ce0eb407049a78f889bc7d51be1Marco NelissenFragmentedMP4Parser::FragmentedMP4Parser()
227840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    : mBufferPos(0),
228c7708555ea7511aea684e00a55fb5309281540ceAndreas Huber      mSuspended(false),
22956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen      mDoneWithMoov(false),
23056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen      mFirstMoofOffset(0),
231c7708555ea7511aea684e00a55fb5309281540ceAndreas Huber      mFinalResult(OK) {
232840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
233840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
234cb1f88c684140ce0eb407049a78f889bc7d51be1Marco NelissenFragmentedMP4Parser::~FragmentedMP4Parser() {
235840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
236840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
237cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenvoid FragmentedMP4Parser::start(const char *filename) {
238840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    sp<AMessage> msg = new AMessage(kWhatStart, id());
239840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    msg->setObject("source", new FileSource(filename));
240840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    msg->post();
24156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    ALOGV("Parser::start(%s)", filename);
242840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
243840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
244cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenvoid FragmentedMP4Parser::start(const sp<Source> &source) {
245840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    sp<AMessage> msg = new AMessage(kWhatStart, id());
246840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    msg->setObject("source", source);
247840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    msg->post();
24856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    ALOGV("Parser::start(Source)");
24956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen}
25056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
25156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenvoid FragmentedMP4Parser::start(sp<DataSource> &source) {
25256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    sp<AMessage> msg = new AMessage(kWhatStart, id());
25356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    msg->setObject("source", new DataSourceSource(source));
25456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    msg->post();
25556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    ALOGV("Parser::start(DataSource)");
256840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
257840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
25856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissensp<AMessage> FragmentedMP4Parser::getFormat(bool audio, bool synchronous) {
259840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
26056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    while (true) {
26156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        bool moovDone = mDoneWithMoov;
26256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        sp<AMessage> msg = new AMessage(kWhatGetFormat, id());
26356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        msg->setInt32("audio", audio);
264840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
26556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        sp<AMessage> response;
26656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        status_t err = msg->postAndAwaitResponse(&response);
267840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
26856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        if (err != OK) {
26956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            ALOGV("getFormat post failed: %d", err);
27056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            return NULL;
27156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        }
27256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
27356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        if (response->findInt32("err", &err) && err != OK) {
27456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            if (synchronous && err == -EWOULDBLOCK && !moovDone) {
27556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                resumeIfNecessary();
27656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                ALOGV("@getFormat parser not ready yet, retrying");
27756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                usleep(10000);
27856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                continue;
27956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            }
28056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            ALOGV("getFormat failed: %d", err);
28156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            return NULL;
28256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        }
283840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
28456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        sp<AMessage> format;
28556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        CHECK(response->findMessage("format", &format));
286840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
28756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        ALOGV("returning format %s", format->debugString().c_str());
28856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        return format;
28956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
290840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
291840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
29256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenstatus_t FragmentedMP4Parser::seekTo(bool wantAudio, int64_t timeUs) {
29356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    sp<AMessage> msg = new AMessage(kWhatSeekTo, id());
29456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    msg->setInt32("audio", wantAudio);
29556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    msg->setInt64("position", timeUs);
296840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
297840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    sp<AMessage> response;
298840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    status_t err = msg->postAndAwaitResponse(&response);
29956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    return err;
30056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen}
301840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
30256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenbool FragmentedMP4Parser::isSeekable() const {
30356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    while (mFirstMoofOffset == 0 && mFinalResult == OK) {
30456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        usleep(10000);
30556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
30656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    bool seekable = mSource->isSeekable();
30756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    for (size_t i = 0; seekable && i < mTracks.size(); i++) {
30856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        const TrackInfo *info = &mTracks.valueAt(i);
30956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        seekable &= !info->mSidx.empty();
310840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
31156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    return seekable;
31256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen}
313840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
31456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenstatus_t FragmentedMP4Parser::onSeekTo(bool wantAudio, int64_t position) {
31556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    status_t err = -EINVAL;
31656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    ssize_t trackIndex = findTrack(wantAudio);
31756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    if (trackIndex < 0) {
31856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        err = trackIndex;
31956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    } else {
32056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        TrackInfo *info = &mTracks.editValueAt(trackIndex);
32156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
32256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        int numSidxEntries = info->mSidx.size();
32356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        int64_t totalTime = 0;
32456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        off_t totalOffset = mFirstMoofOffset;
32556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        for (int i = 0; i < numSidxEntries; i++) {
32656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            const SidxEntry *se = &info->mSidx[i];
32786355f5b1ef6c6434d8717c71428e3165b0fe7b5Marco Nelissen            if (totalTime + se->mDurationUs > position) {
32856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                mBuffer->setRange(0,0);
32956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                mBufferPos = totalOffset;
33056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                if (mFinalResult == ERROR_END_OF_STREAM) {
33156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                    mFinalResult = OK;
33256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                    mSuspended = true; // force resume
33356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                    resumeIfNecessary();
33456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                }
33556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                info->mFragments.clear();
33686355f5b1ef6c6434d8717c71428e3165b0fe7b5Marco Nelissen                info->mDecodingTime = totalTime * info->mMediaTimeScale / 1000000ll;
33756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                return OK;
33856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            }
33986355f5b1ef6c6434d8717c71428e3165b0fe7b5Marco Nelissen            totalTime += se->mDurationUs;
34056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            totalOffset += se->mSize;
34156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        }
342840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
34356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    ALOGV("seekTo out of range");
34456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    return err;
34556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen}
346840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
34756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenstatus_t FragmentedMP4Parser::dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit,
34856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                                                bool synchronous) {
349840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
35056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    while (true) {
35156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        sp<AMessage> msg = new AMessage(kWhatDequeueAccessUnit, id());
35256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        msg->setInt32("audio", audio);
35356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
35456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        sp<AMessage> response;
35556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        status_t err = msg->postAndAwaitResponse(&response);
35656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
35756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        if (err != OK) {
35856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            ALOGV("dequeue fail 1: %d", err);
35956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            return err;
36056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        }
36156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
36256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        if (response->findInt32("err", &err) && err != OK) {
36356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            if (synchronous && err == -EWOULDBLOCK) {
36456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                resumeIfNecessary();
36556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                ALOGV("Parser not ready yet, retrying");
36656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                usleep(10000);
36756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                continue;
36856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            }
36956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            ALOGV("dequeue fail 2: %d, %d", err, synchronous);
37056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            return err;
37156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        }
37256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
37356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        CHECK(response->findBuffer("accessUnit", accessUnit));
37456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
37556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        return OK;
37656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
377840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
378840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
379cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenssize_t FragmentedMP4Parser::findTrack(bool wantAudio) const {
380840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    for (size_t i = 0; i < mTracks.size(); ++i) {
381840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        const TrackInfo *info = &mTracks.valueAt(i);
382840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
383840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        bool isAudio =
384840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            info->mMediaHandlerType == FOURCC('s', 'o', 'u', 'n');
385840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
386840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        bool isVideo =
387840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            info->mMediaHandlerType == FOURCC('v', 'i', 'd', 'e');
388840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
389840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if ((wantAudio && isAudio) || (!wantAudio && !isAudio)) {
390840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            if (info->mSampleDescs.empty()) {
391840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                break;
392840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
393840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
394840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return i;
395840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
396840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
397840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
398840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return -EWOULDBLOCK;
399840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
400840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
401cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenvoid FragmentedMP4Parser::onMessageReceived(const sp<AMessage> &msg) {
402840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    switch (msg->what()) {
403840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        case kWhatStart:
404840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        {
405840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            sp<RefBase> obj;
406840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            CHECK(msg->findObject("source", &obj));
407840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
408840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            mSource = static_cast<Source *>(obj.get());
409840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
410840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            mBuffer = new ABuffer(512 * 1024);
411840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            mBuffer->setRange(0, 0);
412840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
413bd828233d3eda966bf7145108dde74616abd97fbAndreas Huber            enter(0ll, 0, 0);
414840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
415840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            (new AMessage(kWhatProceed, id()))->post();
416840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            break;
417840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
418840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
419840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        case kWhatProceed:
420840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        {
421840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            CHECK(!mSuspended);
422840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
423840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            status_t err = onProceed();
424840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
425840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            if (err == OK) {
426840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                if (!mSuspended) {
427840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    msg->post();
428840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                }
429840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            } else if (err != -EAGAIN) {
430840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                ALOGE("onProceed returned error %d", err);
431840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
432840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
433840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            break;
434840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
435840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
436840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        case kWhatReadMore:
437840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        {
438840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            size_t needed;
439840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            CHECK(msg->findSize("needed", &needed));
440840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
441840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            memmove(mBuffer->base(), mBuffer->data(), mBuffer->size());
442840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            mBufferPos += mBuffer->offset();
443840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            mBuffer->setRange(0, mBuffer->size());
444840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
445840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            size_t maxBytesToRead = mBuffer->capacity() - mBuffer->size();
446b9787142c5f5f8f47e7e35409f4f2ef7112ab72eAndreas Huber
447b9787142c5f5f8f47e7e35409f4f2ef7112ab72eAndreas Huber            if (maxBytesToRead < needed) {
44856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                ALOGV("resizing buffer.");
449b9787142c5f5f8f47e7e35409f4f2ef7112ab72eAndreas Huber
450b9787142c5f5f8f47e7e35409f4f2ef7112ab72eAndreas Huber                sp<ABuffer> newBuffer =
451b9787142c5f5f8f47e7e35409f4f2ef7112ab72eAndreas Huber                    new ABuffer((mBuffer->size() + needed + 1023) & ~1023);
452b9787142c5f5f8f47e7e35409f4f2ef7112ab72eAndreas Huber                memcpy(newBuffer->data(), mBuffer->data(), mBuffer->size());
453b9787142c5f5f8f47e7e35409f4f2ef7112ab72eAndreas Huber                newBuffer->setRange(0, mBuffer->size());
454b9787142c5f5f8f47e7e35409f4f2ef7112ab72eAndreas Huber
455b9787142c5f5f8f47e7e35409f4f2ef7112ab72eAndreas Huber                mBuffer = newBuffer;
456b9787142c5f5f8f47e7e35409f4f2ef7112ab72eAndreas Huber                maxBytesToRead = mBuffer->capacity() - mBuffer->size();
457b9787142c5f5f8f47e7e35409f4f2ef7112ab72eAndreas Huber            }
458b9787142c5f5f8f47e7e35409f4f2ef7112ab72eAndreas Huber
459840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            CHECK_GE(maxBytesToRead, needed);
460840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
461840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            ssize_t n = mSource->readAt(
462840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    mBufferPos + mBuffer->size(),
463840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    mBuffer->data() + mBuffer->size(), needed);
464840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
465840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            if (n < (ssize_t)needed) {
46656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                ALOGV("Reached EOF when reading %d @ %d + %d", needed, mBufferPos, mBuffer->size());
467c7708555ea7511aea684e00a55fb5309281540ceAndreas Huber                if (n < 0) {
468c7708555ea7511aea684e00a55fb5309281540ceAndreas Huber                    mFinalResult = n;
469c7708555ea7511aea684e00a55fb5309281540ceAndreas Huber                } else if (n == 0) {
470c7708555ea7511aea684e00a55fb5309281540ceAndreas Huber                    mFinalResult = ERROR_END_OF_STREAM;
471c7708555ea7511aea684e00a55fb5309281540ceAndreas Huber                } else {
472c7708555ea7511aea684e00a55fb5309281540ceAndreas Huber                    mFinalResult = ERROR_IO;
473c7708555ea7511aea684e00a55fb5309281540ceAndreas Huber                }
474840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            } else {
475840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                mBuffer->setRange(0, mBuffer->size() + n);
476840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                (new AMessage(kWhatProceed, id()))->post();
477840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
478840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
479840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            break;
480840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
481840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
482840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        case kWhatGetFormat:
483840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        {
484840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            int32_t wantAudio;
485840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            CHECK(msg->findInt32("audio", &wantAudio));
486840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
487840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            status_t err = -EWOULDBLOCK;
488840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            sp<AMessage> response = new AMessage;
489840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
490840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            ssize_t trackIndex = findTrack(wantAudio);
491840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
492840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            if (trackIndex < 0) {
493840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                err = trackIndex;
494840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            } else {
495840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                TrackInfo *info = &mTracks.editValueAt(trackIndex);
496840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
49756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                sp<AMessage> format = info->mSampleDescs.itemAt(0).mFormat;
49856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                if (info->mSidxDuration) {
49956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                    format->setInt64("durationUs", info->mSidxDuration);
50056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                } else {
50156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                    // this is probably going to be zero. Oh well...
50256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                    format->setInt64("durationUs",
50356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                                     1000000ll * info->mDuration / info->mMediaTimeScale);
50456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                }
505840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                response->setMessage(
50656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                        "format", format);
507840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
508840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                err = OK;
509840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
510840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
511840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            response->setInt32("err", err);
512840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
513840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            uint32_t replyID;
514840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            CHECK(msg->senderAwaitsResponse(&replyID));
515840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
516840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            response->postReply(replyID);
517840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            break;
518840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
519840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
520840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        case kWhatDequeueAccessUnit:
521840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        {
522840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            int32_t wantAudio;
523840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            CHECK(msg->findInt32("audio", &wantAudio));
524840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
525840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            status_t err = -EWOULDBLOCK;
526840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            sp<AMessage> response = new AMessage;
527840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
528840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            ssize_t trackIndex = findTrack(wantAudio);
529840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
530840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            if (trackIndex < 0) {
531840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                err = trackIndex;
532840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            } else {
533840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                sp<ABuffer> accessUnit;
534840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                err = onDequeueAccessUnit(trackIndex, &accessUnit);
535840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
536840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                if (err == OK) {
537840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    response->setBuffer("accessUnit", accessUnit);
538840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                }
539840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
540840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
541840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            response->setInt32("err", err);
542840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
543840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            uint32_t replyID;
544840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            CHECK(msg->senderAwaitsResponse(&replyID));
545840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
546840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            response->postReply(replyID);
547840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            break;
548840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
549840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
55056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        case kWhatSeekTo:
55156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        {
55256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            ALOGV("kWhatSeekTo");
55356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            int32_t wantAudio;
55456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            CHECK(msg->findInt32("audio", &wantAudio));
55556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            int64_t position;
55656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            CHECK(msg->findInt64("position", &position));
55756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
55856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            status_t err = -EWOULDBLOCK;
55956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            sp<AMessage> response = new AMessage;
56056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
56156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            ssize_t trackIndex = findTrack(wantAudio);
56256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
56356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            if (trackIndex < 0) {
56456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                err = trackIndex;
56556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            } else {
56656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                err = onSeekTo(wantAudio, position);
56756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            }
56856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            response->setInt32("err", err);
56956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            uint32_t replyID;
57056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            CHECK(msg->senderAwaitsResponse(&replyID));
57156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            response->postReply(replyID);
57256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            break;
57356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        }
574840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        default:
575840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            TRESPASS();
576840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
577840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
578840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
579cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenstatus_t FragmentedMP4Parser::onProceed() {
580840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    status_t err;
581840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
582840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if ((err = need(8)) != OK) {
583840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return err;
584840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
585840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
586840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint64_t size = readU32(0);
587840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint32_t type = readU32(4);
588840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
589840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    size_t offset = 8;
590840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
591840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (size == 1) {
592840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if ((err = need(16)) != OK) {
593840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return err;
594840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
595840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
596840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        size = readU64(offset);
597840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        offset += 8;
598840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
599840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
600840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint8_t userType[16];
601840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
602840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (type == FOURCC('u', 'u', 'i', 'd')) {
603840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if ((err = need(offset + 16)) != OK) {
604840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return err;
605840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
606840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
607840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        memcpy(userType, mBuffer->data() + offset, 16);
608840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        offset += 16;
609840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
610840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
611840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    CHECK(!mStack.isEmpty());
612840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint32_t ptype = mStack.itemAt(mStack.size() - 1).mType;
613840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
614840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    static const size_t kNumDispatchers =
615840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        sizeof(kDispatchTable) / sizeof(kDispatchTable[0]);
616840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
617840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    size_t i;
618840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    for (i = 0; i < kNumDispatchers; ++i) {
619840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (kDispatchTable[i].mType == type
620840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                && kDispatchTable[i].mParentType == ptype) {
621840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            break;
622840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
623840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
624840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
625840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    // SampleEntry boxes are container boxes that start with a variable
626840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    // amount of data depending on the media handler type.
627840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    // We don't look inside 'hint' type SampleEntry boxes.
628840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
629840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    bool isSampleEntryBox =
630840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        (ptype == FOURCC('s', 't', 's', 'd'))
631840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        && editTrack(mCurrentTrackID)->mMediaHandlerType
632840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        != FOURCC('h', 'i', 'n', 't');
633840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
634840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if ((i < kNumDispatchers && kDispatchTable[i].mHandler == 0)
635840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            || isSampleEntryBox || ptype == FOURCC('i', 'l', 's', 't')) {
636840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        // This is a container box.
63756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        if (type == FOURCC('m', 'o', 'o', 'f')) {
63856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            if (mFirstMoofOffset == 0) {
63956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                ALOGV("first moof @ %08x", mBufferPos + offset);
64056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                mFirstMoofOffset = mBufferPos + offset - 8; // point at the size
64156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            }
64256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        }
643840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (type == FOURCC('m', 'e', 't', 'a')) {
644840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            if ((err = need(offset + 4)) < OK) {
645840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                return err;
646840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
647840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
648840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            if (readU32(offset) != 0) {
649840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                return -EINVAL;
650840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
651840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
652840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            offset += 4;
653840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        } else if (type == FOURCC('s', 't', 's', 'd')) {
654840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            if ((err = need(offset + 8)) < OK) {
655840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                return err;
656840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
657840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
658840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            if (readU32(offset) != 0) {
659840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                return -EINVAL;
660840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
661840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
662840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            if (readU32(offset + 4) == 0) {
663840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                // We need at least some entries.
664840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                return -EINVAL;
665840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
666840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
667840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            offset += 8;
668840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        } else if (isSampleEntryBox) {
669840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            size_t headerSize;
670840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
671840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            switch (editTrack(mCurrentTrackID)->mMediaHandlerType) {
672840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                case FOURCC('v', 'i', 'd', 'e'):
673840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                {
674840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    // 8 bytes SampleEntry + 70 bytes VisualSampleEntry
675840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    headerSize = 78;
676840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    break;
677840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                }
678840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
679840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                case FOURCC('s', 'o', 'u', 'n'):
680840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                {
681840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    // 8 bytes SampleEntry + 20 bytes AudioSampleEntry
682840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    headerSize = 28;
683840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    break;
684840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                }
685840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
686840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                case FOURCC('m', 'e', 't', 'a'):
687840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                {
688840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    headerSize = 8;  // 8 bytes SampleEntry
689840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    break;
690840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                }
691840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
692840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                default:
693840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    TRESPASS();
694840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
695840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
696840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            if (offset + headerSize > size) {
697840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                return -EINVAL;
698840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
699840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
700840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            if ((err = need(offset + headerSize)) != OK) {
701840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                return err;
702840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
703840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
704840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            switch (editTrack(mCurrentTrackID)->mMediaHandlerType) {
705840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                case FOURCC('v', 'i', 'd', 'e'):
706840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                {
707840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    err = parseVisualSampleEntry(
708840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                            type, offset, offset + headerSize);
709840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    break;
710840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                }
711840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
712840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                case FOURCC('s', 'o', 'u', 'n'):
713840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                {
714840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    err = parseAudioSampleEntry(
715840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                            type, offset, offset + headerSize);
716840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    break;
717840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                }
718840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
719840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                case FOURCC('m', 'e', 't', 'a'):
720840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                {
721840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    err = OK;
722840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    break;
723840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                }
724840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
725840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                default:
726840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    TRESPASS();
727840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
728840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
729840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            if (err != OK) {
730840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                return err;
731840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
732840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
733840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            offset += headerSize;
734840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
735840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
736840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        skip(offset);
737840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
738840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        ALOGV("%sentering box of type '%s'",
739840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                IndentString(mStack.size()), Fourcc2String(type));
740840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
741bd828233d3eda966bf7145108dde74616abd97fbAndreas Huber        enter(mBufferPos - offset, type, size - offset);
742840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    } else {
743840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (!fitsContainer(size)) {
744840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return -EINVAL;
745840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
746840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
747840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (i < kNumDispatchers && kDispatchTable[i].mHandler != 0) {
748840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            // We have a handler for this box type.
749840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
750840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            if ((err = need(size)) != OK) {
751840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                return err;
752840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
753840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
754840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            ALOGV("%sparsing box of type '%s'",
755840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    IndentString(mStack.size()), Fourcc2String(type));
756840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
757840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            if ((err = (this->*kDispatchTable[i].mHandler)(
758840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                            type, offset, size)) != OK) {
759840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                return err;
760840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
761840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        } else {
762840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            // Unknown box type
763840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
764840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            ALOGV("%sskipping box of type '%s', size %llu",
765840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    IndentString(mStack.size()),
766840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    Fourcc2String(type), size);
767840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
768840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
769840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
770840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        skip(size);
771840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
772840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
773840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return OK;
774840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
775840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
776840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber// static
777cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenint FragmentedMP4Parser::CompareSampleLocation(
778840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        const SampleInfo &sample, const MediaDataInfo &mdatInfo) {
779840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (sample.mOffset + sample.mSize < mdatInfo.mOffset) {
780840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return -1;
781840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
782840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
783840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (sample.mOffset >= mdatInfo.mOffset + mdatInfo.mBuffer->size()) {
784840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return 1;
785840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
786840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
787840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    // Otherwise make sure the sample is completely contained within this
788840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    // media data block.
789840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
790840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    CHECK_GE(sample.mOffset, mdatInfo.mOffset);
791840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
792840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    CHECK_LE(sample.mOffset + sample.mSize,
793840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber             mdatInfo.mOffset + mdatInfo.mBuffer->size());
794840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
795840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return 0;
796840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
797840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
798cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenvoid FragmentedMP4Parser::resumeIfNecessary() {
799840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (!mSuspended) {
800840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return;
801840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
802840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
80356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    ALOGV("resuming.");
804840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
805840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    mSuspended = false;
806840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    (new AMessage(kWhatProceed, id()))->post();
807840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
808840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
809cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenstatus_t FragmentedMP4Parser::getSample(
810840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        TrackInfo *info, sp<TrackFragment> *fragment, SampleInfo *sampleInfo) {
811840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    for (;;) {
812840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (info->mFragments.empty()) {
813c7708555ea7511aea684e00a55fb5309281540ceAndreas Huber            if (mFinalResult != OK) {
814c7708555ea7511aea684e00a55fb5309281540ceAndreas Huber                return mFinalResult;
815c7708555ea7511aea684e00a55fb5309281540ceAndreas Huber            }
816c7708555ea7511aea684e00a55fb5309281540ceAndreas Huber
817840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            resumeIfNecessary();
818840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return -EWOULDBLOCK;
819840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
820840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
821840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        *fragment = *info->mFragments.begin();
822840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
823840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        status_t err = (*fragment)->getSample(sampleInfo);
824840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
825840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (err == OK) {
826840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return OK;
827840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        } else if (err != ERROR_END_OF_STREAM) {
828840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return err;
829840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
830840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
831840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        // Really, end of this fragment...
832840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
833840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        info->mFragments.erase(info->mFragments.begin());
834840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
835840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
836840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
837cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenstatus_t FragmentedMP4Parser::onDequeueAccessUnit(
838840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        size_t trackIndex, sp<ABuffer> *accessUnit) {
839840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    TrackInfo *info = &mTracks.editValueAt(trackIndex);
840840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
841840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    sp<TrackFragment> fragment;
842840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    SampleInfo sampleInfo;
843840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    status_t err = getSample(info, &fragment, &sampleInfo);
844840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
845840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (err == -EWOULDBLOCK) {
846840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        resumeIfNecessary();
847840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return err;
848840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    } else if (err != OK) {
849840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return err;
850840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
851840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
852840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    err = -EWOULDBLOCK;
853840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
854840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    bool checkDroppable = false;
855840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
856840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    for (size_t i = 0; i < mMediaData.size(); ++i) {
857840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        const MediaDataInfo &mdatInfo = mMediaData.itemAt(i);
858840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
859840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        int cmp = CompareSampleLocation(sampleInfo, mdatInfo);
860840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
86156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        if (cmp < 0 && !mSource->isSeekable()) {
862840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return -EPIPE;
863840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        } else if (cmp == 0) {
864840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            if (i > 0) {
865840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                checkDroppable = true;
866840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
867840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
868840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            err = makeAccessUnit(info, sampleInfo, mdatInfo, accessUnit);
869840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            break;
870840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
871840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
872840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
873840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (err != OK) {
874840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return err;
875840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
876840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
877840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    fragment->advance();
878840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
879840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (!mMediaData.empty() && checkDroppable) {
880840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        size_t numDroppable = 0;
881840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        bool done = false;
882840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
88356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        // XXX FIXME: if one of the tracks is not advanced (e.g. if you play an audio+video
88456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        // file with sf2), then mMediaData will not be pruned and keeps growing
885840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        for (size_t i = 0; !done && i < mMediaData.size(); ++i) {
886840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            const MediaDataInfo &mdatInfo = mMediaData.itemAt(i);
887840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
888840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            for (size_t j = 0; j < mTracks.size(); ++j) {
889840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                TrackInfo *info = &mTracks.editValueAt(j);
890840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
891840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                sp<TrackFragment> fragment;
892840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                SampleInfo sampleInfo;
893840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                err = getSample(info, &fragment, &sampleInfo);
894840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
895840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                if (err != OK) {
896840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    done = true;
897840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    break;
898840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                }
899840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
900840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                int cmp = CompareSampleLocation(sampleInfo, mdatInfo);
901840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
902840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                if (cmp <= 0) {
903840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    done = true;
904840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    break;
905840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                }
906840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
907840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
908840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            if (!done) {
909840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                ++numDroppable;
910840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
911840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
912840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
913840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (numDroppable > 0) {
914840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            mMediaData.removeItemsAt(0, numDroppable);
915840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
916840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            if (mMediaData.size() < 5) {
917840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                resumeIfNecessary();
918840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
919840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
920840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
921840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
922840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return err;
923840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
924840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
925840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huberstatic size_t parseNALSize(size_t nalLengthSize, const uint8_t *data) {
926840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    switch (nalLengthSize) {
927840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        case 1:
928840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return *data;
929840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        case 2:
930840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return U16_AT(data);
931840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        case 3:
932840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return ((size_t)data[0] << 16) | U16_AT(&data[1]);
933840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        case 4:
934840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return U32_AT(data);
935840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
936840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
937840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    // This cannot happen, mNALLengthSize springs to life by adding 1 to
938840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    // a 2-bit integer.
939840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    TRESPASS();
940840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
941840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return 0;
942840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
943840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
944cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenstatus_t FragmentedMP4Parser::makeAccessUnit(
945840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        TrackInfo *info,
946840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        const SampleInfo &sample,
947840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        const MediaDataInfo &mdatInfo,
948840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        sp<ABuffer> *accessUnit) {
949840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (sample.mSampleDescIndex < 1
950840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            || sample.mSampleDescIndex > info->mSampleDescs.size()) {
951840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return ERROR_MALFORMED;
952840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
953840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
954840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    int64_t presentationTimeUs =
955840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        1000000ll * sample.mPresentationTime / info->mMediaTimeScale;
956840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
957840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    const SampleDescription &sampleDesc =
958840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        info->mSampleDescs.itemAt(sample.mSampleDescIndex - 1);
959840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
960840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    size_t nalLengthSize;
961840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (!sampleDesc.mFormat->findSize("nal-length-size", &nalLengthSize)) {
962840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        *accessUnit = new ABuffer(sample.mSize);
963840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
964840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        memcpy((*accessUnit)->data(),
965840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber               mdatInfo.mBuffer->data() + (sample.mOffset - mdatInfo.mOffset),
966840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber               sample.mSize);
967840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
968840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        (*accessUnit)->meta()->setInt64("timeUs", presentationTimeUs);
9698c95fa91fff6e8726df03598d52243f22e5ff8e7Marco Nelissen        if (IsIDR(*accessUnit)) {
9708c95fa91fff6e8726df03598d52243f22e5ff8e7Marco Nelissen            (*accessUnit)->meta()->setInt32("is-sync-frame", 1);
9718c95fa91fff6e8726df03598d52243f22e5ff8e7Marco Nelissen        }
9728c95fa91fff6e8726df03598d52243f22e5ff8e7Marco Nelissen
973840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return OK;
974840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
975840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
976840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    const uint8_t *srcPtr =
977840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        mdatInfo.mBuffer->data() + (sample.mOffset - mdatInfo.mOffset);
978840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
979840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    for (int i = 0; i < 2 ; ++i) {
980840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        size_t srcOffset = 0;
981840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        size_t dstOffset = 0;
982840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
983840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        while (srcOffset < sample.mSize) {
984840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            if (srcOffset + nalLengthSize > sample.mSize) {
985840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                return ERROR_MALFORMED;
986840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
987840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
988840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            size_t nalSize = parseNALSize(nalLengthSize, &srcPtr[srcOffset]);
989840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            srcOffset += nalLengthSize;
990840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
991840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            if (srcOffset + nalSize > sample.mSize) {
992840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                return ERROR_MALFORMED;
993840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
994840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
995840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            if (i == 1) {
996840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                memcpy((*accessUnit)->data() + dstOffset,
997840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                       "\x00\x00\x00\x01",
998840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                       4);
999840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1000840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                memcpy((*accessUnit)->data() + dstOffset + 4,
1001840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                       srcPtr + srcOffset,
1002840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                       nalSize);
1003840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
1004840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1005840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            srcOffset += nalSize;
1006840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            dstOffset += nalSize + 4;
1007840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
1008840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1009840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (i == 0) {
1010840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            (*accessUnit) = new ABuffer(dstOffset);
1011840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            (*accessUnit)->meta()->setInt64(
1012840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    "timeUs", presentationTimeUs);
1013840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
1014840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
10158c95fa91fff6e8726df03598d52243f22e5ff8e7Marco Nelissen    if (IsIDR(*accessUnit)) {
10168c95fa91fff6e8726df03598d52243f22e5ff8e7Marco Nelissen        (*accessUnit)->meta()->setInt32("is-sync-frame", 1);
10178c95fa91fff6e8726df03598d52243f22e5ff8e7Marco Nelissen    }
1018840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1019840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return OK;
1020840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
1021840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1022cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenstatus_t FragmentedMP4Parser::need(size_t size) {
1023840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (!fitsContainer(size)) {
1024840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return -EINVAL;
1025840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1026840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1027840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (size <= mBuffer->size()) {
1028840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return OK;
1029840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1030840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1031840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    sp<AMessage> msg = new AMessage(kWhatReadMore, id());
1032840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    msg->setSize("needed", size - mBuffer->size());
1033840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    msg->post();
1034840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1035840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    // ALOGV("need(%d) returning -EAGAIN, only have %d", size, mBuffer->size());
1036840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1037840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return -EAGAIN;
1038840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
1039840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1040cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenvoid FragmentedMP4Parser::enter(off64_t offset, uint32_t type, uint64_t size) {
1041840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    Container container;
1042bd828233d3eda966bf7145108dde74616abd97fbAndreas Huber    container.mOffset = offset;
1043840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    container.mType = type;
1044840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    container.mExtendsToEOF = (size == 0);
1045840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    container.mBytesRemaining = size;
1046840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1047840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    mStack.push(container);
1048840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
1049840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1050cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenbool FragmentedMP4Parser::fitsContainer(uint64_t size) const {
1051840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    CHECK(!mStack.isEmpty());
1052840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    const Container &container = mStack.itemAt(mStack.size() - 1);
1053840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1054840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return container.mExtendsToEOF || size <= container.mBytesRemaining;
1055840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
1056840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1057cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenuint16_t FragmentedMP4Parser::readU16(size_t offset) {
1058840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    CHECK_LE(offset + 2, mBuffer->size());
1059840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1060840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    const uint8_t *ptr = mBuffer->data() + offset;
1061840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return (ptr[0] << 8) | ptr[1];
1062840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
1063840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1064cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenuint32_t FragmentedMP4Parser::readU32(size_t offset) {
1065840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    CHECK_LE(offset + 4, mBuffer->size());
1066840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1067840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    const uint8_t *ptr = mBuffer->data() + offset;
1068840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3];
1069840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
1070840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1071cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenuint64_t FragmentedMP4Parser::readU64(size_t offset) {
1072840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return (((uint64_t)readU32(offset)) << 32) | readU32(offset + 4);
1073840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
1074840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1075cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenvoid FragmentedMP4Parser::skip(off_t distance) {
1076840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    CHECK(!mStack.isEmpty());
1077840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    for (size_t i = mStack.size(); i-- > 0;) {
1078840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        Container *container = &mStack.editItemAt(i);
1079840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (!container->mExtendsToEOF) {
1080840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            CHECK_LE(distance, (off_t)container->mBytesRemaining);
1081840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1082840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            container->mBytesRemaining -= distance;
1083840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1084840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            if (container->mBytesRemaining == 0) {
1085840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                ALOGV("%sleaving box of type '%s'",
1086840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                        IndentString(mStack.size() - 1),
1087840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                        Fourcc2String(container->mType));
1088840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1089840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber#if 0
1090840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                if (container->mType == FOURCC('s', 't', 's', 'd')) {
1091840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    TrackInfo *trackInfo = editTrack(mCurrentTrackID);
1092840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    for (size_t i = 0;
1093840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                            i < trackInfo->mSampleDescs.size(); ++i) {
1094840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                        ALOGI("format #%d: %s",
1095840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                              i,
1096840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                              trackInfo->mSampleDescs.itemAt(i)
1097840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                                .mFormat->debugString().c_str());
1098840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    }
1099840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                }
1100840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber#endif
1101840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1102840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                if (container->mType == FOURCC('s', 't', 'b', 'l')) {
1103840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    TrackInfo *trackInfo = editTrack(mCurrentTrackID);
1104840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1105840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    trackInfo->mStaticFragment->signalCompletion();
1106840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1107840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    CHECK(trackInfo->mFragments.empty());
1108840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    trackInfo->mFragments.push_back(trackInfo->mStaticFragment);
1109840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    trackInfo->mStaticFragment.clear();
1110840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                } else if (container->mType == FOURCC('t', 'r', 'a', 'f')) {
1111840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    TrackInfo *trackInfo =
1112840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                        editTrack(mTrackFragmentHeaderInfo.mTrackID);
1113840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1114840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    const sp<TrackFragment> &fragment =
1115840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                        *--trackInfo->mFragments.end();
1116840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1117840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    static_cast<DynamicTrackFragment *>(
1118840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                            fragment.get())->signalCompletion();
111956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                } else if (container->mType == FOURCC('m', 'o', 'o', 'v')) {
112056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                    mDoneWithMoov = true;
1121840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                }
1122840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1123840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                container = NULL;
1124840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                mStack.removeItemsAt(i);
1125840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
1126840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
1127840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1128840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1129840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (distance < (off_t)mBuffer->size()) {
1130840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        mBuffer->setRange(mBuffer->offset() + distance, mBuffer->size() - distance);
1131840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        mBufferPos += distance;
1132840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return;
1133840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1134840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1135840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    mBuffer->setRange(0, 0);
1136840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    mBufferPos += distance;
1137840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
1138840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1139cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenstatus_t FragmentedMP4Parser::parseTrackHeader(
1140840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        uint32_t type, size_t offset, uint64_t size) {
1141840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (offset + 4 > size) {
1142840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return -EINVAL;
1143840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1144840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1145840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint32_t flags = readU32(offset);
1146840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1147840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint32_t version = flags >> 24;
1148840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    flags &= 0xffffff;
1149840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1150840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint32_t trackID;
1151840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint64_t duration;
1152840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1153840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (version == 1) {
1154840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (offset + 36 > size) {
1155840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return -EINVAL;
1156840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
1157840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1158840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        trackID = readU32(offset + 20);
1159840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        duration = readU64(offset + 28);
1160840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1161840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        offset += 36;
1162840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    } else if (version == 0) {
1163840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (offset + 24 > size) {
1164840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return -EINVAL;
1165840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
1166840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1167840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        trackID = readU32(offset + 12);
1168840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        duration = readU32(offset + 20);
1169840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1170840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        offset += 24;
1171840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    } else {
1172840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return -EINVAL;
1173840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1174840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1175840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    TrackInfo *info = editTrack(trackID, true /* createIfNecessary */);
1176840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    info->mFlags = flags;
1177840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    info->mDuration = duration;
117856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    if (info->mDuration == 0xffffffff) {
117956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        // ffmpeg sets this to -1, which is incorrect.
118056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        info->mDuration = 0;
118156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
1182840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1183840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    info->mStaticFragment = new StaticTrackFragment;
1184840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1185840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    mCurrentTrackID = trackID;
1186840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1187840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return OK;
1188840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
1189840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1190cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenstatus_t FragmentedMP4Parser::parseMediaHeader(
1191840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        uint32_t type, size_t offset, uint64_t size) {
1192840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (offset + 4 > size) {
1193840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return -EINVAL;
1194840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1195840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1196840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint32_t versionAndFlags = readU32(offset);
1197840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1198840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (versionAndFlags & 0xffffff) {
1199840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return ERROR_MALFORMED;
1200840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1201840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1202840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint32_t version = versionAndFlags >> 24;
1203840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1204840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    TrackInfo *info = editTrack(mCurrentTrackID);
1205840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1206840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (version == 1) {
1207840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (offset + 4 + 32 > size) {
1208840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return -EINVAL;
1209840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
1210840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        info->mMediaTimeScale = U32_AT(mBuffer->data() + offset + 20);
1211840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    } else if (version == 0) {
1212840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (offset + 4 + 20 > size) {
1213840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return -EINVAL;
1214840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
1215840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        info->mMediaTimeScale = U32_AT(mBuffer->data() + offset + 12);
1216840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    } else {
1217840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return ERROR_MALFORMED;
1218840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1219840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1220840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return OK;
1221840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
1222840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1223cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenstatus_t FragmentedMP4Parser::parseMediaHandler(
1224840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        uint32_t type, size_t offset, uint64_t size) {
1225840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (offset + 12 > size) {
1226840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return -EINVAL;
1227840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1228840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1229840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (readU32(offset) != 0) {
1230840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return -EINVAL;
1231840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1232840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1233840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint32_t handlerType = readU32(offset + 8);
1234840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1235840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    switch (handlerType) {
1236840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        case FOURCC('v', 'i', 'd', 'e'):
1237840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        case FOURCC('s', 'o', 'u', 'n'):
1238840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        case FOURCC('h', 'i', 'n', 't'):
1239840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        case FOURCC('m', 'e', 't', 'a'):
1240840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            break;
1241840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1242840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        default:
1243840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return -EINVAL;
1244840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1245840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1246840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    editTrack(mCurrentTrackID)->mMediaHandlerType = handlerType;
1247840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1248840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return OK;
1249840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
1250840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1251cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenstatus_t FragmentedMP4Parser::parseVisualSampleEntry(
1252840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        uint32_t type, size_t offset, uint64_t size) {
1253840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (offset + 78 > size) {
1254840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return -EINVAL;
1255840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1256840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1257840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    TrackInfo *trackInfo = editTrack(mCurrentTrackID);
1258840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1259840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    trackInfo->mSampleDescs.push();
1260840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    SampleDescription *sampleDesc =
1261840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        &trackInfo->mSampleDescs.editItemAt(
1262840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                trackInfo->mSampleDescs.size() - 1);
1263840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1264840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    sampleDesc->mType = type;
1265840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    sampleDesc->mDataRefIndex = readU16(offset + 6);
1266840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1267840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    sp<AMessage> format = new AMessage;
1268840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1269840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    switch (type) {
1270840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
1271840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            format->setString("mime", MEDIA_MIMETYPE_VIDEO_AVC);
1272840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            break;
1273840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
1274840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            format->setString("mime", MEDIA_MIMETYPE_VIDEO_MPEG4);
1275840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            break;
1276b9787142c5f5f8f47e7e35409f4f2ef7112ab72eAndreas Huber        case FOURCC('s', '2', '6', '3'):
1277b9787142c5f5f8f47e7e35409f4f2ef7112ab72eAndreas Huber        case FOURCC('h', '2', '6', '3'):
1278b9787142c5f5f8f47e7e35409f4f2ef7112ab72eAndreas Huber        case FOURCC('H', '2', '6', '3'):
1279b9787142c5f5f8f47e7e35409f4f2ef7112ab72eAndreas Huber            format->setString("mime", MEDIA_MIMETYPE_VIDEO_H263);
1280b9787142c5f5f8f47e7e35409f4f2ef7112ab72eAndreas Huber            break;
1281840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        default:
1282840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            format->setString("mime", "application/octet-stream");
1283840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            break;
1284840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1285840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1286840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    format->setInt32("width", readU16(offset + 8 + 16));
1287840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    format->setInt32("height", readU16(offset + 8 + 18));
1288840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1289840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    sampleDesc->mFormat = format;
1290840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1291840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return OK;
1292840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
1293840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1294cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenstatus_t FragmentedMP4Parser::parseAudioSampleEntry(
1295840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        uint32_t type, size_t offset, uint64_t size) {
1296840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (offset + 28 > size) {
1297840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return -EINVAL;
1298840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1299840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1300840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    TrackInfo *trackInfo = editTrack(mCurrentTrackID);
1301840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1302840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    trackInfo->mSampleDescs.push();
1303840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    SampleDescription *sampleDesc =
1304840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        &trackInfo->mSampleDescs.editItemAt(
1305840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                trackInfo->mSampleDescs.size() - 1);
1306840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1307840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    sampleDesc->mType = type;
1308840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    sampleDesc->mDataRefIndex = readU16(offset + 6);
1309840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1310840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    sp<AMessage> format = new AMessage;
1311840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1312840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    format->setInt32("channel-count", readU16(offset + 8 + 8));
1313840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    format->setInt32("sample-size", readU16(offset + 8 + 10));
1314840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    format->setInt32("sample-rate", readU32(offset + 8 + 16) / 65536.0f);
1315840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1316840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    switch (type) {
1317840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
1318840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            format->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
1319840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            break;
1320b9787142c5f5f8f47e7e35409f4f2ef7112ab72eAndreas Huber
1321840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
1322840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            format->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
1323840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            format->setInt32("channel-count", 1);
1324840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            format->setInt32("sample-rate", 8000);
1325840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            break;
1326b9787142c5f5f8f47e7e35409f4f2ef7112ab72eAndreas Huber
1327840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        case FOURCC('s', 'a', 'w', 'b'):
1328840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            format->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
1329840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            format->setInt32("channel-count", 1);
1330840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            format->setInt32("sample-rate", 16000);
1331840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            break;
1332840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        default:
1333840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            format->setString("mime", "application/octet-stream");
1334840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            break;
1335840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1336840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1337840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    sampleDesc->mFormat = format;
1338840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1339840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return OK;
1340840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
1341840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1342840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huberstatic void addCodecSpecificData(
1343840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        const sp<AMessage> &format, int32_t index,
1344840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        const void *data, size_t size,
1345840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        bool insertStartCode = false) {
1346840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    sp<ABuffer> csd = new ABuffer(insertStartCode ? size + 4 : size);
1347840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1348840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    memcpy(csd->data() + (insertStartCode ? 4 : 0), data, size);
1349840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1350840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (insertStartCode) {
1351840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        memcpy(csd->data(), "\x00\x00\x00\x01", 4);
1352840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1353840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1354840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    csd->meta()->setInt32("csd", true);
1355840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    csd->meta()->setInt64("timeUs", 0ll);
1356840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1357840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    format->setBuffer(StringPrintf("csd-%d", index).c_str(), csd);
1358840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
1359840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1360cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenstatus_t FragmentedMP4Parser::parseSampleSizes(
1361840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        uint32_t type, size_t offset, uint64_t size) {
1362840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return editTrack(mCurrentTrackID)->mStaticFragment->parseSampleSizes(
1363840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            this, type, offset, size);
1364840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
1365840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1366cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenstatus_t FragmentedMP4Parser::parseCompactSampleSizes(
1367840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        uint32_t type, size_t offset, uint64_t size) {
1368840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return editTrack(mCurrentTrackID)->mStaticFragment->parseCompactSampleSizes(
1369840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            this, type, offset, size);
1370840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
1371840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1372cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenstatus_t FragmentedMP4Parser::parseSampleToChunk(
1373840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        uint32_t type, size_t offset, uint64_t size) {
1374840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return editTrack(mCurrentTrackID)->mStaticFragment->parseSampleToChunk(
1375840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            this, type, offset, size);
1376840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
1377840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1378cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenstatus_t FragmentedMP4Parser::parseChunkOffsets(
1379840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        uint32_t type, size_t offset, uint64_t size) {
1380840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return editTrack(mCurrentTrackID)->mStaticFragment->parseChunkOffsets(
1381840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            this, type, offset, size);
1382840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
1383840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1384cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenstatus_t FragmentedMP4Parser::parseChunkOffsets64(
1385840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        uint32_t type, size_t offset, uint64_t size) {
1386840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return editTrack(mCurrentTrackID)->mStaticFragment->parseChunkOffsets64(
1387840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            this, type, offset, size);
1388840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
1389840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1390cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenstatus_t FragmentedMP4Parser::parseAVCCodecSpecificData(
1391840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        uint32_t type, size_t offset, uint64_t size) {
1392840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    TrackInfo *trackInfo = editTrack(mCurrentTrackID);
1393840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1394840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    SampleDescription *sampleDesc =
1395840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        &trackInfo->mSampleDescs.editItemAt(
1396840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                trackInfo->mSampleDescs.size() - 1);
1397840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1398840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (sampleDesc->mType != FOURCC('a', 'v', 'c', '1')) {
1399840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return -EINVAL;
1400840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1401840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1402840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    const uint8_t *ptr = mBuffer->data() + offset;
1403840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1404840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    size -= offset;
1405840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    offset = 0;
1406840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1407840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (size < 7 || ptr[0] != 0x01) {
1408840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return ERROR_MALFORMED;
1409840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1410840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1411840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    sampleDesc->mFormat->setSize("nal-length-size", 1 + (ptr[4] & 3));
1412840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1413840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    size_t numSPS = ptr[5] & 31;
1414840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1415840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    ptr += 6;
1416840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    size -= 6;
1417840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1418840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    for (size_t i = 0; i < numSPS; ++i) {
1419840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (size < 2) {
1420840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return ERROR_MALFORMED;
1421840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
1422840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1423840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        size_t length = U16_AT(ptr);
1424840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1425840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        ptr += 2;
1426840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        size -= 2;
1427840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1428840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (size < length) {
1429840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return ERROR_MALFORMED;
1430840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
1431840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1432840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        addCodecSpecificData(
1433840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                sampleDesc->mFormat, i, ptr, length,
1434840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                true /* insertStartCode */);
1435840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1436840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        ptr += length;
1437840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        size -= length;
1438840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1439840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1440840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (size < 1) {
1441840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return ERROR_MALFORMED;
1442840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1443840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1444840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    size_t numPPS = *ptr;
1445840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    ++ptr;
1446840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    --size;
1447840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1448840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    for (size_t i = 0; i < numPPS; ++i) {
1449840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (size < 2) {
1450840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return ERROR_MALFORMED;
1451840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
1452840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1453840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        size_t length = U16_AT(ptr);
1454840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1455840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        ptr += 2;
1456840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        size -= 2;
1457840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1458840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (size < length) {
1459840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return ERROR_MALFORMED;
1460840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
1461840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1462840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        addCodecSpecificData(
1463840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                sampleDesc->mFormat, numSPS + i, ptr, length,
1464840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                true /* insertStartCode */);
1465840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1466840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        ptr += length;
1467840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        size -= length;
1468840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1469840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1470840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return OK;
1471840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
1472840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1473cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenstatus_t FragmentedMP4Parser::parseESDSCodecSpecificData(
1474840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        uint32_t type, size_t offset, uint64_t size) {
1475840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    TrackInfo *trackInfo = editTrack(mCurrentTrackID);
1476840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1477840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    SampleDescription *sampleDesc =
1478840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        &trackInfo->mSampleDescs.editItemAt(
1479840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                trackInfo->mSampleDescs.size() - 1);
1480840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1481840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (sampleDesc->mType != FOURCC('m', 'p', '4', 'a')
1482840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            && sampleDesc->mType != FOURCC('m', 'p', '4', 'v')) {
1483840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return -EINVAL;
1484840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1485840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1486840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    const uint8_t *ptr = mBuffer->data() + offset;
1487840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1488840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    size -= offset;
1489840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    offset = 0;
1490840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1491840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (size < 4) {
1492840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return -EINVAL;
1493840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1494840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1495840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (U32_AT(ptr) != 0) {
1496840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return -EINVAL;
1497840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1498840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1499840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    ptr += 4;
1500840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    size -=4;
1501840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1502840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    ESDS esds(ptr, size);
1503840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1504840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint8_t objectTypeIndication;
1505840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) {
1506840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return ERROR_MALFORMED;
1507840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1508840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1509840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    const uint8_t *csd;
1510840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    size_t csd_size;
1511840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (esds.getCodecSpecificInfo(
1512840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                (const void **)&csd, &csd_size) != OK) {
1513840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return ERROR_MALFORMED;
1514840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1515840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1516840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    addCodecSpecificData(sampleDesc->mFormat, 0, csd, csd_size);
1517840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1518840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (sampleDesc->mType != FOURCC('m', 'p', '4', 'a')) {
1519840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return OK;
1520840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1521840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1522840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (csd_size == 0) {
1523840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        // There's no further information, i.e. no codec specific data
1524840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        // Let's assume that the information provided in the mpeg4 headers
1525840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        // is accurate and hope for the best.
1526840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1527840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return OK;
1528840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1529840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1530840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (csd_size < 2) {
1531840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return ERROR_MALFORMED;
1532840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1533840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1534840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint32_t objectType = csd[0] >> 3;
1535840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1536840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (objectType == 31) {
1537840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return ERROR_UNSUPPORTED;
1538840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1539840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1540840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint32_t freqIndex = (csd[0] & 7) << 1 | (csd[1] >> 7);
1541840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    int32_t sampleRate = 0;
1542840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    int32_t numChannels = 0;
1543840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (freqIndex == 15) {
1544840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (csd_size < 5) {
1545840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return ERROR_MALFORMED;
1546840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
1547840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1548840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        sampleRate = (csd[1] & 0x7f) << 17
1549840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                        | csd[2] << 9
1550840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                        | csd[3] << 1
1551840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                        | (csd[4] >> 7);
1552840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1553840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        numChannels = (csd[4] >> 3) & 15;
1554840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    } else {
1555840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        static uint32_t kSamplingRate[] = {
1556840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
1557840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            16000, 12000, 11025, 8000, 7350
1558840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        };
1559840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1560840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (freqIndex == 13 || freqIndex == 14) {
1561840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return ERROR_MALFORMED;
1562840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
1563840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1564840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        sampleRate = kSamplingRate[freqIndex];
1565840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        numChannels = (csd[1] >> 3) & 15;
1566840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1567840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1568840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (numChannels == 0) {
1569840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return ERROR_UNSUPPORTED;
1570840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1571840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1572840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    sampleDesc->mFormat->setInt32("sample-rate", sampleRate);
1573840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    sampleDesc->mFormat->setInt32("channel-count", numChannels);
1574840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1575840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return OK;
1576840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
1577840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1578cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenstatus_t FragmentedMP4Parser::parseMediaData(
1579840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        uint32_t type, size_t offset, uint64_t size) {
1580840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    ALOGV("skipping 'mdat' chunk at offsets 0x%08lx-0x%08llx.",
1581840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber          mBufferPos + offset, mBufferPos + size);
1582840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1583840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    sp<ABuffer> buffer = new ABuffer(size - offset);
1584840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    memcpy(buffer->data(), mBuffer->data() + offset, size - offset);
1585840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1586840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    mMediaData.push();
1587840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    MediaDataInfo *info = &mMediaData.editItemAt(mMediaData.size() - 1);
1588840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    info->mBuffer = buffer;
1589840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    info->mOffset = mBufferPos + offset;
1590840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1591840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (mMediaData.size() > 10) {
159256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        ALOGV("suspending for now.");
1593840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        mSuspended = true;
1594840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1595840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1596840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return OK;
1597840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
1598840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
159956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenstatus_t FragmentedMP4Parser::parseSegmentIndex(
160056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        uint32_t type, size_t offset, uint64_t size) {
160156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    ALOGV("sidx box type %d, offset %d, size %d", type, int(offset), int(size));
160256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen//    AString sidxstr;
160356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen//    hexdump(mBuffer->data() + offset, size, 0 /* indent */, &sidxstr);
160456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen//    ALOGV("raw sidx:");
160556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen//    ALOGV("%s", sidxstr.c_str());
160656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    if (offset + 12 > size) {
160756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        return -EINVAL;
160856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
160956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
161056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    uint32_t flags = readU32(offset);
161156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
161256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    uint32_t version = flags >> 24;
161356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    flags &= 0xffffff;
161456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
161556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    ALOGV("sidx version %d", version);
161656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
161756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    uint32_t referenceId = readU32(offset + 4);
161856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    uint32_t timeScale = readU32(offset + 8);
161956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    ALOGV("sidx refid/timescale: %d/%d", referenceId, timeScale);
162056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
162156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    uint64_t earliestPresentationTime;
162256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    uint64_t firstOffset;
162356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
162456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    offset += 12;
162556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
162656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    if (version == 0) {
162756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        if (offset + 8 > size) {
162856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            return -EINVAL;
162956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        }
163056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        earliestPresentationTime = readU32(offset);
163156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        firstOffset = readU32(offset + 4);
163256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        offset += 8;
163356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    } else {
163456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        if (offset + 16 > size) {
163556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            return -EINVAL;
163656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        }
163756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        earliestPresentationTime = readU64(offset);
163856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        firstOffset = readU64(offset + 8);
163956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        offset += 16;
164056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
164156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    ALOGV("sidx pres/off: %Ld/%Ld", earliestPresentationTime, firstOffset);
164256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
164356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    if (offset + 4 > size) {
164456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        return -EINVAL;
164556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
164656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    if (readU16(offset) != 0) { // reserved
164756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        return -EINVAL;
164856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
164956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    int32_t referenceCount = readU16(offset + 2);
165056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    offset += 4;
165156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    ALOGV("refcount: %d", referenceCount);
165256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
165356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    if (offset + referenceCount * 12 > size) {
165456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        return -EINVAL;
165556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
165656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
165756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    TrackInfo *info = editTrack(mCurrentTrackID);
165856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    uint64_t total_duration = 0;
165956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    for (int i = 0; i < referenceCount; i++) {
166056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        uint32_t d1 = readU32(offset);
166156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        uint32_t d2 = readU32(offset + 4);
166256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        uint32_t d3 = readU32(offset + 8);
166356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
166456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        if (d1 & 0x80000000) {
166556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            ALOGW("sub-sidx boxes not supported yet");
166656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        }
166756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        bool sap = d3 & 0x80000000;
166856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        bool saptype = d3 >> 28;
166956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        if (!sap || saptype > 2) {
167056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            ALOGW("not a stream access point, or unsupported type");
167156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        }
167256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        total_duration += d2;
167356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        offset += 12;
167456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        ALOGV(" item %d, %08x %08x %08x", i, d1, d2, d3);
167556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        SidxEntry se;
167656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        se.mSize = d1 & 0x7fffffff;
167756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        se.mDurationUs = 1000000LL * d2 / timeScale;
167856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        info->mSidx.add(se);
167956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
168056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
168156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    info->mSidxDuration = total_duration * 1000000 / timeScale;
168256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    ALOGV("duration: %lld", info->mSidxDuration);
168356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    return OK;
168456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen}
168556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
1686cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenstatus_t FragmentedMP4Parser::parseTrackExtends(
1687840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        uint32_t type, size_t offset, uint64_t size) {
1688840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (offset + 24 > size) {
1689840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return -EINVAL;
1690840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1691840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1692840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (readU32(offset) != 0) {
1693840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return -EINVAL;
1694840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1695840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1696840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint32_t trackID = readU32(offset + 4);
1697840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1698840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    TrackInfo *info = editTrack(trackID, true /* createIfNecessary */);
1699840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    info->mDefaultSampleDescriptionIndex = readU32(offset + 8);
1700840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    info->mDefaultSampleDuration = readU32(offset + 12);
1701840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    info->mDefaultSampleSize = readU32(offset + 16);
1702840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    info->mDefaultSampleFlags = readU32(offset + 20);
1703840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1704840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return OK;
1705840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
1706840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1707cb1f88c684140ce0eb407049a78f889bc7d51be1Marco NelissenFragmentedMP4Parser::TrackInfo *FragmentedMP4Parser::editTrack(
1708840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        uint32_t trackID, bool createIfNecessary) {
1709840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    ssize_t i = mTracks.indexOfKey(trackID);
1710840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1711840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (i >= 0) {
1712840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return &mTracks.editValueAt(i);
1713840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1714840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1715840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (!createIfNecessary) {
1716840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return NULL;
1717840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1718840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1719840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    TrackInfo info;
1720840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    info.mTrackID = trackID;
1721840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    info.mFlags = 0;
1722840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    info.mDuration = 0xffffffff;
172356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    info.mSidxDuration = 0;
1724840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    info.mMediaTimeScale = 0;
1725840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    info.mMediaHandlerType = 0;
1726840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    info.mDefaultSampleDescriptionIndex = 0;
1727840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    info.mDefaultSampleDuration = 0;
1728840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    info.mDefaultSampleSize = 0;
1729840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    info.mDefaultSampleFlags = 0;
1730840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1731840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    info.mDecodingTime = 0;
1732840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1733840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    mTracks.add(trackID, info);
1734840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return &mTracks.editValueAt(mTracks.indexOfKey(trackID));
1735840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
1736840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1737cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenstatus_t FragmentedMP4Parser::parseTrackFragmentHeader(
1738840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        uint32_t type, size_t offset, uint64_t size) {
1739840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (offset + 8 > size) {
1740840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return -EINVAL;
1741840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1742840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1743840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint32_t flags = readU32(offset);
1744840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1745840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (flags & 0xff000000) {
1746840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return -EINVAL;
1747840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1748840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1749840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    mTrackFragmentHeaderInfo.mFlags = flags;
1750840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1751840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    mTrackFragmentHeaderInfo.mTrackID = readU32(offset + 4);
1752840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    offset += 8;
1753840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1754840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent) {
1755840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (offset + 8 > size) {
1756840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return -EINVAL;
1757840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
1758840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1759840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        mTrackFragmentHeaderInfo.mBaseDataOffset = readU64(offset);
1760840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        offset += 8;
1761840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1762840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1763840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (flags & TrackFragmentHeaderInfo::kSampleDescriptionIndexPresent) {
1764840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (offset + 4 > size) {
1765840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return -EINVAL;
1766840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
1767840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1768840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        mTrackFragmentHeaderInfo.mSampleDescriptionIndex = readU32(offset);
1769840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        offset += 4;
1770840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1771840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1772840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (flags & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
1773840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (offset + 4 > size) {
1774840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return -EINVAL;
1775840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
1776840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1777840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        mTrackFragmentHeaderInfo.mDefaultSampleDuration = readU32(offset);
1778840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        offset += 4;
1779840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1780840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1781840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (flags & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
1782840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (offset + 4 > size) {
1783840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return -EINVAL;
1784840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
1785840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1786840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        mTrackFragmentHeaderInfo.mDefaultSampleSize = readU32(offset);
1787840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        offset += 4;
1788840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1789840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1790840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (flags & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
1791840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (offset + 4 > size) {
1792840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return -EINVAL;
1793840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
1794840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1795840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        mTrackFragmentHeaderInfo.mDefaultSampleFlags = readU32(offset);
1796840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        offset += 4;
1797840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1798840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1799840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (!(flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent)) {
1800bd828233d3eda966bf7145108dde74616abd97fbAndreas Huber        // This should point to the position of the first byte of the
1801bd828233d3eda966bf7145108dde74616abd97fbAndreas Huber        // enclosing 'moof' container for the first track and
1802bd828233d3eda966bf7145108dde74616abd97fbAndreas Huber        // the end of the data of the preceding fragment for subsequent
1803bd828233d3eda966bf7145108dde74616abd97fbAndreas Huber        // tracks.
1804840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1805bd828233d3eda966bf7145108dde74616abd97fbAndreas Huber        CHECK_GE(mStack.size(), 2u);
1806840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1807840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        mTrackFragmentHeaderInfo.mBaseDataOffset =
1808bd828233d3eda966bf7145108dde74616abd97fbAndreas Huber            mStack.itemAt(mStack.size() - 2).mOffset;
1809bd828233d3eda966bf7145108dde74616abd97fbAndreas Huber
1810bd828233d3eda966bf7145108dde74616abd97fbAndreas Huber        // XXX TODO: This does not do the right thing for the 2nd and
1811bd828233d3eda966bf7145108dde74616abd97fbAndreas Huber        // subsequent tracks yet.
1812840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1813840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1814840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    mTrackFragmentHeaderInfo.mDataOffset =
1815840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        mTrackFragmentHeaderInfo.mBaseDataOffset;
1816840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1817840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    TrackInfo *trackInfo = editTrack(mTrackFragmentHeaderInfo.mTrackID);
1818840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1819840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (trackInfo->mFragments.empty()
1820840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            || (*trackInfo->mFragments.begin())->complete()) {
1821840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        trackInfo->mFragments.push_back(new DynamicTrackFragment);
1822840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1823840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1824840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return OK;
1825840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
1826840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1827cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenstatus_t FragmentedMP4Parser::parseTrackFragmentRun(
1828840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        uint32_t type, size_t offset, uint64_t size) {
1829840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (offset + 8 > size) {
1830840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return -EINVAL;
1831840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1832840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1833840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    enum {
1834840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        kDataOffsetPresent                  = 0x01,
1835840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        kFirstSampleFlagsPresent            = 0x04,
1836840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        kSampleDurationPresent              = 0x100,
1837840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        kSampleSizePresent                  = 0x200,
1838840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        kSampleFlagsPresent                 = 0x400,
1839840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        kSampleCompositionTimeOffsetPresent = 0x800,
1840840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    };
1841840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1842840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint32_t flags = readU32(offset);
1843840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1844840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (flags & 0xff000000) {
1845840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return -EINVAL;
1846840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1847840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1848840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if ((flags & kFirstSampleFlagsPresent) && (flags & kSampleFlagsPresent)) {
1849840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        // These two shall not be used together.
1850840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return -EINVAL;
1851840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1852840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1853840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint32_t sampleCount = readU32(offset + 4);
1854840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    offset += 8;
1855840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1856840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint64_t dataOffset = mTrackFragmentHeaderInfo.mDataOffset;
1857840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1858840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint32_t firstSampleFlags = 0;
1859840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1860840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (flags & kDataOffsetPresent) {
1861840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (offset + 4 > size) {
1862840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return -EINVAL;
1863840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
1864840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1865840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        int32_t dataOffsetDelta = (int32_t)readU32(offset);
1866840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1867840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        dataOffset = mTrackFragmentHeaderInfo.mBaseDataOffset + dataOffsetDelta;
1868840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1869840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        offset += 4;
1870840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1871840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1872840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (flags & kFirstSampleFlagsPresent) {
1873840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (offset + 4 > size) {
1874840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return -EINVAL;
1875840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
1876840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1877840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        firstSampleFlags = readU32(offset);
1878840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        offset += 4;
1879840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1880840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1881840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    TrackInfo *info = editTrack(mTrackFragmentHeaderInfo.mTrackID);
1882840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1883840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (info == NULL) {
1884840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return -EINVAL;
1885840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1886840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1887840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint32_t sampleDuration = 0, sampleSize = 0, sampleFlags = 0,
1888840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber             sampleCtsOffset = 0;
1889840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1890840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    size_t bytesPerSample = 0;
1891840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (flags & kSampleDurationPresent) {
1892840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        bytesPerSample += 4;
1893840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    } else if (mTrackFragmentHeaderInfo.mFlags
1894840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
1895840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration;
1896840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    } else {
1897840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        sampleDuration = info->mDefaultSampleDuration;
1898840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1899840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1900840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (flags & kSampleSizePresent) {
1901840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        bytesPerSample += 4;
1902840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    } else if (mTrackFragmentHeaderInfo.mFlags
1903840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
1904840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
1905840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    } else {
1906840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        sampleSize = info->mDefaultSampleSize;
1907840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1908840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1909840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (flags & kSampleFlagsPresent) {
1910840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        bytesPerSample += 4;
1911840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    } else if (mTrackFragmentHeaderInfo.mFlags
1912840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
1913840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
1914840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    } else {
1915840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        sampleFlags = info->mDefaultSampleFlags;
1916840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1917840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1918840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (flags & kSampleCompositionTimeOffsetPresent) {
1919840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        bytesPerSample += 4;
1920840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    } else {
1921840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        sampleCtsOffset = 0;
1922840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1923840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1924840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (offset + sampleCount * bytesPerSample > size) {
1925840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return -EINVAL;
1926840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1927840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1928840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint32_t sampleDescIndex =
1929840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        (mTrackFragmentHeaderInfo.mFlags
1930840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            & TrackFragmentHeaderInfo::kSampleDescriptionIndexPresent)
1931840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            ? mTrackFragmentHeaderInfo.mSampleDescriptionIndex
1932840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            : info->mDefaultSampleDescriptionIndex;
1933840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1934840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    for (uint32_t i = 0; i < sampleCount; ++i) {
1935840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (flags & kSampleDurationPresent) {
1936840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            sampleDuration = readU32(offset);
1937840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            offset += 4;
1938840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
1939840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1940840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (flags & kSampleSizePresent) {
1941840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            sampleSize = readU32(offset);
1942840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            offset += 4;
1943840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
1944840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1945840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (flags & kSampleFlagsPresent) {
1946840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            sampleFlags = readU32(offset);
1947840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            offset += 4;
1948840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
1949840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1950840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (flags & kSampleCompositionTimeOffsetPresent) {
1951840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            sampleCtsOffset = readU32(offset);
1952840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            offset += 4;
1953840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
1954840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1955840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        ALOGV("adding sample at offset 0x%08llx, size %u, duration %u, "
1956840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber              "sampleDescIndex=%u, flags 0x%08x",
1957840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                dataOffset, sampleSize, sampleDuration,
1958840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                sampleDescIndex,
1959840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                (flags & kFirstSampleFlagsPresent) && i == 0
1960840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    ? firstSampleFlags : sampleFlags);
1961840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1962840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        const sp<TrackFragment> &fragment = *--info->mFragments.end();
1963840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1964840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        uint32_t decodingTime = info->mDecodingTime;
1965840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        info->mDecodingTime += sampleDuration;
1966840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        uint32_t presentationTime = decodingTime + sampleCtsOffset;
1967840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1968840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        static_cast<DynamicTrackFragment *>(
1969840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                fragment.get())->addSample(
1970840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    dataOffset,
1971840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    sampleSize,
1972840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    presentationTime,
1973840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    sampleDescIndex,
1974840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    ((flags & kFirstSampleFlagsPresent) && i == 0)
1975840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                        ? firstSampleFlags : sampleFlags);
1976840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1977840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        dataOffset += sampleSize;
1978840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
1979840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1980840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    mTrackFragmentHeaderInfo.mDataOffset = dataOffset;
1981840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1982840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return OK;
1983840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
1984840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1985cb1f88c684140ce0eb407049a78f889bc7d51be1Marco Nelissenvoid FragmentedMP4Parser::copyBuffer(
19862e136686cd60556b681480079142142ab4a7e07cJames Dong        sp<ABuffer> *dst, size_t offset, uint64_t size) const {
19872e136686cd60556b681480079142142ab4a7e07cJames Dong    sp<ABuffer> buf = new ABuffer(size);
1988840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    memcpy(buf->data(), mBuffer->data() + offset, size);
1989840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1990840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    *dst = buf;
1991840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
1992840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
1993840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}  // namespace android
1994