1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "FragmentedMP4Parser"
19#include <utils/Log.h>
20
21#include "include/ESDS.h"
22#include "include/FragmentedMP4Parser.h"
23#include "TrackFragment.h"
24
25
26#include <media/stagefright/foundation/ABuffer.h>
27#include <media/stagefright/foundation/ADebug.h>
28#include <media/stagefright/foundation/AMessage.h>
29#include <media/stagefright/foundation/hexdump.h>
30#include <media/stagefright/MediaDefs.h>
31#include <media/stagefright/MediaErrors.h>
32#include <media/stagefright/Utils.h>
33
34
35namespace android {
36
37static const char *Fourcc2String(uint32_t fourcc) {
38    static char buffer[5];
39    buffer[4] = '\0';
40    buffer[0] = fourcc >> 24;
41    buffer[1] = (fourcc >> 16) & 0xff;
42    buffer[2] = (fourcc >> 8) & 0xff;
43    buffer[3] = fourcc & 0xff;
44
45    return buffer;
46}
47
48static const char *IndentString(size_t n) {
49    static const char kSpace[] = "                              ";
50    return kSpace + sizeof(kSpace) - 2 * n - 1;
51}
52
53// static
54const FragmentedMP4Parser::DispatchEntry FragmentedMP4Parser::kDispatchTable[] = {
55    { FOURCC('m', 'o', 'o', 'v'), 0, NULL },
56    { FOURCC('t', 'r', 'a', 'k'), FOURCC('m', 'o', 'o', 'v'), NULL },
57    { FOURCC('u', 'd', 't', 'a'), FOURCC('t', 'r', 'a', 'k'), NULL },
58    { FOURCC('u', 'd', 't', 'a'), FOURCC('m', 'o', 'o', 'v'), NULL },
59    { FOURCC('m', 'e', 't', 'a'), FOURCC('u', 'd', 't', 'a'), NULL },
60    { FOURCC('i', 'l', 's', 't'), FOURCC('m', 'e', 't', 'a'), NULL },
61
62    { FOURCC('t', 'k', 'h', 'd'), FOURCC('t', 'r', 'a', 'k'),
63        &FragmentedMP4Parser::parseTrackHeader
64    },
65
66    { FOURCC('m', 'v', 'e', 'x'), FOURCC('m', 'o', 'o', 'v'), NULL },
67
68    { FOURCC('t', 'r', 'e', 'x'), FOURCC('m', 'v', 'e', 'x'),
69        &FragmentedMP4Parser::parseTrackExtends
70    },
71
72    { FOURCC('e', 'd', 't', 's'), FOURCC('t', 'r', 'a', 'k'), NULL },
73    { FOURCC('m', 'd', 'i', 'a'), FOURCC('t', 'r', 'a', 'k'), NULL },
74
75    { FOURCC('m', 'd', 'h', 'd'), FOURCC('m', 'd', 'i', 'a'),
76        &FragmentedMP4Parser::parseMediaHeader
77    },
78
79    { FOURCC('h', 'd', 'l', 'r'), FOURCC('m', 'd', 'i', 'a'),
80        &FragmentedMP4Parser::parseMediaHandler
81    },
82
83    { FOURCC('m', 'i', 'n', 'f'), FOURCC('m', 'd', 'i', 'a'), NULL },
84    { FOURCC('d', 'i', 'n', 'f'), FOURCC('m', 'i', 'n', 'f'), NULL },
85    { FOURCC('s', 't', 'b', 'l'), FOURCC('m', 'i', 'n', 'f'), NULL },
86    { FOURCC('s', 't', 's', 'd'), FOURCC('s', 't', 'b', 'l'), NULL },
87
88    { FOURCC('s', 't', 's', 'z'), FOURCC('s', 't', 'b', 'l'),
89        &FragmentedMP4Parser::parseSampleSizes },
90
91    { FOURCC('s', 't', 'z', '2'), FOURCC('s', 't', 'b', 'l'),
92        &FragmentedMP4Parser::parseCompactSampleSizes },
93
94    { FOURCC('s', 't', 's', 'c'), FOURCC('s', 't', 'b', 'l'),
95        &FragmentedMP4Parser::parseSampleToChunk },
96
97    { FOURCC('s', 't', 'c', 'o'), FOURCC('s', 't', 'b', 'l'),
98        &FragmentedMP4Parser::parseChunkOffsets },
99
100    { FOURCC('c', 'o', '6', '4'), FOURCC('s', 't', 'b', 'l'),
101        &FragmentedMP4Parser::parseChunkOffsets64 },
102
103    { FOURCC('a', 'v', 'c', 'C'), FOURCC('a', 'v', 'c', '1'),
104        &FragmentedMP4Parser::parseAVCCodecSpecificData },
105
106    { FOURCC('e', 's', 'd', 's'), FOURCC('m', 'p', '4', 'a'),
107        &FragmentedMP4Parser::parseESDSCodecSpecificData },
108
109    { FOURCC('e', 's', 'd', 's'), FOURCC('m', 'p', '4', 'v'),
110        &FragmentedMP4Parser::parseESDSCodecSpecificData },
111
112    { FOURCC('m', 'd', 'a', 't'), 0, &FragmentedMP4Parser::parseMediaData },
113
114    { FOURCC('m', 'o', 'o', 'f'), 0, NULL },
115    { FOURCC('t', 'r', 'a', 'f'), FOURCC('m', 'o', 'o', 'f'), NULL },
116
117    { FOURCC('t', 'f', 'h', 'd'), FOURCC('t', 'r', 'a', 'f'),
118        &FragmentedMP4Parser::parseTrackFragmentHeader
119    },
120    { FOURCC('t', 'r', 'u', 'n'), FOURCC('t', 'r', 'a', 'f'),
121        &FragmentedMP4Parser::parseTrackFragmentRun
122    },
123
124    { FOURCC('m', 'f', 'r', 'a'), 0, NULL },
125
126    { FOURCC('s', 'i', 'd', 'x'), 0, &FragmentedMP4Parser::parseSegmentIndex },
127};
128
129struct FileSource : public FragmentedMP4Parser::Source {
130    FileSource(const char *filename)
131        : mFile(fopen(filename, "rb")) {
132            CHECK(mFile != NULL);
133        }
134
135    virtual ssize_t readAt(off64_t offset, void *data, size_t size) {
136        fseek(mFile, offset, SEEK_SET);
137        return fread(data, 1, size, mFile);
138    }
139
140    virtual bool isSeekable() {
141        return true;
142    }
143
144    private:
145    FILE *mFile;
146
147    DISALLOW_EVIL_CONSTRUCTORS(FileSource);
148};
149
150struct ReadTracker : public RefBase {
151    ReadTracker(off64_t size) {
152        allocSize = 1 + size / 8192; // 1 bit per kilobyte
153        bitmap = (char*) calloc(1, allocSize);
154    }
155    virtual ~ReadTracker() {
156        dumpToLog();
157        free(bitmap);
158    }
159    void mark(off64_t offset, size_t size) {
160        int firstbit = offset / 1024;
161        int lastbit = (offset + size - 1) / 1024;
162        for (int i = firstbit; i <= lastbit; i++) {
163            bitmap[i/8] |= (0x80 >> (i & 7));
164        }
165    }
166
167 private:
168    void dumpToLog() {
169        // 96 chars per line, each char represents one kilobyte, 1 kb per bit
170        int numlines = allocSize / 12;
171        char buf[97];
172        char *cur = bitmap;
173        for (int i = 0; i < numlines; i++ && cur) {
174            for (int j = 0; j < 12; j++) {
175                for (int k = 0; k < 8; k++) {
176                    buf[(j * 8) + k] = (*cur & (0x80 >> k)) ? 'X' : '.';
177                }
178                cur++;
179            }
180            buf[96] = '\0';
181            ALOGI("%5dk: %s", i * 96, buf);
182        }
183    }
184
185    size_t allocSize;
186    char *bitmap;
187};
188
189struct DataSourceSource : public FragmentedMP4Parser::Source {
190    DataSourceSource(sp<DataSource> &source)
191        : mDataSource(source) {
192            CHECK(mDataSource != NULL);
193#if 0
194            off64_t size;
195            if (source->getSize(&size) == OK) {
196                mReadTracker = new ReadTracker(size);
197            } else {
198                ALOGE("couldn't get data source size");
199            }
200#endif
201        }
202
203    virtual ssize_t readAt(off64_t offset, void *data, size_t size) {
204        if (mReadTracker != NULL) {
205            mReadTracker->mark(offset, size);
206        }
207        return mDataSource->readAt(offset, data, size);
208    }
209
210    virtual bool isSeekable() {
211        return true;
212    }
213
214    private:
215    sp<DataSource> mDataSource;
216    sp<ReadTracker> mReadTracker;
217
218    DISALLOW_EVIL_CONSTRUCTORS(DataSourceSource);
219};
220
221FragmentedMP4Parser::FragmentedMP4Parser()
222    : mBufferPos(0),
223      mSuspended(false),
224      mDoneWithMoov(false),
225      mFirstMoofOffset(0),
226      mFinalResult(OK) {
227}
228
229FragmentedMP4Parser::~FragmentedMP4Parser() {
230}
231
232void FragmentedMP4Parser::start(const char *filename) {
233    sp<AMessage> msg = new AMessage(kWhatStart, id());
234    msg->setObject("source", new FileSource(filename));
235    msg->post();
236    ALOGV("Parser::start(%s)", filename);
237}
238
239void FragmentedMP4Parser::start(const sp<Source> &source) {
240    sp<AMessage> msg = new AMessage(kWhatStart, id());
241    msg->setObject("source", source);
242    msg->post();
243    ALOGV("Parser::start(Source)");
244}
245
246void FragmentedMP4Parser::start(sp<DataSource> &source) {
247    sp<AMessage> msg = new AMessage(kWhatStart, id());
248    msg->setObject("source", new DataSourceSource(source));
249    msg->post();
250    ALOGV("Parser::start(DataSource)");
251}
252
253sp<AMessage> FragmentedMP4Parser::getFormat(bool audio, bool synchronous) {
254
255    while (true) {
256        bool moovDone = mDoneWithMoov;
257        sp<AMessage> msg = new AMessage(kWhatGetFormat, id());
258        msg->setInt32("audio", audio);
259
260        sp<AMessage> response;
261        status_t err = msg->postAndAwaitResponse(&response);
262
263        if (err != OK) {
264            ALOGV("getFormat post failed: %d", err);
265            return NULL;
266        }
267
268        if (response->findInt32("err", &err) && err != OK) {
269            if (synchronous && err == -EWOULDBLOCK && !moovDone) {
270                resumeIfNecessary();
271                ALOGV("@getFormat parser not ready yet, retrying");
272                usleep(10000);
273                continue;
274            }
275            ALOGV("getFormat failed: %d", err);
276            return NULL;
277        }
278
279        sp<AMessage> format;
280        CHECK(response->findMessage("format", &format));
281
282        ALOGV("returning format %s", format->debugString().c_str());
283        return format;
284    }
285}
286
287status_t FragmentedMP4Parser::seekTo(bool wantAudio, int64_t timeUs) {
288    sp<AMessage> msg = new AMessage(kWhatSeekTo, id());
289    msg->setInt32("audio", wantAudio);
290    msg->setInt64("position", timeUs);
291
292    sp<AMessage> response;
293    status_t err = msg->postAndAwaitResponse(&response);
294    return err;
295}
296
297bool FragmentedMP4Parser::isSeekable() const {
298    while (mFirstMoofOffset == 0 && mFinalResult == OK) {
299        usleep(10000);
300    }
301    bool seekable = mSource->isSeekable();
302    for (size_t i = 0; seekable && i < mTracks.size(); i++) {
303        const TrackInfo *info = &mTracks.valueAt(i);
304        seekable &= !info->mSidx.empty();
305    }
306    return seekable;
307}
308
309status_t FragmentedMP4Parser::onSeekTo(bool wantAudio, int64_t position) {
310    status_t err = -EINVAL;
311    ssize_t trackIndex = findTrack(wantAudio);
312    if (trackIndex < 0) {
313        err = trackIndex;
314    } else {
315        TrackInfo *info = &mTracks.editValueAt(trackIndex);
316
317        int numSidxEntries = info->mSidx.size();
318        int64_t totalTime = 0;
319        off_t totalOffset = mFirstMoofOffset;
320        for (int i = 0; i < numSidxEntries; i++) {
321            const SidxEntry *se = &info->mSidx[i];
322            totalTime += se->mDurationUs;
323            if (totalTime > position) {
324                mBuffer->setRange(0,0);
325                mBufferPos = totalOffset;
326                if (mFinalResult == ERROR_END_OF_STREAM) {
327                    mFinalResult = OK;
328                    mSuspended = true; // force resume
329                    resumeIfNecessary();
330                }
331                info->mFragments.clear();
332                info->mDecodingTime = position * info->mMediaTimeScale / 1000000ll;
333                return OK;
334            }
335            totalOffset += se->mSize;
336        }
337    }
338    ALOGV("seekTo out of range");
339    return err;
340}
341
342status_t FragmentedMP4Parser::dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit,
343                                                bool synchronous) {
344
345    while (true) {
346        sp<AMessage> msg = new AMessage(kWhatDequeueAccessUnit, id());
347        msg->setInt32("audio", audio);
348
349        sp<AMessage> response;
350        status_t err = msg->postAndAwaitResponse(&response);
351
352        if (err != OK) {
353            ALOGV("dequeue fail 1: %d", err);
354            return err;
355        }
356
357        if (response->findInt32("err", &err) && err != OK) {
358            if (synchronous && err == -EWOULDBLOCK) {
359                resumeIfNecessary();
360                ALOGV("Parser not ready yet, retrying");
361                usleep(10000);
362                continue;
363            }
364            ALOGV("dequeue fail 2: %d, %d", err, synchronous);
365            return err;
366        }
367
368        CHECK(response->findBuffer("accessUnit", accessUnit));
369
370        return OK;
371    }
372}
373
374ssize_t FragmentedMP4Parser::findTrack(bool wantAudio) const {
375    for (size_t i = 0; i < mTracks.size(); ++i) {
376        const TrackInfo *info = &mTracks.valueAt(i);
377
378        bool isAudio =
379            info->mMediaHandlerType == FOURCC('s', 'o', 'u', 'n');
380
381        bool isVideo =
382            info->mMediaHandlerType == FOURCC('v', 'i', 'd', 'e');
383
384        if ((wantAudio && isAudio) || (!wantAudio && !isAudio)) {
385            if (info->mSampleDescs.empty()) {
386                break;
387            }
388
389            return i;
390        }
391    }
392
393    return -EWOULDBLOCK;
394}
395
396void FragmentedMP4Parser::onMessageReceived(const sp<AMessage> &msg) {
397    switch (msg->what()) {
398        case kWhatStart:
399        {
400            sp<RefBase> obj;
401            CHECK(msg->findObject("source", &obj));
402
403            mSource = static_cast<Source *>(obj.get());
404
405            mBuffer = new ABuffer(512 * 1024);
406            mBuffer->setRange(0, 0);
407
408            enter(0ll, 0, 0);
409
410            (new AMessage(kWhatProceed, id()))->post();
411            break;
412        }
413
414        case kWhatProceed:
415        {
416            CHECK(!mSuspended);
417
418            status_t err = onProceed();
419
420            if (err == OK) {
421                if (!mSuspended) {
422                    msg->post();
423                }
424            } else if (err != -EAGAIN) {
425                ALOGE("onProceed returned error %d", err);
426            }
427
428            break;
429        }
430
431        case kWhatReadMore:
432        {
433            size_t needed;
434            CHECK(msg->findSize("needed", &needed));
435
436            memmove(mBuffer->base(), mBuffer->data(), mBuffer->size());
437            mBufferPos += mBuffer->offset();
438            mBuffer->setRange(0, mBuffer->size());
439
440            size_t maxBytesToRead = mBuffer->capacity() - mBuffer->size();
441
442            if (maxBytesToRead < needed) {
443                ALOGV("resizing buffer.");
444
445                sp<ABuffer> newBuffer =
446                    new ABuffer((mBuffer->size() + needed + 1023) & ~1023);
447                memcpy(newBuffer->data(), mBuffer->data(), mBuffer->size());
448                newBuffer->setRange(0, mBuffer->size());
449
450                mBuffer = newBuffer;
451                maxBytesToRead = mBuffer->capacity() - mBuffer->size();
452            }
453
454            CHECK_GE(maxBytesToRead, needed);
455
456            ssize_t n = mSource->readAt(
457                    mBufferPos + mBuffer->size(),
458                    mBuffer->data() + mBuffer->size(), needed);
459
460            if (n < (ssize_t)needed) {
461                ALOGV("Reached EOF when reading %d @ %d + %d", needed, mBufferPos, mBuffer->size());
462                if (n < 0) {
463                    mFinalResult = n;
464                } else if (n == 0) {
465                    mFinalResult = ERROR_END_OF_STREAM;
466                } else {
467                    mFinalResult = ERROR_IO;
468                }
469            } else {
470                mBuffer->setRange(0, mBuffer->size() + n);
471                (new AMessage(kWhatProceed, id()))->post();
472            }
473
474            break;
475        }
476
477        case kWhatGetFormat:
478        {
479            int32_t wantAudio;
480            CHECK(msg->findInt32("audio", &wantAudio));
481
482            status_t err = -EWOULDBLOCK;
483            sp<AMessage> response = new AMessage;
484
485            ssize_t trackIndex = findTrack(wantAudio);
486
487            if (trackIndex < 0) {
488                err = trackIndex;
489            } else {
490                TrackInfo *info = &mTracks.editValueAt(trackIndex);
491
492                sp<AMessage> format = info->mSampleDescs.itemAt(0).mFormat;
493                if (info->mSidxDuration) {
494                    format->setInt64("durationUs", info->mSidxDuration);
495                } else {
496                    // this is probably going to be zero. Oh well...
497                    format->setInt64("durationUs",
498                                     1000000ll * info->mDuration / info->mMediaTimeScale);
499                }
500                response->setMessage(
501                        "format", format);
502
503                err = OK;
504            }
505
506            response->setInt32("err", err);
507
508            uint32_t replyID;
509            CHECK(msg->senderAwaitsResponse(&replyID));
510
511            response->postReply(replyID);
512            break;
513        }
514
515        case kWhatDequeueAccessUnit:
516        {
517            int32_t wantAudio;
518            CHECK(msg->findInt32("audio", &wantAudio));
519
520            status_t err = -EWOULDBLOCK;
521            sp<AMessage> response = new AMessage;
522
523            ssize_t trackIndex = findTrack(wantAudio);
524
525            if (trackIndex < 0) {
526                err = trackIndex;
527            } else {
528                sp<ABuffer> accessUnit;
529                err = onDequeueAccessUnit(trackIndex, &accessUnit);
530
531                if (err == OK) {
532                    response->setBuffer("accessUnit", accessUnit);
533                }
534            }
535
536            response->setInt32("err", err);
537
538            uint32_t replyID;
539            CHECK(msg->senderAwaitsResponse(&replyID));
540
541            response->postReply(replyID);
542            break;
543        }
544
545        case kWhatSeekTo:
546        {
547            ALOGV("kWhatSeekTo");
548            int32_t wantAudio;
549            CHECK(msg->findInt32("audio", &wantAudio));
550            int64_t position;
551            CHECK(msg->findInt64("position", &position));
552
553            status_t err = -EWOULDBLOCK;
554            sp<AMessage> response = new AMessage;
555
556            ssize_t trackIndex = findTrack(wantAudio);
557
558            if (trackIndex < 0) {
559                err = trackIndex;
560            } else {
561                err = onSeekTo(wantAudio, position);
562            }
563            response->setInt32("err", err);
564            uint32_t replyID;
565            CHECK(msg->senderAwaitsResponse(&replyID));
566            response->postReply(replyID);
567            break;
568        }
569        default:
570            TRESPASS();
571    }
572}
573
574status_t FragmentedMP4Parser::onProceed() {
575    status_t err;
576
577    if ((err = need(8)) != OK) {
578        return err;
579    }
580
581    uint64_t size = readU32(0);
582    uint32_t type = readU32(4);
583
584    size_t offset = 8;
585
586    if (size == 1) {
587        if ((err = need(16)) != OK) {
588            return err;
589        }
590
591        size = readU64(offset);
592        offset += 8;
593    }
594
595    uint8_t userType[16];
596
597    if (type == FOURCC('u', 'u', 'i', 'd')) {
598        if ((err = need(offset + 16)) != OK) {
599            return err;
600        }
601
602        memcpy(userType, mBuffer->data() + offset, 16);
603        offset += 16;
604    }
605
606    CHECK(!mStack.isEmpty());
607    uint32_t ptype = mStack.itemAt(mStack.size() - 1).mType;
608
609    static const size_t kNumDispatchers =
610        sizeof(kDispatchTable) / sizeof(kDispatchTable[0]);
611
612    size_t i;
613    for (i = 0; i < kNumDispatchers; ++i) {
614        if (kDispatchTable[i].mType == type
615                && kDispatchTable[i].mParentType == ptype) {
616            break;
617        }
618    }
619
620    // SampleEntry boxes are container boxes that start with a variable
621    // amount of data depending on the media handler type.
622    // We don't look inside 'hint' type SampleEntry boxes.
623
624    bool isSampleEntryBox =
625        (ptype == FOURCC('s', 't', 's', 'd'))
626        && editTrack(mCurrentTrackID)->mMediaHandlerType
627        != FOURCC('h', 'i', 'n', 't');
628
629    if ((i < kNumDispatchers && kDispatchTable[i].mHandler == 0)
630            || isSampleEntryBox || ptype == FOURCC('i', 'l', 's', 't')) {
631        // This is a container box.
632        if (type == FOURCC('m', 'o', 'o', 'f')) {
633            if (mFirstMoofOffset == 0) {
634                ALOGV("first moof @ %08x", mBufferPos + offset);
635                mFirstMoofOffset = mBufferPos + offset - 8; // point at the size
636            }
637        }
638        if (type == FOURCC('m', 'e', 't', 'a')) {
639            if ((err = need(offset + 4)) < OK) {
640                return err;
641            }
642
643            if (readU32(offset) != 0) {
644                return -EINVAL;
645            }
646
647            offset += 4;
648        } else if (type == FOURCC('s', 't', 's', 'd')) {
649            if ((err = need(offset + 8)) < OK) {
650                return err;
651            }
652
653            if (readU32(offset) != 0) {
654                return -EINVAL;
655            }
656
657            if (readU32(offset + 4) == 0) {
658                // We need at least some entries.
659                return -EINVAL;
660            }
661
662            offset += 8;
663        } else if (isSampleEntryBox) {
664            size_t headerSize;
665
666            switch (editTrack(mCurrentTrackID)->mMediaHandlerType) {
667                case FOURCC('v', 'i', 'd', 'e'):
668                {
669                    // 8 bytes SampleEntry + 70 bytes VisualSampleEntry
670                    headerSize = 78;
671                    break;
672                }
673
674                case FOURCC('s', 'o', 'u', 'n'):
675                {
676                    // 8 bytes SampleEntry + 20 bytes AudioSampleEntry
677                    headerSize = 28;
678                    break;
679                }
680
681                case FOURCC('m', 'e', 't', 'a'):
682                {
683                    headerSize = 8;  // 8 bytes SampleEntry
684                    break;
685                }
686
687                default:
688                    TRESPASS();
689            }
690
691            if (offset + headerSize > size) {
692                return -EINVAL;
693            }
694
695            if ((err = need(offset + headerSize)) != OK) {
696                return err;
697            }
698
699            switch (editTrack(mCurrentTrackID)->mMediaHandlerType) {
700                case FOURCC('v', 'i', 'd', 'e'):
701                {
702                    err = parseVisualSampleEntry(
703                            type, offset, offset + headerSize);
704                    break;
705                }
706
707                case FOURCC('s', 'o', 'u', 'n'):
708                {
709                    err = parseAudioSampleEntry(
710                            type, offset, offset + headerSize);
711                    break;
712                }
713
714                case FOURCC('m', 'e', 't', 'a'):
715                {
716                    err = OK;
717                    break;
718                }
719
720                default:
721                    TRESPASS();
722            }
723
724            if (err != OK) {
725                return err;
726            }
727
728            offset += headerSize;
729        }
730
731        skip(offset);
732
733        ALOGV("%sentering box of type '%s'",
734                IndentString(mStack.size()), Fourcc2String(type));
735
736        enter(mBufferPos - offset, type, size - offset);
737    } else {
738        if (!fitsContainer(size)) {
739            return -EINVAL;
740        }
741
742        if (i < kNumDispatchers && kDispatchTable[i].mHandler != 0) {
743            // We have a handler for this box type.
744
745            if ((err = need(size)) != OK) {
746                return err;
747            }
748
749            ALOGV("%sparsing box of type '%s'",
750                    IndentString(mStack.size()), Fourcc2String(type));
751
752            if ((err = (this->*kDispatchTable[i].mHandler)(
753                            type, offset, size)) != OK) {
754                return err;
755            }
756        } else {
757            // Unknown box type
758
759            ALOGV("%sskipping box of type '%s', size %llu",
760                    IndentString(mStack.size()),
761                    Fourcc2String(type), size);
762
763        }
764
765        skip(size);
766    }
767
768    return OK;
769}
770
771// static
772int FragmentedMP4Parser::CompareSampleLocation(
773        const SampleInfo &sample, const MediaDataInfo &mdatInfo) {
774    if (sample.mOffset + sample.mSize < mdatInfo.mOffset) {
775        return -1;
776    }
777
778    if (sample.mOffset >= mdatInfo.mOffset + mdatInfo.mBuffer->size()) {
779        return 1;
780    }
781
782    // Otherwise make sure the sample is completely contained within this
783    // media data block.
784
785    CHECK_GE(sample.mOffset, mdatInfo.mOffset);
786
787    CHECK_LE(sample.mOffset + sample.mSize,
788             mdatInfo.mOffset + mdatInfo.mBuffer->size());
789
790    return 0;
791}
792
793void FragmentedMP4Parser::resumeIfNecessary() {
794    if (!mSuspended) {
795        return;
796    }
797
798    ALOGV("resuming.");
799
800    mSuspended = false;
801    (new AMessage(kWhatProceed, id()))->post();
802}
803
804status_t FragmentedMP4Parser::getSample(
805        TrackInfo *info, sp<TrackFragment> *fragment, SampleInfo *sampleInfo) {
806    for (;;) {
807        if (info->mFragments.empty()) {
808            if (mFinalResult != OK) {
809                return mFinalResult;
810            }
811
812            resumeIfNecessary();
813            return -EWOULDBLOCK;
814        }
815
816        *fragment = *info->mFragments.begin();
817
818        status_t err = (*fragment)->getSample(sampleInfo);
819
820        if (err == OK) {
821            return OK;
822        } else if (err != ERROR_END_OF_STREAM) {
823            return err;
824        }
825
826        // Really, end of this fragment...
827
828        info->mFragments.erase(info->mFragments.begin());
829    }
830}
831
832status_t FragmentedMP4Parser::onDequeueAccessUnit(
833        size_t trackIndex, sp<ABuffer> *accessUnit) {
834    TrackInfo *info = &mTracks.editValueAt(trackIndex);
835
836    sp<TrackFragment> fragment;
837    SampleInfo sampleInfo;
838    status_t err = getSample(info, &fragment, &sampleInfo);
839
840    if (err == -EWOULDBLOCK) {
841        resumeIfNecessary();
842        return err;
843    } else if (err != OK) {
844        return err;
845    }
846
847    err = -EWOULDBLOCK;
848
849    bool checkDroppable = false;
850
851    for (size_t i = 0; i < mMediaData.size(); ++i) {
852        const MediaDataInfo &mdatInfo = mMediaData.itemAt(i);
853
854        int cmp = CompareSampleLocation(sampleInfo, mdatInfo);
855
856        if (cmp < 0 && !mSource->isSeekable()) {
857            return -EPIPE;
858        } else if (cmp == 0) {
859            if (i > 0) {
860                checkDroppable = true;
861            }
862
863            err = makeAccessUnit(info, sampleInfo, mdatInfo, accessUnit);
864            break;
865        }
866    }
867
868    if (err != OK) {
869        return err;
870    }
871
872    fragment->advance();
873
874    if (!mMediaData.empty() && checkDroppable) {
875        size_t numDroppable = 0;
876        bool done = false;
877
878        // XXX FIXME: if one of the tracks is not advanced (e.g. if you play an audio+video
879        // file with sf2), then mMediaData will not be pruned and keeps growing
880        for (size_t i = 0; !done && i < mMediaData.size(); ++i) {
881            const MediaDataInfo &mdatInfo = mMediaData.itemAt(i);
882
883            for (size_t j = 0; j < mTracks.size(); ++j) {
884                TrackInfo *info = &mTracks.editValueAt(j);
885
886                sp<TrackFragment> fragment;
887                SampleInfo sampleInfo;
888                err = getSample(info, &fragment, &sampleInfo);
889
890                if (err != OK) {
891                    done = true;
892                    break;
893                }
894
895                int cmp = CompareSampleLocation(sampleInfo, mdatInfo);
896
897                if (cmp <= 0) {
898                    done = true;
899                    break;
900                }
901            }
902
903            if (!done) {
904                ++numDroppable;
905            }
906        }
907
908        if (numDroppable > 0) {
909            mMediaData.removeItemsAt(0, numDroppable);
910
911            if (mMediaData.size() < 5) {
912                resumeIfNecessary();
913            }
914        }
915    }
916
917    return err;
918}
919
920static size_t parseNALSize(size_t nalLengthSize, const uint8_t *data) {
921    switch (nalLengthSize) {
922        case 1:
923            return *data;
924        case 2:
925            return U16_AT(data);
926        case 3:
927            return ((size_t)data[0] << 16) | U16_AT(&data[1]);
928        case 4:
929            return U32_AT(data);
930    }
931
932    // This cannot happen, mNALLengthSize springs to life by adding 1 to
933    // a 2-bit integer.
934    TRESPASS();
935
936    return 0;
937}
938
939status_t FragmentedMP4Parser::makeAccessUnit(
940        TrackInfo *info,
941        const SampleInfo &sample,
942        const MediaDataInfo &mdatInfo,
943        sp<ABuffer> *accessUnit) {
944    if (sample.mSampleDescIndex < 1
945            || sample.mSampleDescIndex > info->mSampleDescs.size()) {
946        return ERROR_MALFORMED;
947    }
948
949    int64_t presentationTimeUs =
950        1000000ll * sample.mPresentationTime / info->mMediaTimeScale;
951
952    const SampleDescription &sampleDesc =
953        info->mSampleDescs.itemAt(sample.mSampleDescIndex - 1);
954
955    size_t nalLengthSize;
956    if (!sampleDesc.mFormat->findSize("nal-length-size", &nalLengthSize)) {
957        *accessUnit = new ABuffer(sample.mSize);
958
959        memcpy((*accessUnit)->data(),
960               mdatInfo.mBuffer->data() + (sample.mOffset - mdatInfo.mOffset),
961               sample.mSize);
962
963        (*accessUnit)->meta()->setInt64("timeUs", presentationTimeUs);
964        return OK;
965    }
966
967    const uint8_t *srcPtr =
968        mdatInfo.mBuffer->data() + (sample.mOffset - mdatInfo.mOffset);
969
970    for (int i = 0; i < 2 ; ++i) {
971        size_t srcOffset = 0;
972        size_t dstOffset = 0;
973
974        while (srcOffset < sample.mSize) {
975            if (srcOffset + nalLengthSize > sample.mSize) {
976                return ERROR_MALFORMED;
977            }
978
979            size_t nalSize = parseNALSize(nalLengthSize, &srcPtr[srcOffset]);
980            srcOffset += nalLengthSize;
981
982            if (srcOffset + nalSize > sample.mSize) {
983                return ERROR_MALFORMED;
984            }
985
986            if (i == 1) {
987                memcpy((*accessUnit)->data() + dstOffset,
988                       "\x00\x00\x00\x01",
989                       4);
990
991                memcpy((*accessUnit)->data() + dstOffset + 4,
992                       srcPtr + srcOffset,
993                       nalSize);
994            }
995
996            srcOffset += nalSize;
997            dstOffset += nalSize + 4;
998        }
999
1000        if (i == 0) {
1001            (*accessUnit) = new ABuffer(dstOffset);
1002            (*accessUnit)->meta()->setInt64(
1003                    "timeUs", presentationTimeUs);
1004        }
1005    }
1006
1007    return OK;
1008}
1009
1010status_t FragmentedMP4Parser::need(size_t size) {
1011    if (!fitsContainer(size)) {
1012        return -EINVAL;
1013    }
1014
1015    if (size <= mBuffer->size()) {
1016        return OK;
1017    }
1018
1019    sp<AMessage> msg = new AMessage(kWhatReadMore, id());
1020    msg->setSize("needed", size - mBuffer->size());
1021    msg->post();
1022
1023    // ALOGV("need(%d) returning -EAGAIN, only have %d", size, mBuffer->size());
1024
1025    return -EAGAIN;
1026}
1027
1028void FragmentedMP4Parser::enter(off64_t offset, uint32_t type, uint64_t size) {
1029    Container container;
1030    container.mOffset = offset;
1031    container.mType = type;
1032    container.mExtendsToEOF = (size == 0);
1033    container.mBytesRemaining = size;
1034
1035    mStack.push(container);
1036}
1037
1038bool FragmentedMP4Parser::fitsContainer(uint64_t size) const {
1039    CHECK(!mStack.isEmpty());
1040    const Container &container = mStack.itemAt(mStack.size() - 1);
1041
1042    return container.mExtendsToEOF || size <= container.mBytesRemaining;
1043}
1044
1045uint16_t FragmentedMP4Parser::readU16(size_t offset) {
1046    CHECK_LE(offset + 2, mBuffer->size());
1047
1048    const uint8_t *ptr = mBuffer->data() + offset;
1049    return (ptr[0] << 8) | ptr[1];
1050}
1051
1052uint32_t FragmentedMP4Parser::readU32(size_t offset) {
1053    CHECK_LE(offset + 4, mBuffer->size());
1054
1055    const uint8_t *ptr = mBuffer->data() + offset;
1056    return (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3];
1057}
1058
1059uint64_t FragmentedMP4Parser::readU64(size_t offset) {
1060    return (((uint64_t)readU32(offset)) << 32) | readU32(offset + 4);
1061}
1062
1063void FragmentedMP4Parser::skip(off_t distance) {
1064    CHECK(!mStack.isEmpty());
1065    for (size_t i = mStack.size(); i-- > 0;) {
1066        Container *container = &mStack.editItemAt(i);
1067        if (!container->mExtendsToEOF) {
1068            CHECK_LE(distance, (off_t)container->mBytesRemaining);
1069
1070            container->mBytesRemaining -= distance;
1071
1072            if (container->mBytesRemaining == 0) {
1073                ALOGV("%sleaving box of type '%s'",
1074                        IndentString(mStack.size() - 1),
1075                        Fourcc2String(container->mType));
1076
1077#if 0
1078                if (container->mType == FOURCC('s', 't', 's', 'd')) {
1079                    TrackInfo *trackInfo = editTrack(mCurrentTrackID);
1080                    for (size_t i = 0;
1081                            i < trackInfo->mSampleDescs.size(); ++i) {
1082                        ALOGI("format #%d: %s",
1083                              i,
1084                              trackInfo->mSampleDescs.itemAt(i)
1085                                .mFormat->debugString().c_str());
1086                    }
1087                }
1088#endif
1089
1090                if (container->mType == FOURCC('s', 't', 'b', 'l')) {
1091                    TrackInfo *trackInfo = editTrack(mCurrentTrackID);
1092
1093                    trackInfo->mStaticFragment->signalCompletion();
1094
1095                    CHECK(trackInfo->mFragments.empty());
1096                    trackInfo->mFragments.push_back(trackInfo->mStaticFragment);
1097                    trackInfo->mStaticFragment.clear();
1098                } else if (container->mType == FOURCC('t', 'r', 'a', 'f')) {
1099                    TrackInfo *trackInfo =
1100                        editTrack(mTrackFragmentHeaderInfo.mTrackID);
1101
1102                    const sp<TrackFragment> &fragment =
1103                        *--trackInfo->mFragments.end();
1104
1105                    static_cast<DynamicTrackFragment *>(
1106                            fragment.get())->signalCompletion();
1107                } else if (container->mType == FOURCC('m', 'o', 'o', 'v')) {
1108                    mDoneWithMoov = true;
1109                }
1110
1111                container = NULL;
1112                mStack.removeItemsAt(i);
1113            }
1114        }
1115    }
1116
1117    if (distance < (off_t)mBuffer->size()) {
1118        mBuffer->setRange(mBuffer->offset() + distance, mBuffer->size() - distance);
1119        mBufferPos += distance;
1120        return;
1121    }
1122
1123    mBuffer->setRange(0, 0);
1124    mBufferPos += distance;
1125}
1126
1127status_t FragmentedMP4Parser::parseTrackHeader(
1128        uint32_t type, size_t offset, uint64_t size) {
1129    if (offset + 4 > size) {
1130        return -EINVAL;
1131    }
1132
1133    uint32_t flags = readU32(offset);
1134
1135    uint32_t version = flags >> 24;
1136    flags &= 0xffffff;
1137
1138    uint32_t trackID;
1139    uint64_t duration;
1140
1141    if (version == 1) {
1142        if (offset + 36 > size) {
1143            return -EINVAL;
1144        }
1145
1146        trackID = readU32(offset + 20);
1147        duration = readU64(offset + 28);
1148
1149        offset += 36;
1150    } else if (version == 0) {
1151        if (offset + 24 > size) {
1152            return -EINVAL;
1153        }
1154
1155        trackID = readU32(offset + 12);
1156        duration = readU32(offset + 20);
1157
1158        offset += 24;
1159    } else {
1160        return -EINVAL;
1161    }
1162
1163    TrackInfo *info = editTrack(trackID, true /* createIfNecessary */);
1164    info->mFlags = flags;
1165    info->mDuration = duration;
1166    if (info->mDuration == 0xffffffff) {
1167        // ffmpeg sets this to -1, which is incorrect.
1168        info->mDuration = 0;
1169    }
1170
1171    info->mStaticFragment = new StaticTrackFragment;
1172
1173    mCurrentTrackID = trackID;
1174
1175    return OK;
1176}
1177
1178status_t FragmentedMP4Parser::parseMediaHeader(
1179        uint32_t type, size_t offset, uint64_t size) {
1180    if (offset + 4 > size) {
1181        return -EINVAL;
1182    }
1183
1184    uint32_t versionAndFlags = readU32(offset);
1185
1186    if (versionAndFlags & 0xffffff) {
1187        return ERROR_MALFORMED;
1188    }
1189
1190    uint32_t version = versionAndFlags >> 24;
1191
1192    TrackInfo *info = editTrack(mCurrentTrackID);
1193
1194    if (version == 1) {
1195        if (offset + 4 + 32 > size) {
1196            return -EINVAL;
1197        }
1198        info->mMediaTimeScale = U32_AT(mBuffer->data() + offset + 20);
1199    } else if (version == 0) {
1200        if (offset + 4 + 20 > size) {
1201            return -EINVAL;
1202        }
1203        info->mMediaTimeScale = U32_AT(mBuffer->data() + offset + 12);
1204    } else {
1205        return ERROR_MALFORMED;
1206    }
1207
1208    return OK;
1209}
1210
1211status_t FragmentedMP4Parser::parseMediaHandler(
1212        uint32_t type, size_t offset, uint64_t size) {
1213    if (offset + 12 > size) {
1214        return -EINVAL;
1215    }
1216
1217    if (readU32(offset) != 0) {
1218        return -EINVAL;
1219    }
1220
1221    uint32_t handlerType = readU32(offset + 8);
1222
1223    switch (handlerType) {
1224        case FOURCC('v', 'i', 'd', 'e'):
1225        case FOURCC('s', 'o', 'u', 'n'):
1226        case FOURCC('h', 'i', 'n', 't'):
1227        case FOURCC('m', 'e', 't', 'a'):
1228            break;
1229
1230        default:
1231            return -EINVAL;
1232    }
1233
1234    editTrack(mCurrentTrackID)->mMediaHandlerType = handlerType;
1235
1236    return OK;
1237}
1238
1239status_t FragmentedMP4Parser::parseVisualSampleEntry(
1240        uint32_t type, size_t offset, uint64_t size) {
1241    if (offset + 78 > size) {
1242        return -EINVAL;
1243    }
1244
1245    TrackInfo *trackInfo = editTrack(mCurrentTrackID);
1246
1247    trackInfo->mSampleDescs.push();
1248    SampleDescription *sampleDesc =
1249        &trackInfo->mSampleDescs.editItemAt(
1250                trackInfo->mSampleDescs.size() - 1);
1251
1252    sampleDesc->mType = type;
1253    sampleDesc->mDataRefIndex = readU16(offset + 6);
1254
1255    sp<AMessage> format = new AMessage;
1256
1257    switch (type) {
1258        case FOURCC('a', 'v', 'c', '1'):
1259            format->setString("mime", MEDIA_MIMETYPE_VIDEO_AVC);
1260            break;
1261        case FOURCC('m', 'p', '4', 'v'):
1262            format->setString("mime", MEDIA_MIMETYPE_VIDEO_MPEG4);
1263            break;
1264        case FOURCC('s', '2', '6', '3'):
1265        case FOURCC('h', '2', '6', '3'):
1266        case FOURCC('H', '2', '6', '3'):
1267            format->setString("mime", MEDIA_MIMETYPE_VIDEO_H263);
1268            break;
1269        default:
1270            format->setString("mime", "application/octet-stream");
1271            break;
1272    }
1273
1274    format->setInt32("width", readU16(offset + 8 + 16));
1275    format->setInt32("height", readU16(offset + 8 + 18));
1276
1277    sampleDesc->mFormat = format;
1278
1279    return OK;
1280}
1281
1282status_t FragmentedMP4Parser::parseAudioSampleEntry(
1283        uint32_t type, size_t offset, uint64_t size) {
1284    if (offset + 28 > size) {
1285        return -EINVAL;
1286    }
1287
1288    TrackInfo *trackInfo = editTrack(mCurrentTrackID);
1289
1290    trackInfo->mSampleDescs.push();
1291    SampleDescription *sampleDesc =
1292        &trackInfo->mSampleDescs.editItemAt(
1293                trackInfo->mSampleDescs.size() - 1);
1294
1295    sampleDesc->mType = type;
1296    sampleDesc->mDataRefIndex = readU16(offset + 6);
1297
1298    sp<AMessage> format = new AMessage;
1299
1300    format->setInt32("channel-count", readU16(offset + 8 + 8));
1301    format->setInt32("sample-size", readU16(offset + 8 + 10));
1302    format->setInt32("sample-rate", readU32(offset + 8 + 16) / 65536.0f);
1303
1304    switch (type) {
1305        case FOURCC('m', 'p', '4', 'a'):
1306            format->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
1307            break;
1308
1309        case FOURCC('s', 'a', 'm', 'r'):
1310            format->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
1311            format->setInt32("channel-count", 1);
1312            format->setInt32("sample-rate", 8000);
1313            break;
1314
1315        case FOURCC('s', 'a', 'w', 'b'):
1316            format->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
1317            format->setInt32("channel-count", 1);
1318            format->setInt32("sample-rate", 16000);
1319            break;
1320        default:
1321            format->setString("mime", "application/octet-stream");
1322            break;
1323    }
1324
1325    sampleDesc->mFormat = format;
1326
1327    return OK;
1328}
1329
1330static void addCodecSpecificData(
1331        const sp<AMessage> &format, int32_t index,
1332        const void *data, size_t size,
1333        bool insertStartCode = false) {
1334    sp<ABuffer> csd = new ABuffer(insertStartCode ? size + 4 : size);
1335
1336    memcpy(csd->data() + (insertStartCode ? 4 : 0), data, size);
1337
1338    if (insertStartCode) {
1339        memcpy(csd->data(), "\x00\x00\x00\x01", 4);
1340    }
1341
1342    csd->meta()->setInt32("csd", true);
1343    csd->meta()->setInt64("timeUs", 0ll);
1344
1345    format->setBuffer(StringPrintf("csd-%d", index).c_str(), csd);
1346}
1347
1348status_t FragmentedMP4Parser::parseSampleSizes(
1349        uint32_t type, size_t offset, uint64_t size) {
1350    return editTrack(mCurrentTrackID)->mStaticFragment->parseSampleSizes(
1351            this, type, offset, size);
1352}
1353
1354status_t FragmentedMP4Parser::parseCompactSampleSizes(
1355        uint32_t type, size_t offset, uint64_t size) {
1356    return editTrack(mCurrentTrackID)->mStaticFragment->parseCompactSampleSizes(
1357            this, type, offset, size);
1358}
1359
1360status_t FragmentedMP4Parser::parseSampleToChunk(
1361        uint32_t type, size_t offset, uint64_t size) {
1362    return editTrack(mCurrentTrackID)->mStaticFragment->parseSampleToChunk(
1363            this, type, offset, size);
1364}
1365
1366status_t FragmentedMP4Parser::parseChunkOffsets(
1367        uint32_t type, size_t offset, uint64_t size) {
1368    return editTrack(mCurrentTrackID)->mStaticFragment->parseChunkOffsets(
1369            this, type, offset, size);
1370}
1371
1372status_t FragmentedMP4Parser::parseChunkOffsets64(
1373        uint32_t type, size_t offset, uint64_t size) {
1374    return editTrack(mCurrentTrackID)->mStaticFragment->parseChunkOffsets64(
1375            this, type, offset, size);
1376}
1377
1378status_t FragmentedMP4Parser::parseAVCCodecSpecificData(
1379        uint32_t type, size_t offset, uint64_t size) {
1380    TrackInfo *trackInfo = editTrack(mCurrentTrackID);
1381
1382    SampleDescription *sampleDesc =
1383        &trackInfo->mSampleDescs.editItemAt(
1384                trackInfo->mSampleDescs.size() - 1);
1385
1386    if (sampleDesc->mType != FOURCC('a', 'v', 'c', '1')) {
1387        return -EINVAL;
1388    }
1389
1390    const uint8_t *ptr = mBuffer->data() + offset;
1391
1392    size -= offset;
1393    offset = 0;
1394
1395    if (size < 7 || ptr[0] != 0x01) {
1396        return ERROR_MALFORMED;
1397    }
1398
1399    sampleDesc->mFormat->setSize("nal-length-size", 1 + (ptr[4] & 3));
1400
1401    size_t numSPS = ptr[5] & 31;
1402
1403    ptr += 6;
1404    size -= 6;
1405
1406    for (size_t i = 0; i < numSPS; ++i) {
1407        if (size < 2) {
1408            return ERROR_MALFORMED;
1409        }
1410
1411        size_t length = U16_AT(ptr);
1412
1413        ptr += 2;
1414        size -= 2;
1415
1416        if (size < length) {
1417            return ERROR_MALFORMED;
1418        }
1419
1420        addCodecSpecificData(
1421                sampleDesc->mFormat, i, ptr, length,
1422                true /* insertStartCode */);
1423
1424        ptr += length;
1425        size -= length;
1426    }
1427
1428    if (size < 1) {
1429        return ERROR_MALFORMED;
1430    }
1431
1432    size_t numPPS = *ptr;
1433    ++ptr;
1434    --size;
1435
1436    for (size_t i = 0; i < numPPS; ++i) {
1437        if (size < 2) {
1438            return ERROR_MALFORMED;
1439        }
1440
1441        size_t length = U16_AT(ptr);
1442
1443        ptr += 2;
1444        size -= 2;
1445
1446        if (size < length) {
1447            return ERROR_MALFORMED;
1448        }
1449
1450        addCodecSpecificData(
1451                sampleDesc->mFormat, numSPS + i, ptr, length,
1452                true /* insertStartCode */);
1453
1454        ptr += length;
1455        size -= length;
1456    }
1457
1458    return OK;
1459}
1460
1461status_t FragmentedMP4Parser::parseESDSCodecSpecificData(
1462        uint32_t type, size_t offset, uint64_t size) {
1463    TrackInfo *trackInfo = editTrack(mCurrentTrackID);
1464
1465    SampleDescription *sampleDesc =
1466        &trackInfo->mSampleDescs.editItemAt(
1467                trackInfo->mSampleDescs.size() - 1);
1468
1469    if (sampleDesc->mType != FOURCC('m', 'p', '4', 'a')
1470            && sampleDesc->mType != FOURCC('m', 'p', '4', 'v')) {
1471        return -EINVAL;
1472    }
1473
1474    const uint8_t *ptr = mBuffer->data() + offset;
1475
1476    size -= offset;
1477    offset = 0;
1478
1479    if (size < 4) {
1480        return -EINVAL;
1481    }
1482
1483    if (U32_AT(ptr) != 0) {
1484        return -EINVAL;
1485    }
1486
1487    ptr += 4;
1488    size -=4;
1489
1490    ESDS esds(ptr, size);
1491
1492    uint8_t objectTypeIndication;
1493    if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) {
1494        return ERROR_MALFORMED;
1495    }
1496
1497    const uint8_t *csd;
1498    size_t csd_size;
1499    if (esds.getCodecSpecificInfo(
1500                (const void **)&csd, &csd_size) != OK) {
1501        return ERROR_MALFORMED;
1502    }
1503
1504    addCodecSpecificData(sampleDesc->mFormat, 0, csd, csd_size);
1505
1506    if (sampleDesc->mType != FOURCC('m', 'p', '4', 'a')) {
1507        return OK;
1508    }
1509
1510    if (csd_size == 0) {
1511        // There's no further information, i.e. no codec specific data
1512        // Let's assume that the information provided in the mpeg4 headers
1513        // is accurate and hope for the best.
1514
1515        return OK;
1516    }
1517
1518    if (csd_size < 2) {
1519        return ERROR_MALFORMED;
1520    }
1521
1522    uint32_t objectType = csd[0] >> 3;
1523
1524    if (objectType == 31) {
1525        return ERROR_UNSUPPORTED;
1526    }
1527
1528    uint32_t freqIndex = (csd[0] & 7) << 1 | (csd[1] >> 7);
1529    int32_t sampleRate = 0;
1530    int32_t numChannels = 0;
1531    if (freqIndex == 15) {
1532        if (csd_size < 5) {
1533            return ERROR_MALFORMED;
1534        }
1535
1536        sampleRate = (csd[1] & 0x7f) << 17
1537                        | csd[2] << 9
1538                        | csd[3] << 1
1539                        | (csd[4] >> 7);
1540
1541        numChannels = (csd[4] >> 3) & 15;
1542    } else {
1543        static uint32_t kSamplingRate[] = {
1544            96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
1545            16000, 12000, 11025, 8000, 7350
1546        };
1547
1548        if (freqIndex == 13 || freqIndex == 14) {
1549            return ERROR_MALFORMED;
1550        }
1551
1552        sampleRate = kSamplingRate[freqIndex];
1553        numChannels = (csd[1] >> 3) & 15;
1554    }
1555
1556    if (numChannels == 0) {
1557        return ERROR_UNSUPPORTED;
1558    }
1559
1560    sampleDesc->mFormat->setInt32("sample-rate", sampleRate);
1561    sampleDesc->mFormat->setInt32("channel-count", numChannels);
1562
1563    return OK;
1564}
1565
1566status_t FragmentedMP4Parser::parseMediaData(
1567        uint32_t type, size_t offset, uint64_t size) {
1568    ALOGV("skipping 'mdat' chunk at offsets 0x%08lx-0x%08llx.",
1569          mBufferPos + offset, mBufferPos + size);
1570
1571    sp<ABuffer> buffer = new ABuffer(size - offset);
1572    memcpy(buffer->data(), mBuffer->data() + offset, size - offset);
1573
1574    mMediaData.push();
1575    MediaDataInfo *info = &mMediaData.editItemAt(mMediaData.size() - 1);
1576    info->mBuffer = buffer;
1577    info->mOffset = mBufferPos + offset;
1578
1579    if (mMediaData.size() > 10) {
1580        ALOGV("suspending for now.");
1581        mSuspended = true;
1582    }
1583
1584    return OK;
1585}
1586
1587status_t FragmentedMP4Parser::parseSegmentIndex(
1588        uint32_t type, size_t offset, uint64_t size) {
1589    ALOGV("sidx box type %d, offset %d, size %d", type, int(offset), int(size));
1590//    AString sidxstr;
1591//    hexdump(mBuffer->data() + offset, size, 0 /* indent */, &sidxstr);
1592//    ALOGV("raw sidx:");
1593//    ALOGV("%s", sidxstr.c_str());
1594    if (offset + 12 > size) {
1595        return -EINVAL;
1596    }
1597
1598    uint32_t flags = readU32(offset);
1599
1600    uint32_t version = flags >> 24;
1601    flags &= 0xffffff;
1602
1603    ALOGV("sidx version %d", version);
1604
1605    uint32_t referenceId = readU32(offset + 4);
1606    uint32_t timeScale = readU32(offset + 8);
1607    ALOGV("sidx refid/timescale: %d/%d", referenceId, timeScale);
1608
1609    uint64_t earliestPresentationTime;
1610    uint64_t firstOffset;
1611
1612    offset += 12;
1613
1614    if (version == 0) {
1615        if (offset + 8 > size) {
1616            return -EINVAL;
1617        }
1618        earliestPresentationTime = readU32(offset);
1619        firstOffset = readU32(offset + 4);
1620        offset += 8;
1621    } else {
1622        if (offset + 16 > size) {
1623            return -EINVAL;
1624        }
1625        earliestPresentationTime = readU64(offset);
1626        firstOffset = readU64(offset + 8);
1627        offset += 16;
1628    }
1629    ALOGV("sidx pres/off: %Ld/%Ld", earliestPresentationTime, firstOffset);
1630
1631    if (offset + 4 > size) {
1632        return -EINVAL;
1633    }
1634    if (readU16(offset) != 0) { // reserved
1635        return -EINVAL;
1636    }
1637    int32_t referenceCount = readU16(offset + 2);
1638    offset += 4;
1639    ALOGV("refcount: %d", referenceCount);
1640
1641    if (offset + referenceCount * 12 > size) {
1642        return -EINVAL;
1643    }
1644
1645    TrackInfo *info = editTrack(mCurrentTrackID);
1646    uint64_t total_duration = 0;
1647    for (int i = 0; i < referenceCount; i++) {
1648        uint32_t d1 = readU32(offset);
1649        uint32_t d2 = readU32(offset + 4);
1650        uint32_t d3 = readU32(offset + 8);
1651
1652        if (d1 & 0x80000000) {
1653            ALOGW("sub-sidx boxes not supported yet");
1654        }
1655        bool sap = d3 & 0x80000000;
1656        bool saptype = d3 >> 28;
1657        if (!sap || saptype > 2) {
1658            ALOGW("not a stream access point, or unsupported type");
1659        }
1660        total_duration += d2;
1661        offset += 12;
1662        ALOGV(" item %d, %08x %08x %08x", i, d1, d2, d3);
1663        SidxEntry se;
1664        se.mSize = d1 & 0x7fffffff;
1665        se.mDurationUs = 1000000LL * d2 / timeScale;
1666        info->mSidx.add(se);
1667    }
1668
1669    info->mSidxDuration = total_duration * 1000000 / timeScale;
1670    ALOGV("duration: %lld", info->mSidxDuration);
1671    return OK;
1672}
1673
1674status_t FragmentedMP4Parser::parseTrackExtends(
1675        uint32_t type, size_t offset, uint64_t size) {
1676    if (offset + 24 > size) {
1677        return -EINVAL;
1678    }
1679
1680    if (readU32(offset) != 0) {
1681        return -EINVAL;
1682    }
1683
1684    uint32_t trackID = readU32(offset + 4);
1685
1686    TrackInfo *info = editTrack(trackID, true /* createIfNecessary */);
1687    info->mDefaultSampleDescriptionIndex = readU32(offset + 8);
1688    info->mDefaultSampleDuration = readU32(offset + 12);
1689    info->mDefaultSampleSize = readU32(offset + 16);
1690    info->mDefaultSampleFlags = readU32(offset + 20);
1691
1692    return OK;
1693}
1694
1695FragmentedMP4Parser::TrackInfo *FragmentedMP4Parser::editTrack(
1696        uint32_t trackID, bool createIfNecessary) {
1697    ssize_t i = mTracks.indexOfKey(trackID);
1698
1699    if (i >= 0) {
1700        return &mTracks.editValueAt(i);
1701    }
1702
1703    if (!createIfNecessary) {
1704        return NULL;
1705    }
1706
1707    TrackInfo info;
1708    info.mTrackID = trackID;
1709    info.mFlags = 0;
1710    info.mDuration = 0xffffffff;
1711    info.mSidxDuration = 0;
1712    info.mMediaTimeScale = 0;
1713    info.mMediaHandlerType = 0;
1714    info.mDefaultSampleDescriptionIndex = 0;
1715    info.mDefaultSampleDuration = 0;
1716    info.mDefaultSampleSize = 0;
1717    info.mDefaultSampleFlags = 0;
1718
1719    info.mDecodingTime = 0;
1720
1721    mTracks.add(trackID, info);
1722    return &mTracks.editValueAt(mTracks.indexOfKey(trackID));
1723}
1724
1725status_t FragmentedMP4Parser::parseTrackFragmentHeader(
1726        uint32_t type, size_t offset, uint64_t size) {
1727    if (offset + 8 > size) {
1728        return -EINVAL;
1729    }
1730
1731    uint32_t flags = readU32(offset);
1732
1733    if (flags & 0xff000000) {
1734        return -EINVAL;
1735    }
1736
1737    mTrackFragmentHeaderInfo.mFlags = flags;
1738
1739    mTrackFragmentHeaderInfo.mTrackID = readU32(offset + 4);
1740    offset += 8;
1741
1742    if (flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent) {
1743        if (offset + 8 > size) {
1744            return -EINVAL;
1745        }
1746
1747        mTrackFragmentHeaderInfo.mBaseDataOffset = readU64(offset);
1748        offset += 8;
1749    }
1750
1751    if (flags & TrackFragmentHeaderInfo::kSampleDescriptionIndexPresent) {
1752        if (offset + 4 > size) {
1753            return -EINVAL;
1754        }
1755
1756        mTrackFragmentHeaderInfo.mSampleDescriptionIndex = readU32(offset);
1757        offset += 4;
1758    }
1759
1760    if (flags & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
1761        if (offset + 4 > size) {
1762            return -EINVAL;
1763        }
1764
1765        mTrackFragmentHeaderInfo.mDefaultSampleDuration = readU32(offset);
1766        offset += 4;
1767    }
1768
1769    if (flags & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
1770        if (offset + 4 > size) {
1771            return -EINVAL;
1772        }
1773
1774        mTrackFragmentHeaderInfo.mDefaultSampleSize = readU32(offset);
1775        offset += 4;
1776    }
1777
1778    if (flags & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
1779        if (offset + 4 > size) {
1780            return -EINVAL;
1781        }
1782
1783        mTrackFragmentHeaderInfo.mDefaultSampleFlags = readU32(offset);
1784        offset += 4;
1785    }
1786
1787    if (!(flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent)) {
1788        // This should point to the position of the first byte of the
1789        // enclosing 'moof' container for the first track and
1790        // the end of the data of the preceding fragment for subsequent
1791        // tracks.
1792
1793        CHECK_GE(mStack.size(), 2u);
1794
1795        mTrackFragmentHeaderInfo.mBaseDataOffset =
1796            mStack.itemAt(mStack.size() - 2).mOffset;
1797
1798        // XXX TODO: This does not do the right thing for the 2nd and
1799        // subsequent tracks yet.
1800    }
1801
1802    mTrackFragmentHeaderInfo.mDataOffset =
1803        mTrackFragmentHeaderInfo.mBaseDataOffset;
1804
1805    TrackInfo *trackInfo = editTrack(mTrackFragmentHeaderInfo.mTrackID);
1806
1807    if (trackInfo->mFragments.empty()
1808            || (*trackInfo->mFragments.begin())->complete()) {
1809        trackInfo->mFragments.push_back(new DynamicTrackFragment);
1810    }
1811
1812    return OK;
1813}
1814
1815status_t FragmentedMP4Parser::parseTrackFragmentRun(
1816        uint32_t type, size_t offset, uint64_t size) {
1817    if (offset + 8 > size) {
1818        return -EINVAL;
1819    }
1820
1821    enum {
1822        kDataOffsetPresent                  = 0x01,
1823        kFirstSampleFlagsPresent            = 0x04,
1824        kSampleDurationPresent              = 0x100,
1825        kSampleSizePresent                  = 0x200,
1826        kSampleFlagsPresent                 = 0x400,
1827        kSampleCompositionTimeOffsetPresent = 0x800,
1828    };
1829
1830    uint32_t flags = readU32(offset);
1831
1832    if (flags & 0xff000000) {
1833        return -EINVAL;
1834    }
1835
1836    if ((flags & kFirstSampleFlagsPresent) && (flags & kSampleFlagsPresent)) {
1837        // These two shall not be used together.
1838        return -EINVAL;
1839    }
1840
1841    uint32_t sampleCount = readU32(offset + 4);
1842    offset += 8;
1843
1844    uint64_t dataOffset = mTrackFragmentHeaderInfo.mDataOffset;
1845
1846    uint32_t firstSampleFlags = 0;
1847
1848    if (flags & kDataOffsetPresent) {
1849        if (offset + 4 > size) {
1850            return -EINVAL;
1851        }
1852
1853        int32_t dataOffsetDelta = (int32_t)readU32(offset);
1854
1855        dataOffset = mTrackFragmentHeaderInfo.mBaseDataOffset + dataOffsetDelta;
1856
1857        offset += 4;
1858    }
1859
1860    if (flags & kFirstSampleFlagsPresent) {
1861        if (offset + 4 > size) {
1862            return -EINVAL;
1863        }
1864
1865        firstSampleFlags = readU32(offset);
1866        offset += 4;
1867    }
1868
1869    TrackInfo *info = editTrack(mTrackFragmentHeaderInfo.mTrackID);
1870
1871    if (info == NULL) {
1872        return -EINVAL;
1873    }
1874
1875    uint32_t sampleDuration = 0, sampleSize = 0, sampleFlags = 0,
1876             sampleCtsOffset = 0;
1877
1878    size_t bytesPerSample = 0;
1879    if (flags & kSampleDurationPresent) {
1880        bytesPerSample += 4;
1881    } else if (mTrackFragmentHeaderInfo.mFlags
1882            & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
1883        sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration;
1884    } else {
1885        sampleDuration = info->mDefaultSampleDuration;
1886    }
1887
1888    if (flags & kSampleSizePresent) {
1889        bytesPerSample += 4;
1890    } else if (mTrackFragmentHeaderInfo.mFlags
1891            & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
1892        sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
1893    } else {
1894        sampleSize = info->mDefaultSampleSize;
1895    }
1896
1897    if (flags & kSampleFlagsPresent) {
1898        bytesPerSample += 4;
1899    } else if (mTrackFragmentHeaderInfo.mFlags
1900            & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
1901        sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
1902    } else {
1903        sampleFlags = info->mDefaultSampleFlags;
1904    }
1905
1906    if (flags & kSampleCompositionTimeOffsetPresent) {
1907        bytesPerSample += 4;
1908    } else {
1909        sampleCtsOffset = 0;
1910    }
1911
1912    if (offset + sampleCount * bytesPerSample > size) {
1913        return -EINVAL;
1914    }
1915
1916    uint32_t sampleDescIndex =
1917        (mTrackFragmentHeaderInfo.mFlags
1918            & TrackFragmentHeaderInfo::kSampleDescriptionIndexPresent)
1919            ? mTrackFragmentHeaderInfo.mSampleDescriptionIndex
1920            : info->mDefaultSampleDescriptionIndex;
1921
1922    for (uint32_t i = 0; i < sampleCount; ++i) {
1923        if (flags & kSampleDurationPresent) {
1924            sampleDuration = readU32(offset);
1925            offset += 4;
1926        }
1927
1928        if (flags & kSampleSizePresent) {
1929            sampleSize = readU32(offset);
1930            offset += 4;
1931        }
1932
1933        if (flags & kSampleFlagsPresent) {
1934            sampleFlags = readU32(offset);
1935            offset += 4;
1936        }
1937
1938        if (flags & kSampleCompositionTimeOffsetPresent) {
1939            sampleCtsOffset = readU32(offset);
1940            offset += 4;
1941        }
1942
1943        ALOGV("adding sample at offset 0x%08llx, size %u, duration %u, "
1944              "sampleDescIndex=%u, flags 0x%08x",
1945                dataOffset, sampleSize, sampleDuration,
1946                sampleDescIndex,
1947                (flags & kFirstSampleFlagsPresent) && i == 0
1948                    ? firstSampleFlags : sampleFlags);
1949
1950        const sp<TrackFragment> &fragment = *--info->mFragments.end();
1951
1952        uint32_t decodingTime = info->mDecodingTime;
1953        info->mDecodingTime += sampleDuration;
1954        uint32_t presentationTime = decodingTime + sampleCtsOffset;
1955
1956        static_cast<DynamicTrackFragment *>(
1957                fragment.get())->addSample(
1958                    dataOffset,
1959                    sampleSize,
1960                    presentationTime,
1961                    sampleDescIndex,
1962                    ((flags & kFirstSampleFlagsPresent) && i == 0)
1963                        ? firstSampleFlags : sampleFlags);
1964
1965        dataOffset += sampleSize;
1966    }
1967
1968    mTrackFragmentHeaderInfo.mDataOffset = dataOffset;
1969
1970    return OK;
1971}
1972
1973void FragmentedMP4Parser::copyBuffer(
1974        sp<ABuffer> *dst, size_t offset, uint64_t size, size_t extra) const {
1975    sp<ABuffer> buf = new ABuffer(size + extra);
1976    memcpy(buf->data(), mBuffer->data() + offset, size);
1977
1978    *dst = buf;
1979}
1980
1981}  // namespace android
1982