blob: 68508426267641cf6302eefb7c6e7a8a2ce92d2b [file] [log] [blame]
Andreas Huber84066782011-08-16 09:34:26 -07001/*
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 "Parser"
19#include <utils/Log.h>
20
21#include "Parser.h"
22#include "TrackFragment.h"
23
24#include "ESDS.h"
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#include "../NuPlayerStreamListener.h"
35
36namespace android {
37
38static const char *Fourcc2String(uint32_t fourcc) {
39 static char buffer[5];
40 buffer[4] = '\0';
41 buffer[0] = fourcc >> 24;
42 buffer[1] = (fourcc >> 16) & 0xff;
43 buffer[2] = (fourcc >> 8) & 0xff;
44 buffer[3] = fourcc & 0xff;
45
46 return buffer;
47}
48
49static const char *IndentString(size_t n) {
50 static const char kSpace[] = " ";
51 return kSpace + sizeof(kSpace) - 2 * n - 1;
52}
53
54// static
55const Parser::DispatchEntry Parser::kDispatchTable[] = {
56 { FOURCC('m', 'o', 'o', 'v'), 0, NULL },
57 { FOURCC('t', 'r', 'a', 'k'), FOURCC('m', 'o', 'o', 'v'), NULL },
58 { FOURCC('u', 'd', 't', 'a'), FOURCC('t', 'r', 'a', 'k'), NULL },
59 { FOURCC('u', 'd', 't', 'a'), FOURCC('m', 'o', 'o', 'v'), NULL },
60 { FOURCC('m', 'e', 't', 'a'), FOURCC('u', 'd', 't', 'a'), NULL },
61 { FOURCC('i', 'l', 's', 't'), FOURCC('m', 'e', 't', 'a'), NULL },
62
63 { FOURCC('t', 'k', 'h', 'd'), FOURCC('t', 'r', 'a', 'k'),
64 &Parser::parseTrackHeader
65 },
66
67 { FOURCC('m', 'v', 'e', 'x'), FOURCC('m', 'o', 'o', 'v'), NULL },
68
69 { FOURCC('t', 'r', 'e', 'x'), FOURCC('m', 'v', 'e', 'x'),
70 &Parser::parseTrackExtends
71 },
72
73 { FOURCC('e', 'd', 't', 's'), FOURCC('t', 'r', 'a', 'k'), NULL },
74 { FOURCC('m', 'd', 'i', 'a'), FOURCC('t', 'r', 'a', 'k'), NULL },
75
76 { FOURCC('m', 'd', 'h', 'd'), FOURCC('m', 'd', 'i', 'a'),
77 &Parser::parseMediaHeader
78 },
79
80 { FOURCC('h', 'd', 'l', 'r'), FOURCC('m', 'd', 'i', 'a'),
81 &Parser::parseMediaHandler
82 },
83
84 { FOURCC('m', 'i', 'n', 'f'), FOURCC('m', 'd', 'i', 'a'), NULL },
85 { FOURCC('d', 'i', 'n', 'f'), FOURCC('m', 'i', 'n', 'f'), NULL },
86 { FOURCC('s', 't', 'b', 'l'), FOURCC('m', 'i', 'n', 'f'), NULL },
87 { FOURCC('s', 't', 's', 'd'), FOURCC('s', 't', 'b', 'l'), NULL },
88
89 { FOURCC('s', 't', 's', 'z'), FOURCC('s', 't', 'b', 'l'),
90 &Parser::parseSampleSizes },
91
92 { FOURCC('s', 't', 'z', '2'), FOURCC('s', 't', 'b', 'l'),
93 &Parser::parseCompactSampleSizes },
94
95 { FOURCC('s', 't', 's', 'c'), FOURCC('s', 't', 'b', 'l'),
96 &Parser::parseSampleToChunk },
97
98 { FOURCC('s', 't', 'c', 'o'), FOURCC('s', 't', 'b', 'l'),
99 &Parser::parseChunkOffsets },
100
101 { FOURCC('c', 'o', '6', '4'), FOURCC('s', 't', 'b', 'l'),
102 &Parser::parseChunkOffsets64 },
103
104 { FOURCC('a', 'v', 'c', 'C'), FOURCC('a', 'v', 'c', '1'),
105 &Parser::parseAVCCodecSpecificData },
106
107 { FOURCC('e', 's', 'd', 's'), FOURCC('m', 'p', '4', 'a'),
108 &Parser::parseESDSCodecSpecificData },
109
110 { FOURCC('e', 's', 'd', 's'), FOURCC('m', 'p', '4', 'v'),
111 &Parser::parseESDSCodecSpecificData },
112
113 { FOURCC('m', 'd', 'a', 't'), 0, &Parser::parseMediaData },
114
115 { FOURCC('m', 'o', 'o', 'f'), 0, NULL },
116 { FOURCC('t', 'r', 'a', 'f'), FOURCC('m', 'o', 'o', 'f'), NULL },
117
118 { FOURCC('t', 'f', 'h', 'd'), FOURCC('t', 'r', 'a', 'f'),
119 &Parser::parseTrackFragmentHeader
120 },
121 { FOURCC('t', 'r', 'u', 'n'), FOURCC('t', 'r', 'a', 'f'),
122 &Parser::parseTrackFragmentRun
123 },
124
125 { FOURCC('m', 'f', 'r', 'a'), 0, NULL },
126};
127
128struct FileSource : public Parser::Source {
129 FileSource(const char *filename)
130 : mFile(fopen(filename, "rb")) {
131 CHECK(mFile != NULL);
132 }
133
134 virtual ssize_t readAt(off64_t offset, void *data, size_t size) {
135 fseek(mFile, offset, SEEK_SET);
136 return fread(data, 1, size, mFile);
137 }
138
139 private:
140 FILE *mFile;
141
142 DISALLOW_EVIL_CONSTRUCTORS(FileSource);
143};
144
145Parser::Parser()
146 : mBufferPos(0),
Andreas Huberc7708552012-08-09 16:24:54 -0700147 mSuspended(false),
148 mFinalResult(OK) {
Andreas Huber84066782011-08-16 09:34:26 -0700149}
150
151Parser::~Parser() {
152}
153
154void Parser::start(const char *filename) {
155 sp<AMessage> msg = new AMessage(kWhatStart, id());
156 msg->setObject("source", new FileSource(filename));
157 msg->post();
158}
159
160void Parser::start(const sp<Source> &source) {
161 sp<AMessage> msg = new AMessage(kWhatStart, id());
162 msg->setObject("source", source);
163 msg->post();
164}
165
166sp<AMessage> Parser::getFormat(bool audio) {
167 sp<AMessage> msg = new AMessage(kWhatGetFormat, id());
168 msg->setInt32("audio", audio);
169
170 sp<AMessage> response;
171 status_t err = msg->postAndAwaitResponse(&response);
172
173 if (err != OK) {
174 return NULL;
175 }
176
177 if (response->findInt32("err", &err) && err != OK) {
178 return NULL;
179 }
180
181 sp<AMessage> format;
182 CHECK(response->findMessage("format", &format));
183
184 ALOGV("returning format %s", format->debugString().c_str());
185 return format;
186}
187
188status_t Parser::dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit) {
189 sp<AMessage> msg = new AMessage(kWhatDequeueAccessUnit, id());
190 msg->setInt32("audio", audio);
191
192 sp<AMessage> response;
193 status_t err = msg->postAndAwaitResponse(&response);
194
195 if (err != OK) {
196 return err;
197 }
198
199 if (response->findInt32("err", &err) && err != OK) {
200 return err;
201 }
202
203 CHECK(response->findBuffer("accessUnit", accessUnit));
204
205 return OK;
206}
207
208ssize_t Parser::findTrack(bool wantAudio) const {
209 for (size_t i = 0; i < mTracks.size(); ++i) {
210 const TrackInfo *info = &mTracks.valueAt(i);
211
212 bool isAudio =
213 info->mMediaHandlerType == FOURCC('s', 'o', 'u', 'n');
214
215 bool isVideo =
216 info->mMediaHandlerType == FOURCC('v', 'i', 'd', 'e');
217
218 if ((wantAudio && isAudio) || (!wantAudio && !isAudio)) {
219 if (info->mSampleDescs.empty()) {
220 break;
221 }
222
223 return i;
224 }
225 }
226
227 return -EWOULDBLOCK;
228}
229
230void Parser::onMessageReceived(const sp<AMessage> &msg) {
231 switch (msg->what()) {
232 case kWhatStart:
233 {
234 sp<RefBase> obj;
235 CHECK(msg->findObject("source", &obj));
236
237 mSource = static_cast<Source *>(obj.get());
238
239 mBuffer = new ABuffer(512 * 1024);
240 mBuffer->setRange(0, 0);
241
242 enter(0, 0);
243
244 (new AMessage(kWhatProceed, id()))->post();
245 break;
246 }
247
248 case kWhatProceed:
249 {
250 CHECK(!mSuspended);
251
252 status_t err = onProceed();
253
254 if (err == OK) {
255 if (!mSuspended) {
256 msg->post();
257 }
258 } else if (err != -EAGAIN) {
259 ALOGE("onProceed returned error %d", err);
260 }
261
262 break;
263 }
264
265 case kWhatReadMore:
266 {
267 size_t needed;
268 CHECK(msg->findSize("needed", &needed));
269
270 memmove(mBuffer->base(), mBuffer->data(), mBuffer->size());
271 mBufferPos += mBuffer->offset();
272 mBuffer->setRange(0, mBuffer->size());
273
274 size_t maxBytesToRead = mBuffer->capacity() - mBuffer->size();
Andreas Huberb9787142012-08-09 09:15:48 -0700275
276 if (maxBytesToRead < needed) {
277 ALOGI("resizing buffer.");
278
279 sp<ABuffer> newBuffer =
280 new ABuffer((mBuffer->size() + needed + 1023) & ~1023);
281 memcpy(newBuffer->data(), mBuffer->data(), mBuffer->size());
282 newBuffer->setRange(0, mBuffer->size());
283
284 mBuffer = newBuffer;
285 maxBytesToRead = mBuffer->capacity() - mBuffer->size();
286 }
287
Andreas Huber84066782011-08-16 09:34:26 -0700288 CHECK_GE(maxBytesToRead, needed);
289
290 ssize_t n = mSource->readAt(
291 mBufferPos + mBuffer->size(),
292 mBuffer->data() + mBuffer->size(), needed);
293
294 if (n < (ssize_t)needed) {
295 ALOGI("%s", "Reached EOF");
Andreas Huberc7708552012-08-09 16:24:54 -0700296 if (n < 0) {
297 mFinalResult = n;
298 } else if (n == 0) {
299 mFinalResult = ERROR_END_OF_STREAM;
300 } else {
301 mFinalResult = ERROR_IO;
302 }
Andreas Huber84066782011-08-16 09:34:26 -0700303 } else {
304 mBuffer->setRange(0, mBuffer->size() + n);
305 (new AMessage(kWhatProceed, id()))->post();
306 }
307
308 break;
309 }
310
311 case kWhatGetFormat:
312 {
313 int32_t wantAudio;
314 CHECK(msg->findInt32("audio", &wantAudio));
315
316 status_t err = -EWOULDBLOCK;
317 sp<AMessage> response = new AMessage;
318
319 ssize_t trackIndex = findTrack(wantAudio);
320
321 if (trackIndex < 0) {
322 err = trackIndex;
323 } else {
324 TrackInfo *info = &mTracks.editValueAt(trackIndex);
325
326 response->setMessage(
327 "format", info->mSampleDescs.itemAt(0).mFormat);
328
329 err = OK;
330 }
331
332 response->setInt32("err", err);
333
334 uint32_t replyID;
335 CHECK(msg->senderAwaitsResponse(&replyID));
336
337 response->postReply(replyID);
338 break;
339 }
340
341 case kWhatDequeueAccessUnit:
342 {
343 int32_t wantAudio;
344 CHECK(msg->findInt32("audio", &wantAudio));
345
346 status_t err = -EWOULDBLOCK;
347 sp<AMessage> response = new AMessage;
348
349 ssize_t trackIndex = findTrack(wantAudio);
350
351 if (trackIndex < 0) {
352 err = trackIndex;
353 } else {
354 sp<ABuffer> accessUnit;
355 err = onDequeueAccessUnit(trackIndex, &accessUnit);
356
357 if (err == OK) {
358 response->setBuffer("accessUnit", accessUnit);
359 }
360 }
361
362 response->setInt32("err", err);
363
364 uint32_t replyID;
365 CHECK(msg->senderAwaitsResponse(&replyID));
366
367 response->postReply(replyID);
368 break;
369 }
370
371 default:
372 TRESPASS();
373 }
374}
375
376status_t Parser::onProceed() {
377 status_t err;
378
379 if ((err = need(8)) != OK) {
380 return err;
381 }
382
383 uint64_t size = readU32(0);
384 uint32_t type = readU32(4);
385
386 size_t offset = 8;
387
388 if (size == 1) {
389 if ((err = need(16)) != OK) {
390 return err;
391 }
392
393 size = readU64(offset);
394 offset += 8;
395 }
396
397 uint8_t userType[16];
398
399 if (type == FOURCC('u', 'u', 'i', 'd')) {
400 if ((err = need(offset + 16)) != OK) {
401 return err;
402 }
403
404 memcpy(userType, mBuffer->data() + offset, 16);
405 offset += 16;
406 }
407
408 CHECK(!mStack.isEmpty());
409 uint32_t ptype = mStack.itemAt(mStack.size() - 1).mType;
410
411 static const size_t kNumDispatchers =
412 sizeof(kDispatchTable) / sizeof(kDispatchTable[0]);
413
414 size_t i;
415 for (i = 0; i < kNumDispatchers; ++i) {
416 if (kDispatchTable[i].mType == type
417 && kDispatchTable[i].mParentType == ptype) {
418 break;
419 }
420 }
421
422 // SampleEntry boxes are container boxes that start with a variable
423 // amount of data depending on the media handler type.
424 // We don't look inside 'hint' type SampleEntry boxes.
425
426 bool isSampleEntryBox =
427 (ptype == FOURCC('s', 't', 's', 'd'))
428 && editTrack(mCurrentTrackID)->mMediaHandlerType
429 != FOURCC('h', 'i', 'n', 't');
430
431 if ((i < kNumDispatchers && kDispatchTable[i].mHandler == 0)
432 || isSampleEntryBox || ptype == FOURCC('i', 'l', 's', 't')) {
433 // This is a container box.
434 if (type == FOURCC('m', 'e', 't', 'a')) {
435 if ((err = need(offset + 4)) < OK) {
436 return err;
437 }
438
439 if (readU32(offset) != 0) {
440 return -EINVAL;
441 }
442
443 offset += 4;
444 } else if (type == FOURCC('s', 't', 's', 'd')) {
445 if ((err = need(offset + 8)) < OK) {
446 return err;
447 }
448
449 if (readU32(offset) != 0) {
450 return -EINVAL;
451 }
452
453 if (readU32(offset + 4) == 0) {
454 // We need at least some entries.
455 return -EINVAL;
456 }
457
458 offset += 8;
459 } else if (isSampleEntryBox) {
460 size_t headerSize;
461
462 switch (editTrack(mCurrentTrackID)->mMediaHandlerType) {
463 case FOURCC('v', 'i', 'd', 'e'):
464 {
465 // 8 bytes SampleEntry + 70 bytes VisualSampleEntry
466 headerSize = 78;
467 break;
468 }
469
470 case FOURCC('s', 'o', 'u', 'n'):
471 {
472 // 8 bytes SampleEntry + 20 bytes AudioSampleEntry
473 headerSize = 28;
474 break;
475 }
476
477 case FOURCC('m', 'e', 't', 'a'):
478 {
479 headerSize = 8; // 8 bytes SampleEntry
480 break;
481 }
482
483 default:
484 TRESPASS();
485 }
486
487 if (offset + headerSize > size) {
488 return -EINVAL;
489 }
490
491 if ((err = need(offset + headerSize)) != OK) {
492 return err;
493 }
494
495 switch (editTrack(mCurrentTrackID)->mMediaHandlerType) {
496 case FOURCC('v', 'i', 'd', 'e'):
497 {
498 err = parseVisualSampleEntry(
499 type, offset, offset + headerSize);
500 break;
501 }
502
503 case FOURCC('s', 'o', 'u', 'n'):
504 {
505 err = parseAudioSampleEntry(
506 type, offset, offset + headerSize);
507 break;
508 }
509
510 case FOURCC('m', 'e', 't', 'a'):
511 {
512 err = OK;
513 break;
514 }
515
516 default:
517 TRESPASS();
518 }
519
520 if (err != OK) {
521 return err;
522 }
523
524 offset += headerSize;
525 }
526
527 skip(offset);
528
529 ALOGV("%sentering box of type '%s'",
530 IndentString(mStack.size()), Fourcc2String(type));
531
532 enter(type, size - offset);
533 } else {
534 if (!fitsContainer(size)) {
535 return -EINVAL;
536 }
537
538 if (i < kNumDispatchers && kDispatchTable[i].mHandler != 0) {
539 // We have a handler for this box type.
540
541 if ((err = need(size)) != OK) {
542 return err;
543 }
544
545 ALOGV("%sparsing box of type '%s'",
546 IndentString(mStack.size()), Fourcc2String(type));
547
548 if ((err = (this->*kDispatchTable[i].mHandler)(
549 type, offset, size)) != OK) {
550 return err;
551 }
552 } else {
553 // Unknown box type
554
555 ALOGV("%sskipping box of type '%s', size %llu",
556 IndentString(mStack.size()),
557 Fourcc2String(type), size);
558
559 }
560
561 skip(size);
562 }
563
564 return OK;
565}
566
567// static
568int Parser::CompareSampleLocation(
569 const SampleInfo &sample, const MediaDataInfo &mdatInfo) {
570 if (sample.mOffset + sample.mSize < mdatInfo.mOffset) {
571 return -1;
572 }
573
574 if (sample.mOffset >= mdatInfo.mOffset + mdatInfo.mBuffer->size()) {
575 return 1;
576 }
577
578 // Otherwise make sure the sample is completely contained within this
579 // media data block.
580
581 CHECK_GE(sample.mOffset, mdatInfo.mOffset);
582
583 CHECK_LE(sample.mOffset + sample.mSize,
584 mdatInfo.mOffset + mdatInfo.mBuffer->size());
585
586 return 0;
587}
588
589void Parser::resumeIfNecessary() {
590 if (!mSuspended) {
591 return;
592 }
593
594 ALOGI("resuming.");
595
596 mSuspended = false;
597 (new AMessage(kWhatProceed, id()))->post();
598}
599
600status_t Parser::getSample(
601 TrackInfo *info, sp<TrackFragment> *fragment, SampleInfo *sampleInfo) {
602 for (;;) {
603 if (info->mFragments.empty()) {
Andreas Huberc7708552012-08-09 16:24:54 -0700604 if (mFinalResult != OK) {
605 return mFinalResult;
606 }
607
Andreas Huber84066782011-08-16 09:34:26 -0700608 resumeIfNecessary();
609 return -EWOULDBLOCK;
610 }
611
612 *fragment = *info->mFragments.begin();
613
614 status_t err = (*fragment)->getSample(sampleInfo);
615
616 if (err == OK) {
617 return OK;
618 } else if (err != ERROR_END_OF_STREAM) {
619 return err;
620 }
621
622 // Really, end of this fragment...
623
624 info->mFragments.erase(info->mFragments.begin());
625 }
626}
627
628status_t Parser::onDequeueAccessUnit(
629 size_t trackIndex, sp<ABuffer> *accessUnit) {
630 TrackInfo *info = &mTracks.editValueAt(trackIndex);
631
632 sp<TrackFragment> fragment;
633 SampleInfo sampleInfo;
634 status_t err = getSample(info, &fragment, &sampleInfo);
635
636 if (err == -EWOULDBLOCK) {
637 resumeIfNecessary();
638 return err;
639 } else if (err != OK) {
640 return err;
641 }
642
643 err = -EWOULDBLOCK;
644
645 bool checkDroppable = false;
646
647 for (size_t i = 0; i < mMediaData.size(); ++i) {
648 const MediaDataInfo &mdatInfo = mMediaData.itemAt(i);
649
650 int cmp = CompareSampleLocation(sampleInfo, mdatInfo);
651
652 if (cmp < 0) {
653 return -EPIPE;
654 } else if (cmp == 0) {
655 if (i > 0) {
656 checkDroppable = true;
657 }
658
659 err = makeAccessUnit(info, sampleInfo, mdatInfo, accessUnit);
660 break;
661 }
662 }
663
664 if (err != OK) {
665 return err;
666 }
667
668 fragment->advance();
669
670 if (!mMediaData.empty() && checkDroppable) {
671 size_t numDroppable = 0;
672 bool done = false;
673
674 for (size_t i = 0; !done && i < mMediaData.size(); ++i) {
675 const MediaDataInfo &mdatInfo = mMediaData.itemAt(i);
676
677 for (size_t j = 0; j < mTracks.size(); ++j) {
678 TrackInfo *info = &mTracks.editValueAt(j);
679
680 sp<TrackFragment> fragment;
681 SampleInfo sampleInfo;
682 err = getSample(info, &fragment, &sampleInfo);
683
684 if (err != OK) {
685 done = true;
686 break;
687 }
688
689 int cmp = CompareSampleLocation(sampleInfo, mdatInfo);
690
691 if (cmp <= 0) {
692 done = true;
693 break;
694 }
695 }
696
697 if (!done) {
698 ++numDroppable;
699 }
700 }
701
702 if (numDroppable > 0) {
703 mMediaData.removeItemsAt(0, numDroppable);
704
705 if (mMediaData.size() < 5) {
706 resumeIfNecessary();
707 }
708 }
709 }
710
711 return err;
712}
713
714static size_t parseNALSize(size_t nalLengthSize, const uint8_t *data) {
715 switch (nalLengthSize) {
716 case 1:
717 return *data;
718 case 2:
719 return U16_AT(data);
720 case 3:
721 return ((size_t)data[0] << 16) | U16_AT(&data[1]);
722 case 4:
723 return U32_AT(data);
724 }
725
726 // This cannot happen, mNALLengthSize springs to life by adding 1 to
727 // a 2-bit integer.
728 TRESPASS();
729
730 return 0;
731}
732
733status_t Parser::makeAccessUnit(
734 TrackInfo *info,
735 const SampleInfo &sample,
736 const MediaDataInfo &mdatInfo,
737 sp<ABuffer> *accessUnit) {
738 if (sample.mSampleDescIndex < 1
739 || sample.mSampleDescIndex > info->mSampleDescs.size()) {
740 return ERROR_MALFORMED;
741 }
742
743 int64_t presentationTimeUs =
744 1000000ll * sample.mPresentationTime / info->mMediaTimeScale;
745
746 const SampleDescription &sampleDesc =
747 info->mSampleDescs.itemAt(sample.mSampleDescIndex - 1);
748
749 size_t nalLengthSize;
750 if (!sampleDesc.mFormat->findSize("nal-length-size", &nalLengthSize)) {
751 *accessUnit = new ABuffer(sample.mSize);
752
753 memcpy((*accessUnit)->data(),
754 mdatInfo.mBuffer->data() + (sample.mOffset - mdatInfo.mOffset),
755 sample.mSize);
756
757 (*accessUnit)->meta()->setInt64("timeUs", presentationTimeUs);
758 return OK;
759 }
760
761 const uint8_t *srcPtr =
762 mdatInfo.mBuffer->data() + (sample.mOffset - mdatInfo.mOffset);
763
764 for (int i = 0; i < 2 ; ++i) {
765 size_t srcOffset = 0;
766 size_t dstOffset = 0;
767
768 while (srcOffset < sample.mSize) {
769 if (srcOffset + nalLengthSize > sample.mSize) {
770 return ERROR_MALFORMED;
771 }
772
773 size_t nalSize = parseNALSize(nalLengthSize, &srcPtr[srcOffset]);
774 srcOffset += nalLengthSize;
775
776 if (srcOffset + nalSize > sample.mSize) {
777 return ERROR_MALFORMED;
778 }
779
780 if (i == 1) {
781 memcpy((*accessUnit)->data() + dstOffset,
782 "\x00\x00\x00\x01",
783 4);
784
785 memcpy((*accessUnit)->data() + dstOffset + 4,
786 srcPtr + srcOffset,
787 nalSize);
788 }
789
790 srcOffset += nalSize;
791 dstOffset += nalSize + 4;
792 }
793
794 if (i == 0) {
795 (*accessUnit) = new ABuffer(dstOffset);
796 (*accessUnit)->meta()->setInt64(
797 "timeUs", presentationTimeUs);
798 }
799 }
800
801 return OK;
802}
803
804status_t Parser::need(size_t size) {
805 if (!fitsContainer(size)) {
806 return -EINVAL;
807 }
808
809 if (size <= mBuffer->size()) {
810 return OK;
811 }
812
813 sp<AMessage> msg = new AMessage(kWhatReadMore, id());
814 msg->setSize("needed", size - mBuffer->size());
815 msg->post();
816
817 // ALOGV("need(%d) returning -EAGAIN, only have %d", size, mBuffer->size());
818
819 return -EAGAIN;
820}
821
822void Parser::enter(uint32_t type, uint64_t size) {
823 Container container;
824 container.mType = type;
825 container.mExtendsToEOF = (size == 0);
826 container.mBytesRemaining = size;
827
828 mStack.push(container);
829}
830
831bool Parser::fitsContainer(uint64_t size) const {
832 CHECK(!mStack.isEmpty());
833 const Container &container = mStack.itemAt(mStack.size() - 1);
834
835 return container.mExtendsToEOF || size <= container.mBytesRemaining;
836}
837
838uint16_t Parser::readU16(size_t offset) {
839 CHECK_LE(offset + 2, mBuffer->size());
840
841 const uint8_t *ptr = mBuffer->data() + offset;
842 return (ptr[0] << 8) | ptr[1];
843}
844
845uint32_t Parser::readU32(size_t offset) {
846 CHECK_LE(offset + 4, mBuffer->size());
847
848 const uint8_t *ptr = mBuffer->data() + offset;
849 return (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3];
850}
851
852uint64_t Parser::readU64(size_t offset) {
853 return (((uint64_t)readU32(offset)) << 32) | readU32(offset + 4);
854}
855
856void Parser::skip(off_t distance) {
857 CHECK(!mStack.isEmpty());
858 for (size_t i = mStack.size(); i-- > 0;) {
859 Container *container = &mStack.editItemAt(i);
860 if (!container->mExtendsToEOF) {
861 CHECK_LE(distance, (off_t)container->mBytesRemaining);
862
863 container->mBytesRemaining -= distance;
864
865 if (container->mBytesRemaining == 0) {
866 ALOGV("%sleaving box of type '%s'",
867 IndentString(mStack.size() - 1),
868 Fourcc2String(container->mType));
869
870#if 0
871 if (container->mType == FOURCC('s', 't', 's', 'd')) {
872 TrackInfo *trackInfo = editTrack(mCurrentTrackID);
873 for (size_t i = 0;
874 i < trackInfo->mSampleDescs.size(); ++i) {
875 ALOGI("format #%d: %s",
876 i,
877 trackInfo->mSampleDescs.itemAt(i)
878 .mFormat->debugString().c_str());
879 }
880 }
881#endif
882
883 if (container->mType == FOURCC('s', 't', 'b', 'l')) {
884 TrackInfo *trackInfo = editTrack(mCurrentTrackID);
885
886 trackInfo->mStaticFragment->signalCompletion();
887
888 CHECK(trackInfo->mFragments.empty());
889 trackInfo->mFragments.push_back(trackInfo->mStaticFragment);
890 trackInfo->mStaticFragment.clear();
891 } else if (container->mType == FOURCC('t', 'r', 'a', 'f')) {
892 TrackInfo *trackInfo =
893 editTrack(mTrackFragmentHeaderInfo.mTrackID);
894
895 const sp<TrackFragment> &fragment =
896 *--trackInfo->mFragments.end();
897
898 static_cast<DynamicTrackFragment *>(
899 fragment.get())->signalCompletion();
900 }
901
902 container = NULL;
903 mStack.removeItemsAt(i);
904 }
905 }
906 }
907
908 if (distance < (off_t)mBuffer->size()) {
909 mBuffer->setRange(mBuffer->offset() + distance, mBuffer->size() - distance);
910 mBufferPos += distance;
911 return;
912 }
913
914 mBuffer->setRange(0, 0);
915 mBufferPos += distance;
916}
917
918status_t Parser::parseTrackHeader(
919 uint32_t type, size_t offset, uint64_t size) {
920 if (offset + 4 > size) {
921 return -EINVAL;
922 }
923
924 uint32_t flags = readU32(offset);
925
926 uint32_t version = flags >> 24;
927 flags &= 0xffffff;
928
929 uint32_t trackID;
930 uint64_t duration;
931
932 if (version == 1) {
933 if (offset + 36 > size) {
934 return -EINVAL;
935 }
936
937 trackID = readU32(offset + 20);
938 duration = readU64(offset + 28);
939
940 offset += 36;
941 } else if (version == 0) {
942 if (offset + 24 > size) {
943 return -EINVAL;
944 }
945
946 trackID = readU32(offset + 12);
947 duration = readU32(offset + 20);
948
949 offset += 24;
950 } else {
951 return -EINVAL;
952 }
953
954 TrackInfo *info = editTrack(trackID, true /* createIfNecessary */);
955 info->mFlags = flags;
956 info->mDuration = duration;
957
958 info->mStaticFragment = new StaticTrackFragment;
959
960 mCurrentTrackID = trackID;
961
962 return OK;
963}
964
965status_t Parser::parseMediaHeader(
966 uint32_t type, size_t offset, uint64_t size) {
967 if (offset + 4 > size) {
968 return -EINVAL;
969 }
970
971 uint32_t versionAndFlags = readU32(offset);
972
973 if (versionAndFlags & 0xffffff) {
974 return ERROR_MALFORMED;
975 }
976
977 uint32_t version = versionAndFlags >> 24;
978
979 TrackInfo *info = editTrack(mCurrentTrackID);
980
981 if (version == 1) {
982 if (offset + 4 + 32 > size) {
983 return -EINVAL;
984 }
985 info->mMediaTimeScale = U32_AT(mBuffer->data() + offset + 20);
986 } else if (version == 0) {
987 if (offset + 4 + 20 > size) {
988 return -EINVAL;
989 }
990 info->mMediaTimeScale = U32_AT(mBuffer->data() + offset + 12);
991 } else {
992 return ERROR_MALFORMED;
993 }
994
995 return OK;
996}
997
998status_t Parser::parseMediaHandler(
999 uint32_t type, size_t offset, uint64_t size) {
1000 if (offset + 12 > size) {
1001 return -EINVAL;
1002 }
1003
1004 if (readU32(offset) != 0) {
1005 return -EINVAL;
1006 }
1007
1008 uint32_t handlerType = readU32(offset + 8);
1009
1010 switch (handlerType) {
1011 case FOURCC('v', 'i', 'd', 'e'):
1012 case FOURCC('s', 'o', 'u', 'n'):
1013 case FOURCC('h', 'i', 'n', 't'):
1014 case FOURCC('m', 'e', 't', 'a'):
1015 break;
1016
1017 default:
1018 return -EINVAL;
1019 }
1020
1021 editTrack(mCurrentTrackID)->mMediaHandlerType = handlerType;
1022
1023 return OK;
1024}
1025
1026status_t Parser::parseVisualSampleEntry(
1027 uint32_t type, size_t offset, uint64_t size) {
1028 if (offset + 78 > size) {
1029 return -EINVAL;
1030 }
1031
1032 TrackInfo *trackInfo = editTrack(mCurrentTrackID);
1033
1034 trackInfo->mSampleDescs.push();
1035 SampleDescription *sampleDesc =
1036 &trackInfo->mSampleDescs.editItemAt(
1037 trackInfo->mSampleDescs.size() - 1);
1038
1039 sampleDesc->mType = type;
1040 sampleDesc->mDataRefIndex = readU16(offset + 6);
1041
1042 sp<AMessage> format = new AMessage;
1043
1044 switch (type) {
1045 case FOURCC('a', 'v', 'c', '1'):
1046 format->setString("mime", MEDIA_MIMETYPE_VIDEO_AVC);
1047 break;
1048 case FOURCC('m', 'p', '4', 'v'):
1049 format->setString("mime", MEDIA_MIMETYPE_VIDEO_MPEG4);
1050 break;
Andreas Huberb9787142012-08-09 09:15:48 -07001051 case FOURCC('s', '2', '6', '3'):
1052 case FOURCC('h', '2', '6', '3'):
1053 case FOURCC('H', '2', '6', '3'):
1054 format->setString("mime", MEDIA_MIMETYPE_VIDEO_H263);
1055 break;
Andreas Huber84066782011-08-16 09:34:26 -07001056 default:
1057 format->setString("mime", "application/octet-stream");
1058 break;
1059 }
1060
1061 format->setInt32("width", readU16(offset + 8 + 16));
1062 format->setInt32("height", readU16(offset + 8 + 18));
1063
1064 sampleDesc->mFormat = format;
1065
1066 return OK;
1067}
1068
1069status_t Parser::parseAudioSampleEntry(
1070 uint32_t type, size_t offset, uint64_t size) {
1071 if (offset + 28 > size) {
1072 return -EINVAL;
1073 }
1074
1075 TrackInfo *trackInfo = editTrack(mCurrentTrackID);
1076
1077 trackInfo->mSampleDescs.push();
1078 SampleDescription *sampleDesc =
1079 &trackInfo->mSampleDescs.editItemAt(
1080 trackInfo->mSampleDescs.size() - 1);
1081
1082 sampleDesc->mType = type;
1083 sampleDesc->mDataRefIndex = readU16(offset + 6);
1084
1085 sp<AMessage> format = new AMessage;
1086
1087 format->setInt32("channel-count", readU16(offset + 8 + 8));
1088 format->setInt32("sample-size", readU16(offset + 8 + 10));
1089 format->setInt32("sample-rate", readU32(offset + 8 + 16) / 65536.0f);
1090
1091 switch (type) {
1092 case FOURCC('m', 'p', '4', 'a'):
1093 format->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
1094 break;
Andreas Huberb9787142012-08-09 09:15:48 -07001095
Andreas Huber84066782011-08-16 09:34:26 -07001096 case FOURCC('s', 'a', 'm', 'r'):
1097 format->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
1098 format->setInt32("channel-count", 1);
1099 format->setInt32("sample-rate", 8000);
1100 break;
Andreas Huberb9787142012-08-09 09:15:48 -07001101
Andreas Huber84066782011-08-16 09:34:26 -07001102 case FOURCC('s', 'a', 'w', 'b'):
1103 format->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
1104 format->setInt32("channel-count", 1);
1105 format->setInt32("sample-rate", 16000);
1106 break;
1107 default:
1108 format->setString("mime", "application/octet-stream");
1109 break;
1110 }
1111
1112 sampleDesc->mFormat = format;
1113
1114 return OK;
1115}
1116
1117static void addCodecSpecificData(
1118 const sp<AMessage> &format, int32_t index,
1119 const void *data, size_t size,
1120 bool insertStartCode = false) {
1121 sp<ABuffer> csd = new ABuffer(insertStartCode ? size + 4 : size);
1122
1123 memcpy(csd->data() + (insertStartCode ? 4 : 0), data, size);
1124
1125 if (insertStartCode) {
1126 memcpy(csd->data(), "\x00\x00\x00\x01", 4);
1127 }
1128
1129 csd->meta()->setInt32("csd", true);
1130 csd->meta()->setInt64("timeUs", 0ll);
1131
1132 format->setBuffer(StringPrintf("csd-%d", index).c_str(), csd);
1133}
1134
1135status_t Parser::parseSampleSizes(
1136 uint32_t type, size_t offset, uint64_t size) {
1137 return editTrack(mCurrentTrackID)->mStaticFragment->parseSampleSizes(
1138 this, type, offset, size);
1139}
1140
1141status_t Parser::parseCompactSampleSizes(
1142 uint32_t type, size_t offset, uint64_t size) {
1143 return editTrack(mCurrentTrackID)->mStaticFragment->parseCompactSampleSizes(
1144 this, type, offset, size);
1145}
1146
1147status_t Parser::parseSampleToChunk(
1148 uint32_t type, size_t offset, uint64_t size) {
1149 return editTrack(mCurrentTrackID)->mStaticFragment->parseSampleToChunk(
1150 this, type, offset, size);
1151}
1152
1153status_t Parser::parseChunkOffsets(
1154 uint32_t type, size_t offset, uint64_t size) {
1155 return editTrack(mCurrentTrackID)->mStaticFragment->parseChunkOffsets(
1156 this, type, offset, size);
1157}
1158
1159status_t Parser::parseChunkOffsets64(
1160 uint32_t type, size_t offset, uint64_t size) {
1161 return editTrack(mCurrentTrackID)->mStaticFragment->parseChunkOffsets64(
1162 this, type, offset, size);
1163}
1164
1165status_t Parser::parseAVCCodecSpecificData(
1166 uint32_t type, size_t offset, uint64_t size) {
1167 TrackInfo *trackInfo = editTrack(mCurrentTrackID);
1168
1169 SampleDescription *sampleDesc =
1170 &trackInfo->mSampleDescs.editItemAt(
1171 trackInfo->mSampleDescs.size() - 1);
1172
1173 if (sampleDesc->mType != FOURCC('a', 'v', 'c', '1')) {
1174 return -EINVAL;
1175 }
1176
1177 const uint8_t *ptr = mBuffer->data() + offset;
1178
1179 size -= offset;
1180 offset = 0;
1181
1182 if (size < 7 || ptr[0] != 0x01) {
1183 return ERROR_MALFORMED;
1184 }
1185
1186 sampleDesc->mFormat->setSize("nal-length-size", 1 + (ptr[4] & 3));
1187
1188 size_t numSPS = ptr[5] & 31;
1189
1190 ptr += 6;
1191 size -= 6;
1192
1193 for (size_t i = 0; i < numSPS; ++i) {
1194 if (size < 2) {
1195 return ERROR_MALFORMED;
1196 }
1197
1198 size_t length = U16_AT(ptr);
1199
1200 ptr += 2;
1201 size -= 2;
1202
1203 if (size < length) {
1204 return ERROR_MALFORMED;
1205 }
1206
1207 addCodecSpecificData(
1208 sampleDesc->mFormat, i, ptr, length,
1209 true /* insertStartCode */);
1210
1211 ptr += length;
1212 size -= length;
1213 }
1214
1215 if (size < 1) {
1216 return ERROR_MALFORMED;
1217 }
1218
1219 size_t numPPS = *ptr;
1220 ++ptr;
1221 --size;
1222
1223 for (size_t i = 0; i < numPPS; ++i) {
1224 if (size < 2) {
1225 return ERROR_MALFORMED;
1226 }
1227
1228 size_t length = U16_AT(ptr);
1229
1230 ptr += 2;
1231 size -= 2;
1232
1233 if (size < length) {
1234 return ERROR_MALFORMED;
1235 }
1236
1237 addCodecSpecificData(
1238 sampleDesc->mFormat, numSPS + i, ptr, length,
1239 true /* insertStartCode */);
1240
1241 ptr += length;
1242 size -= length;
1243 }
1244
1245 return OK;
1246}
1247
1248status_t Parser::parseESDSCodecSpecificData(
1249 uint32_t type, size_t offset, uint64_t size) {
1250 TrackInfo *trackInfo = editTrack(mCurrentTrackID);
1251
1252 SampleDescription *sampleDesc =
1253 &trackInfo->mSampleDescs.editItemAt(
1254 trackInfo->mSampleDescs.size() - 1);
1255
1256 if (sampleDesc->mType != FOURCC('m', 'p', '4', 'a')
1257 && sampleDesc->mType != FOURCC('m', 'p', '4', 'v')) {
1258 return -EINVAL;
1259 }
1260
1261 const uint8_t *ptr = mBuffer->data() + offset;
1262
1263 size -= offset;
1264 offset = 0;
1265
1266 if (size < 4) {
1267 return -EINVAL;
1268 }
1269
1270 if (U32_AT(ptr) != 0) {
1271 return -EINVAL;
1272 }
1273
1274 ptr += 4;
1275 size -=4;
1276
1277 ESDS esds(ptr, size);
1278
1279 uint8_t objectTypeIndication;
1280 if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) {
1281 return ERROR_MALFORMED;
1282 }
1283
1284 const uint8_t *csd;
1285 size_t csd_size;
1286 if (esds.getCodecSpecificInfo(
1287 (const void **)&csd, &csd_size) != OK) {
1288 return ERROR_MALFORMED;
1289 }
1290
1291 addCodecSpecificData(sampleDesc->mFormat, 0, csd, csd_size);
1292
1293 if (sampleDesc->mType != FOURCC('m', 'p', '4', 'a')) {
1294 return OK;
1295 }
1296
1297 if (csd_size == 0) {
1298 // There's no further information, i.e. no codec specific data
1299 // Let's assume that the information provided in the mpeg4 headers
1300 // is accurate and hope for the best.
1301
1302 return OK;
1303 }
1304
1305 if (csd_size < 2) {
1306 return ERROR_MALFORMED;
1307 }
1308
1309 uint32_t objectType = csd[0] >> 3;
1310
1311 if (objectType == 31) {
1312 return ERROR_UNSUPPORTED;
1313 }
1314
1315 uint32_t freqIndex = (csd[0] & 7) << 1 | (csd[1] >> 7);
1316 int32_t sampleRate = 0;
1317 int32_t numChannels = 0;
1318 if (freqIndex == 15) {
1319 if (csd_size < 5) {
1320 return ERROR_MALFORMED;
1321 }
1322
1323 sampleRate = (csd[1] & 0x7f) << 17
1324 | csd[2] << 9
1325 | csd[3] << 1
1326 | (csd[4] >> 7);
1327
1328 numChannels = (csd[4] >> 3) & 15;
1329 } else {
1330 static uint32_t kSamplingRate[] = {
1331 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
1332 16000, 12000, 11025, 8000, 7350
1333 };
1334
1335 if (freqIndex == 13 || freqIndex == 14) {
1336 return ERROR_MALFORMED;
1337 }
1338
1339 sampleRate = kSamplingRate[freqIndex];
1340 numChannels = (csd[1] >> 3) & 15;
1341 }
1342
1343 if (numChannels == 0) {
1344 return ERROR_UNSUPPORTED;
1345 }
1346
1347 sampleDesc->mFormat->setInt32("sample-rate", sampleRate);
1348 sampleDesc->mFormat->setInt32("channel-count", numChannels);
1349
1350 return OK;
1351}
1352
1353status_t Parser::parseMediaData(
1354 uint32_t type, size_t offset, uint64_t size) {
1355 ALOGV("skipping 'mdat' chunk at offsets 0x%08lx-0x%08llx.",
1356 mBufferPos + offset, mBufferPos + size);
1357
1358 sp<ABuffer> buffer = new ABuffer(size - offset);
1359 memcpy(buffer->data(), mBuffer->data() + offset, size - offset);
1360
1361 mMediaData.push();
1362 MediaDataInfo *info = &mMediaData.editItemAt(mMediaData.size() - 1);
1363 info->mBuffer = buffer;
1364 info->mOffset = mBufferPos + offset;
1365
1366 if (mMediaData.size() > 10) {
1367 ALOGI("suspending for now.");
1368 mSuspended = true;
1369 }
1370
1371 return OK;
1372}
1373
1374status_t Parser::parseTrackExtends(
1375 uint32_t type, size_t offset, uint64_t size) {
1376 if (offset + 24 > size) {
1377 return -EINVAL;
1378 }
1379
1380 if (readU32(offset) != 0) {
1381 return -EINVAL;
1382 }
1383
1384 uint32_t trackID = readU32(offset + 4);
1385
1386 TrackInfo *info = editTrack(trackID, true /* createIfNecessary */);
1387 info->mDefaultSampleDescriptionIndex = readU32(offset + 8);
1388 info->mDefaultSampleDuration = readU32(offset + 12);
1389 info->mDefaultSampleSize = readU32(offset + 16);
1390 info->mDefaultSampleFlags = readU32(offset + 20);
1391
1392 return OK;
1393}
1394
1395Parser::TrackInfo *Parser::editTrack(
1396 uint32_t trackID, bool createIfNecessary) {
1397 ssize_t i = mTracks.indexOfKey(trackID);
1398
1399 if (i >= 0) {
1400 return &mTracks.editValueAt(i);
1401 }
1402
1403 if (!createIfNecessary) {
1404 return NULL;
1405 }
1406
1407 TrackInfo info;
1408 info.mTrackID = trackID;
1409 info.mFlags = 0;
1410 info.mDuration = 0xffffffff;
1411 info.mMediaTimeScale = 0;
1412 info.mMediaHandlerType = 0;
1413 info.mDefaultSampleDescriptionIndex = 0;
1414 info.mDefaultSampleDuration = 0;
1415 info.mDefaultSampleSize = 0;
1416 info.mDefaultSampleFlags = 0;
1417
1418 info.mDecodingTime = 0;
1419
1420 mTracks.add(trackID, info);
1421 return &mTracks.editValueAt(mTracks.indexOfKey(trackID));
1422}
1423
1424status_t Parser::parseTrackFragmentHeader(
1425 uint32_t type, size_t offset, uint64_t size) {
1426 if (offset + 8 > size) {
1427 return -EINVAL;
1428 }
1429
1430 uint32_t flags = readU32(offset);
1431
1432 if (flags & 0xff000000) {
1433 return -EINVAL;
1434 }
1435
1436 mTrackFragmentHeaderInfo.mFlags = flags;
1437
1438 mTrackFragmentHeaderInfo.mTrackID = readU32(offset + 4);
1439 offset += 8;
1440
1441 if (flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent) {
1442 if (offset + 8 > size) {
1443 return -EINVAL;
1444 }
1445
1446 mTrackFragmentHeaderInfo.mBaseDataOffset = readU64(offset);
1447 offset += 8;
1448 }
1449
1450 if (flags & TrackFragmentHeaderInfo::kSampleDescriptionIndexPresent) {
1451 if (offset + 4 > size) {
1452 return -EINVAL;
1453 }
1454
1455 mTrackFragmentHeaderInfo.mSampleDescriptionIndex = readU32(offset);
1456 offset += 4;
1457 }
1458
1459 if (flags & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
1460 if (offset + 4 > size) {
1461 return -EINVAL;
1462 }
1463
1464 mTrackFragmentHeaderInfo.mDefaultSampleDuration = readU32(offset);
1465 offset += 4;
1466 }
1467
1468 if (flags & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
1469 if (offset + 4 > size) {
1470 return -EINVAL;
1471 }
1472
1473 mTrackFragmentHeaderInfo.mDefaultSampleSize = readU32(offset);
1474 offset += 4;
1475 }
1476
1477 if (flags & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
1478 if (offset + 4 > size) {
1479 return -EINVAL;
1480 }
1481
1482 mTrackFragmentHeaderInfo.mDefaultSampleFlags = readU32(offset);
1483 offset += 4;
1484 }
1485
1486 if (!(flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent)) {
1487 CHECK(!mStack.isEmpty());
1488
1489 // This should point to the start of the data inside the 'mdat' box
1490 // following the current 'moof' box.
1491
1492 mTrackFragmentHeaderInfo.mBaseDataOffset =
1493 mBufferPos + mStack.itemAt(mStack.size() - 1).mBytesRemaining + 8;
1494 }
1495
1496 mTrackFragmentHeaderInfo.mDataOffset =
1497 mTrackFragmentHeaderInfo.mBaseDataOffset;
1498
1499 TrackInfo *trackInfo = editTrack(mTrackFragmentHeaderInfo.mTrackID);
1500
1501 if (trackInfo->mFragments.empty()
1502 || (*trackInfo->mFragments.begin())->complete()) {
1503 trackInfo->mFragments.push_back(new DynamicTrackFragment);
1504 }
1505
1506 return OK;
1507}
1508
1509status_t Parser::parseTrackFragmentRun(
1510 uint32_t type, size_t offset, uint64_t size) {
1511 if (offset + 8 > size) {
1512 return -EINVAL;
1513 }
1514
1515 enum {
1516 kDataOffsetPresent = 0x01,
1517 kFirstSampleFlagsPresent = 0x04,
1518 kSampleDurationPresent = 0x100,
1519 kSampleSizePresent = 0x200,
1520 kSampleFlagsPresent = 0x400,
1521 kSampleCompositionTimeOffsetPresent = 0x800,
1522 };
1523
1524 uint32_t flags = readU32(offset);
1525
1526 if (flags & 0xff000000) {
1527 return -EINVAL;
1528 }
1529
1530 if ((flags & kFirstSampleFlagsPresent) && (flags & kSampleFlagsPresent)) {
1531 // These two shall not be used together.
1532 return -EINVAL;
1533 }
1534
1535 uint32_t sampleCount = readU32(offset + 4);
1536 offset += 8;
1537
1538 uint64_t dataOffset = mTrackFragmentHeaderInfo.mDataOffset;
1539
1540 uint32_t firstSampleFlags = 0;
1541
1542 if (flags & kDataOffsetPresent) {
1543 if (offset + 4 > size) {
1544 return -EINVAL;
1545 }
1546
1547 int32_t dataOffsetDelta = (int32_t)readU32(offset);
1548
1549 dataOffset = mTrackFragmentHeaderInfo.mBaseDataOffset + dataOffsetDelta;
1550
1551 offset += 4;
1552 }
1553
1554 if (flags & kFirstSampleFlagsPresent) {
1555 if (offset + 4 > size) {
1556 return -EINVAL;
1557 }
1558
1559 firstSampleFlags = readU32(offset);
1560 offset += 4;
1561 }
1562
1563 TrackInfo *info = editTrack(mTrackFragmentHeaderInfo.mTrackID);
1564
1565 if (info == NULL) {
1566 return -EINVAL;
1567 }
1568
1569 uint32_t sampleDuration = 0, sampleSize = 0, sampleFlags = 0,
1570 sampleCtsOffset = 0;
1571
1572 size_t bytesPerSample = 0;
1573 if (flags & kSampleDurationPresent) {
1574 bytesPerSample += 4;
1575 } else if (mTrackFragmentHeaderInfo.mFlags
1576 & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
1577 sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration;
1578 } else {
1579 sampleDuration = info->mDefaultSampleDuration;
1580 }
1581
1582 if (flags & kSampleSizePresent) {
1583 bytesPerSample += 4;
1584 } else if (mTrackFragmentHeaderInfo.mFlags
1585 & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
1586 sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
1587 } else {
1588 sampleSize = info->mDefaultSampleSize;
1589 }
1590
1591 if (flags & kSampleFlagsPresent) {
1592 bytesPerSample += 4;
1593 } else if (mTrackFragmentHeaderInfo.mFlags
1594 & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
1595 sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
1596 } else {
1597 sampleFlags = info->mDefaultSampleFlags;
1598 }
1599
1600 if (flags & kSampleCompositionTimeOffsetPresent) {
1601 bytesPerSample += 4;
1602 } else {
1603 sampleCtsOffset = 0;
1604 }
1605
1606 if (offset + sampleCount * bytesPerSample > size) {
1607 return -EINVAL;
1608 }
1609
1610 uint32_t sampleDescIndex =
1611 (mTrackFragmentHeaderInfo.mFlags
1612 & TrackFragmentHeaderInfo::kSampleDescriptionIndexPresent)
1613 ? mTrackFragmentHeaderInfo.mSampleDescriptionIndex
1614 : info->mDefaultSampleDescriptionIndex;
1615
1616 for (uint32_t i = 0; i < sampleCount; ++i) {
1617 if (flags & kSampleDurationPresent) {
1618 sampleDuration = readU32(offset);
1619 offset += 4;
1620 }
1621
1622 if (flags & kSampleSizePresent) {
1623 sampleSize = readU32(offset);
1624 offset += 4;
1625 }
1626
1627 if (flags & kSampleFlagsPresent) {
1628 sampleFlags = readU32(offset);
1629 offset += 4;
1630 }
1631
1632 if (flags & kSampleCompositionTimeOffsetPresent) {
1633 sampleCtsOffset = readU32(offset);
1634 offset += 4;
1635 }
1636
1637 ALOGV("adding sample at offset 0x%08llx, size %u, duration %u, "
1638 "sampleDescIndex=%u, flags 0x%08x",
1639 dataOffset, sampleSize, sampleDuration,
1640 sampleDescIndex,
1641 (flags & kFirstSampleFlagsPresent) && i == 0
1642 ? firstSampleFlags : sampleFlags);
1643
1644 const sp<TrackFragment> &fragment = *--info->mFragments.end();
1645
1646 uint32_t decodingTime = info->mDecodingTime;
1647 info->mDecodingTime += sampleDuration;
1648 uint32_t presentationTime = decodingTime + sampleCtsOffset;
1649
1650 static_cast<DynamicTrackFragment *>(
1651 fragment.get())->addSample(
1652 dataOffset,
1653 sampleSize,
1654 presentationTime,
1655 sampleDescIndex,
1656 ((flags & kFirstSampleFlagsPresent) && i == 0)
1657 ? firstSampleFlags : sampleFlags);
1658
1659 dataOffset += sampleSize;
1660 }
1661
1662 mTrackFragmentHeaderInfo.mDataOffset = dataOffset;
1663
1664 return OK;
1665}
1666
1667void Parser::copyBuffer(
1668 sp<ABuffer> *dst, size_t offset, uint64_t size, size_t extra) const {
1669 sp<ABuffer> buf = new ABuffer(size + extra);
1670 memcpy(buf->data(), mBuffer->data() + offset, size);
1671
1672 *dst = buf;
1673}
1674
1675} // namespace android