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