blob: 3503aaf171104563f33647e8317cf4e33c9cfeb9 [file] [log] [blame]
Andreas Huber20111aa2009-07-14 16:56:47 -07001/*
2 * Copyright (C) 2009 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
Marco Nelissen1e9ee012012-08-28 15:09:49 -070017//#define LOG_NDEBUG 0
Andreas Huber20111aa2009-07-14 16:56:47 -070018#define LOG_TAG "MPEG4Extractor"
19#include <utils/Log.h>
20
Andreas Huber66326a52009-10-23 09:55:10 -070021#include "include/MPEG4Extractor.h"
Andreas Huber89e69da2009-10-13 10:22:55 -070022#include "include/SampleTable.h"
Gloria Wang7a1e3e82011-05-03 15:59:03 -070023#include "include/ESDS.h"
Andreas Huber89e69da2009-10-13 10:22:55 -070024
Andreas Huber20111aa2009-07-14 16:56:47 -070025#include <ctype.h>
26#include <stdint.h>
27#include <stdlib.h>
28#include <string.h>
29
Dave Burkeaeb8fd42012-04-19 00:14:27 -070030#include <media/stagefright/foundation/ABitReader.h>
Jan Olof Svensson0fd28832012-09-26 09:08:11 +020031#include <media/stagefright/foundation/ABuffer.h>
Andreas Huberba529e42010-11-16 15:26:30 -080032#include <media/stagefright/foundation/ADebug.h>
Andreas Hubera0f2bf52011-12-05 11:34:43 -080033#include <media/stagefright/foundation/AMessage.h>
Andreas Huber20111aa2009-07-14 16:56:47 -070034#include <media/stagefright/MediaBuffer.h>
35#include <media/stagefright/MediaBufferGroup.h>
Andreas Huber18291bc2009-09-10 14:13:30 -070036#include <media/stagefright/MediaDefs.h>
Andreas Huber20111aa2009-07-14 16:56:47 -070037#include <media/stagefright/MediaSource.h>
38#include <media/stagefright/MetaData.h>
Andreas Huber20111aa2009-07-14 16:56:47 -070039#include <utils/String8.h>
40
41namespace android {
42
43class MPEG4Source : public MediaSource {
44public:
45 // Caller retains ownership of both "dataSource" and "sampleTable".
Andreas Huber693d2712009-08-14 14:37:10 -070046 MPEG4Source(const sp<MetaData> &format,
47 const sp<DataSource> &dataSource,
Andreas Huber48c948b2009-10-08 10:07:49 -070048 int32_t timeScale,
Marco Nelissen62ad9072013-02-13 09:27:28 -080049 const sp<SampleTable> &sampleTable,
50 Vector<SidxEntry> &sidx,
51 off64_t firstMoofOffset);
Andreas Huber20111aa2009-07-14 16:56:47 -070052
53 virtual status_t start(MetaData *params = NULL);
54 virtual status_t stop();
55
56 virtual sp<MetaData> getFormat();
57
Marco Nelissen62ad9072013-02-13 09:27:28 -080058 virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL);
59 virtual status_t fragmentedRead(MediaBuffer **buffer, const ReadOptions *options = NULL);
Andreas Huber20111aa2009-07-14 16:56:47 -070060
Andreas Huber693d2712009-08-14 14:37:10 -070061protected:
62 virtual ~MPEG4Source();
63
Andreas Huber20111aa2009-07-14 16:56:47 -070064private:
Andreas Huber7b3396a2010-02-12 10:42:02 -080065 Mutex mLock;
66
Andreas Huber20111aa2009-07-14 16:56:47 -070067 sp<MetaData> mFormat;
Andreas Huber693d2712009-08-14 14:37:10 -070068 sp<DataSource> mDataSource;
Andreas Huber20111aa2009-07-14 16:56:47 -070069 int32_t mTimescale;
Andreas Huber693d2712009-08-14 14:37:10 -070070 sp<SampleTable> mSampleTable;
Andreas Huber20111aa2009-07-14 16:56:47 -070071 uint32_t mCurrentSampleIndex;
Marco Nelissen62ad9072013-02-13 09:27:28 -080072 uint32_t mCurrentFragmentIndex;
73 Vector<SidxEntry> &mSegments;
74 off64_t mFirstMoofOffset;
75 off64_t mCurrentMoofOffset;
76 off64_t mNextMoofOffset;
77 uint32_t mCurrentTime;
78 int32_t mLastParsedTrackId;
79 int32_t mTrackId;
Andreas Huber20111aa2009-07-14 16:56:47 -070080
Marco Nelissen5544c662013-04-08 14:30:57 -070081 int32_t mCryptoMode; // passed in from extractor
82 int32_t mDefaultIVSize; // passed in from extractor
83 uint8_t mCryptoKey[16]; // passed in from extractor
84 uint32_t mCurrentAuxInfoType;
85 uint32_t mCurrentAuxInfoTypeParameter;
86 uint32_t mCurrentDefaultSampleInfoSize;
87 uint32_t mCurrentSampleInfoCount;
88 uint32_t mCurrentSampleInfoAllocSize;
89 uint8_t* mCurrentSampleInfoSizes;
90 uint32_t mCurrentSampleInfoOffsetCount;
91 uint32_t mCurrentSampleInfoOffsetsAllocSize;
92 uint64_t* mCurrentSampleInfoOffsets;
93
Andreas Huber20111aa2009-07-14 16:56:47 -070094 bool mIsAVC;
Andreas Huber60640172010-01-12 16:30:44 -080095 size_t mNALLengthSize;
96
Andreas Huber20111aa2009-07-14 16:56:47 -070097 bool mStarted;
98
99 MediaBufferGroup *mGroup;
100
101 MediaBuffer *mBuffer;
Andreas Huber20111aa2009-07-14 16:56:47 -0700102
Andreas Huberdbc03442009-08-19 09:29:34 -0700103 bool mWantsNALFragments;
Andreas Huber20111aa2009-07-14 16:56:47 -0700104
Andreas Huber00242452009-07-28 10:03:13 -0700105 uint8_t *mSrcBuffer;
106
Andreas Huber60640172010-01-12 16:30:44 -0800107 size_t parseNALSize(const uint8_t *data) const;
Marco Nelissen62ad9072013-02-13 09:27:28 -0800108 status_t parseChunk(off64_t *offset);
109 status_t parseTrackFragmentHeader(off64_t offset, off64_t size);
110 status_t parseTrackFragmentRun(off64_t offset, off64_t size);
Marco Nelissen5544c662013-04-08 14:30:57 -0700111 status_t parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size);
112 status_t parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size);
Marco Nelissen62ad9072013-02-13 09:27:28 -0800113
114 struct TrackFragmentHeaderInfo {
115 enum Flags {
116 kBaseDataOffsetPresent = 0x01,
117 kSampleDescriptionIndexPresent = 0x02,
118 kDefaultSampleDurationPresent = 0x08,
119 kDefaultSampleSizePresent = 0x10,
120 kDefaultSampleFlagsPresent = 0x20,
121 kDurationIsEmpty = 0x10000,
122 };
123
124 uint32_t mTrackID;
125 uint32_t mFlags;
126 uint64_t mBaseDataOffset;
127 uint32_t mSampleDescriptionIndex;
128 uint32_t mDefaultSampleDuration;
129 uint32_t mDefaultSampleSize;
130 uint32_t mDefaultSampleFlags;
131
132 uint64_t mDataOffset;
133 };
134 TrackFragmentHeaderInfo mTrackFragmentHeaderInfo;
135
136 struct Sample {
137 off64_t offset;
138 size_t size;
139 uint32_t duration;
Marco Nelissen5544c662013-04-08 14:30:57 -0700140 uint8_t iv[16];
141 Vector<size_t> clearsizes;
142 Vector<size_t> encryptedsizes;
Marco Nelissen62ad9072013-02-13 09:27:28 -0800143 };
144 Vector<Sample> mCurrentSamples;
Andreas Huber60640172010-01-12 16:30:44 -0800145
Andreas Huber20111aa2009-07-14 16:56:47 -0700146 MPEG4Source(const MPEG4Source &);
147 MPEG4Source &operator=(const MPEG4Source &);
148};
149
Andreas Huber50a99762010-01-28 14:27:37 -0800150// This custom data source wraps an existing one and satisfies requests
151// falling entirely within a cached range from the cache while forwarding
152// all remaining requests to the wrapped datasource.
153// This is used to cache the full sampletable metadata for a single track,
154// possibly wrapping multiple times to cover all tracks, i.e.
155// Each MPEG4DataSource caches the sampletable metadata for a single track.
156
157struct MPEG4DataSource : public DataSource {
158 MPEG4DataSource(const sp<DataSource> &source);
159
160 virtual status_t initCheck() const;
James Dongc7fc37a2010-11-16 14:04:54 -0800161 virtual ssize_t readAt(off64_t offset, void *data, size_t size);
162 virtual status_t getSize(off64_t *size);
Andreas Huber50a99762010-01-28 14:27:37 -0800163 virtual uint32_t flags();
164
James Dongc7fc37a2010-11-16 14:04:54 -0800165 status_t setCachedRange(off64_t offset, size_t size);
Andreas Huber50a99762010-01-28 14:27:37 -0800166
167protected:
168 virtual ~MPEG4DataSource();
169
170private:
171 Mutex mLock;
172
173 sp<DataSource> mSource;
James Dongc7fc37a2010-11-16 14:04:54 -0800174 off64_t mCachedOffset;
Andreas Huber50a99762010-01-28 14:27:37 -0800175 size_t mCachedSize;
176 uint8_t *mCache;
177
178 void clearCache();
179
180 MPEG4DataSource(const MPEG4DataSource &);
181 MPEG4DataSource &operator=(const MPEG4DataSource &);
182};
183
184MPEG4DataSource::MPEG4DataSource(const sp<DataSource> &source)
185 : mSource(source),
186 mCachedOffset(0),
187 mCachedSize(0),
188 mCache(NULL) {
189}
190
191MPEG4DataSource::~MPEG4DataSource() {
192 clearCache();
193}
194
195void MPEG4DataSource::clearCache() {
196 if (mCache) {
197 free(mCache);
198 mCache = NULL;
199 }
200
201 mCachedOffset = 0;
202 mCachedSize = 0;
203}
204
205status_t MPEG4DataSource::initCheck() const {
206 return mSource->initCheck();
207}
208
James Dongc7fc37a2010-11-16 14:04:54 -0800209ssize_t MPEG4DataSource::readAt(off64_t offset, void *data, size_t size) {
Andreas Huber50a99762010-01-28 14:27:37 -0800210 Mutex::Autolock autoLock(mLock);
211
212 if (offset >= mCachedOffset
213 && offset + size <= mCachedOffset + mCachedSize) {
214 memcpy(data, &mCache[offset - mCachedOffset], size);
215 return size;
216 }
217
218 return mSource->readAt(offset, data, size);
219}
220
James Dongc7fc37a2010-11-16 14:04:54 -0800221status_t MPEG4DataSource::getSize(off64_t *size) {
Andreas Huber50a99762010-01-28 14:27:37 -0800222 return mSource->getSize(size);
223}
224
225uint32_t MPEG4DataSource::flags() {
226 return mSource->flags();
227}
228
James Dongc7fc37a2010-11-16 14:04:54 -0800229status_t MPEG4DataSource::setCachedRange(off64_t offset, size_t size) {
Andreas Huber50a99762010-01-28 14:27:37 -0800230 Mutex::Autolock autoLock(mLock);
231
232 clearCache();
233
234 mCache = (uint8_t *)malloc(size);
235
236 if (mCache == NULL) {
237 return -ENOMEM;
238 }
239
240 mCachedOffset = offset;
241 mCachedSize = size;
242
243 ssize_t err = mSource->readAt(mCachedOffset, mCache, mCachedSize);
244
245 if (err < (ssize_t)size) {
246 clearCache();
247
248 return ERROR_IO;
249 }
250
251 return OK;
252}
253
254////////////////////////////////////////////////////////////////////////////////
255
Andreas Huber20111aa2009-07-14 16:56:47 -0700256static void hexdump(const void *_data, size_t size) {
257 const uint8_t *data = (const uint8_t *)_data;
258 size_t offset = 0;
259 while (offset < size) {
260 printf("0x%04x ", offset);
261
262 size_t n = size - offset;
263 if (n > 16) {
264 n = 16;
265 }
266
267 for (size_t i = 0; i < 16; ++i) {
268 if (i == 8) {
269 printf(" ");
270 }
271
272 if (offset + i < size) {
273 printf("%02x ", data[offset + i]);
274 } else {
275 printf(" ");
276 }
277 }
278
279 printf(" ");
280
281 for (size_t i = 0; i < n; ++i) {
282 if (isprint(data[offset + i])) {
283 printf("%c", data[offset + i]);
284 } else {
285 printf(".");
286 }
287 }
288
289 printf("\n");
290
291 offset += 16;
292 }
293}
294
Andreas Huber18291bc2009-09-10 14:13:30 -0700295static const char *FourCC2MIME(uint32_t fourcc) {
Andreas Huber20111aa2009-07-14 16:56:47 -0700296 switch (fourcc) {
297 case FOURCC('m', 'p', '4', 'a'):
Andreas Huber18291bc2009-09-10 14:13:30 -0700298 return MEDIA_MIMETYPE_AUDIO_AAC;
Andreas Huber20111aa2009-07-14 16:56:47 -0700299
300 case FOURCC('s', 'a', 'm', 'r'):
Andreas Huber18291bc2009-09-10 14:13:30 -0700301 return MEDIA_MIMETYPE_AUDIO_AMR_NB;
Andreas Huber20111aa2009-07-14 16:56:47 -0700302
Andreas Huber371e2432009-09-09 16:32:59 -0700303 case FOURCC('s', 'a', 'w', 'b'):
Andreas Huber18291bc2009-09-10 14:13:30 -0700304 return MEDIA_MIMETYPE_AUDIO_AMR_WB;
Andreas Huber371e2432009-09-09 16:32:59 -0700305
Andreas Huber20111aa2009-07-14 16:56:47 -0700306 case FOURCC('m', 'p', '4', 'v'):
Andreas Huber18291bc2009-09-10 14:13:30 -0700307 return MEDIA_MIMETYPE_VIDEO_MPEG4;
Andreas Huber20111aa2009-07-14 16:56:47 -0700308
309 case FOURCC('s', '2', '6', '3'):
James Donge071b052010-12-15 15:49:46 -0800310 case FOURCC('h', '2', '6', '3'):
311 case FOURCC('H', '2', '6', '3'):
Andreas Huber18291bc2009-09-10 14:13:30 -0700312 return MEDIA_MIMETYPE_VIDEO_H263;
Andreas Huber20111aa2009-07-14 16:56:47 -0700313
314 case FOURCC('a', 'v', 'c', '1'):
Andreas Huber18291bc2009-09-10 14:13:30 -0700315 return MEDIA_MIMETYPE_VIDEO_AVC;
Andreas Huber20111aa2009-07-14 16:56:47 -0700316
317 default:
Andreas Huberdbc03442009-08-19 09:29:34 -0700318 CHECK(!"should not be here.");
Andreas Huber20111aa2009-07-14 16:56:47 -0700319 return NULL;
320 }
321}
322
Andreas Huber693d2712009-08-14 14:37:10 -0700323MPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
Marco Nelissen62ad9072013-02-13 09:27:28 -0800324 : mSidxDuration(0),
325 mMoofOffset(0),
326 mDataSource(source),
Andreas Huberbdba1f22011-03-03 13:48:41 -0800327 mInitCheck(NO_INIT),
Andreas Huber7be64072010-01-13 11:25:10 -0800328 mHasVideo(false),
Andreas Huber20111aa2009-07-14 16:56:47 -0700329 mFirstTrack(NULL),
Andreas Huber72b8c5a2010-01-19 16:43:53 -0800330 mLastTrack(NULL),
Gloria Wangdcd25ef2010-06-22 13:55:38 -0700331 mFileMetaData(new MetaData),
332 mFirstSINF(NULL),
333 mIsDrm(false) {
Andreas Huber20111aa2009-07-14 16:56:47 -0700334}
335
336MPEG4Extractor::~MPEG4Extractor() {
337 Track *track = mFirstTrack;
338 while (track) {
339 Track *next = track->next;
340
Andreas Huber20111aa2009-07-14 16:56:47 -0700341 delete track;
342 track = next;
343 }
344 mFirstTrack = mLastTrack = NULL;
Gloria Wangdcd25ef2010-06-22 13:55:38 -0700345
346 SINF *sinf = mFirstSINF;
347 while (sinf) {
348 SINF *next = sinf->next;
349 delete sinf->IPMPData;
350 delete sinf;
351 sinf = next;
352 }
353 mFirstSINF = NULL;
Marco Nelissen5544c662013-04-08 14:30:57 -0700354
355 for (size_t i = 0; i < mPssh.size(); i++) {
356 delete [] mPssh[i].data;
357 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700358}
359
Marco Nelissen62ad9072013-02-13 09:27:28 -0800360uint32_t MPEG4Extractor::flags() const {
361 return CAN_PAUSE |
362 ((mMoofOffset == 0 || mSidxEntries.size() != 0) ?
363 (CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK) : 0);
364}
365
Andreas Huber7be64072010-01-13 11:25:10 -0800366sp<MetaData> MPEG4Extractor::getMetaData() {
Andreas Huber7be64072010-01-13 11:25:10 -0800367 status_t err;
368 if ((err = readMetaData()) != OK) {
Andreas Huber72b8c5a2010-01-19 16:43:53 -0800369 return new MetaData;
Andreas Huber7be64072010-01-13 11:25:10 -0800370 }
371
Andreas Huber72b8c5a2010-01-19 16:43:53 -0800372 return mFileMetaData;
Andreas Huber7be64072010-01-13 11:25:10 -0800373}
374
Andreas Huber693d2712009-08-14 14:37:10 -0700375size_t MPEG4Extractor::countTracks() {
Andreas Huber20111aa2009-07-14 16:56:47 -0700376 status_t err;
377 if ((err = readMetaData()) != OK) {
Marco Nelissen5544c662013-04-08 14:30:57 -0700378 ALOGV("MPEG4Extractor::countTracks: no tracks");
Andreas Huber693d2712009-08-14 14:37:10 -0700379 return 0;
Andreas Huber20111aa2009-07-14 16:56:47 -0700380 }
381
Andreas Huber693d2712009-08-14 14:37:10 -0700382 size_t n = 0;
Andreas Huber20111aa2009-07-14 16:56:47 -0700383 Track *track = mFirstTrack;
384 while (track) {
Andreas Huber693d2712009-08-14 14:37:10 -0700385 ++n;
Andreas Huber20111aa2009-07-14 16:56:47 -0700386 track = track->next;
387 }
388
Marco Nelissen5544c662013-04-08 14:30:57 -0700389 ALOGV("MPEG4Extractor::countTracks: %d tracks", n);
Andreas Huber693d2712009-08-14 14:37:10 -0700390 return n;
Andreas Huber20111aa2009-07-14 16:56:47 -0700391}
392
Andreas Huber7e04dcf2009-10-22 13:49:30 -0700393sp<MetaData> MPEG4Extractor::getTrackMetaData(
394 size_t index, uint32_t flags) {
Andreas Huber20111aa2009-07-14 16:56:47 -0700395 status_t err;
396 if ((err = readMetaData()) != OK) {
397 return NULL;
398 }
399
400 Track *track = mFirstTrack;
401 while (index > 0) {
402 if (track == NULL) {
403 return NULL;
404 }
405
406 track = track->next;
407 --index;
408 }
409
Andreas Huber371e2432009-09-09 16:32:59 -0700410 if (track == NULL) {
411 return NULL;
412 }
413
Andreas Huber7e04dcf2009-10-22 13:49:30 -0700414 if ((flags & kIncludeExtensiveMetaData)
415 && !track->includes_expensive_metadata) {
416 track->includes_expensive_metadata = true;
417
418 const char *mime;
419 CHECK(track->meta->findCString(kKeyMIMEType, &mime));
420 if (!strncasecmp("video/", mime, 6)) {
Marco Nelissen62ad9072013-02-13 09:27:28 -0800421 if (mMoofOffset > 0) {
422 int64_t duration;
423 if (track->meta->findInt64(kKeyDuration, &duration)) {
424 // nothing fancy, just pick a frame near 1/4th of the duration
425 track->meta->setInt64(
426 kKeyThumbnailTime, duration / 4);
427 }
428 } else {
429 uint32_t sampleIndex;
430 uint32_t sampleTime;
431 if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK
432 && track->sampleTable->getMetaDataForSample(
433 sampleIndex, NULL /* offset */, NULL /* size */,
434 &sampleTime) == OK) {
435 track->meta->setInt64(
436 kKeyThumbnailTime,
437 ((int64_t)sampleTime * 1000000) / track->timescale);
438 }
Andreas Huber7e04dcf2009-10-22 13:49:30 -0700439 }
440 }
441 }
442
Andreas Huber20111aa2009-07-14 16:56:47 -0700443 return track->meta;
444}
445
446status_t MPEG4Extractor::readMetaData() {
Andreas Huberbdba1f22011-03-03 13:48:41 -0800447 if (mInitCheck != NO_INIT) {
448 return mInitCheck;
Andreas Huber20111aa2009-07-14 16:56:47 -0700449 }
450
James Dongc7fc37a2010-11-16 14:04:54 -0800451 off64_t offset = 0;
Andreas Huber20111aa2009-07-14 16:56:47 -0700452 status_t err;
Marco Nelissen62ad9072013-02-13 09:27:28 -0800453 while (true) {
454 err = parseChunk(&offset, 0);
455 if (err == OK) {
456 continue;
457 }
458
459 uint32_t hdr[2];
460 if (mDataSource->readAt(offset, hdr, 8) < 8) {
461 break;
462 }
463 uint32_t chunk_type = ntohl(hdr[1]);
464 if (chunk_type == FOURCC('s', 'i', 'd', 'x')) {
465 // parse the sidx box too
466 continue;
467 } else if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
468 // store the offset of the first segment
469 mMoofOffset = offset;
470 }
471 break;
Andreas Huber20111aa2009-07-14 16:56:47 -0700472 }
Andreas Huber7be64072010-01-13 11:25:10 -0800473
Andreas Huberbdba1f22011-03-03 13:48:41 -0800474 if (mInitCheck == OK) {
Andreas Huber72b8c5a2010-01-19 16:43:53 -0800475 if (mHasVideo) {
Andreas Huberbc8b5fa2012-03-23 08:39:04 -0700476 mFileMetaData->setCString(
477 kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG4);
Andreas Huber72b8c5a2010-01-19 16:43:53 -0800478 } else {
479 mFileMetaData->setCString(kKeyMIMEType, "audio/mp4");
480 }
481
Andreas Huber4678a6d2011-04-15 11:52:29 -0700482 mInitCheck = OK;
Andreas Huberbdba1f22011-03-03 13:48:41 -0800483 } else {
484 mInitCheck = err;
Andreas Huber20111aa2009-07-14 16:56:47 -0700485 }
486
Andreas Huberbdba1f22011-03-03 13:48:41 -0800487 CHECK_NE(err, (status_t)NO_INIT);
Marco Nelissen5544c662013-04-08 14:30:57 -0700488
489 // copy pssh data into file metadata
490 int psshsize = 0;
491 for (size_t i = 0; i < mPssh.size(); i++) {
492 psshsize += 20 + mPssh[i].datalen;
493 }
494 if (psshsize) {
495 char *buf = (char*)malloc(psshsize);
496 char *ptr = buf;
497 for (size_t i = 0; i < mPssh.size(); i++) {
498 memcpy(ptr, mPssh[i].uuid, 20); // uuid + length
499 memcpy(ptr + 20, mPssh[i].data, mPssh[i].datalen);
500 ptr += (20 + mPssh[i].datalen);
501 }
502 mFileMetaData->setData(kKeyPssh, 'pssh', buf, psshsize);
503 free(buf);
504 }
Andreas Huberbdba1f22011-03-03 13:48:41 -0800505 return mInitCheck;
Andreas Huber20111aa2009-07-14 16:56:47 -0700506}
507
Gloria Wangdcd25ef2010-06-22 13:55:38 -0700508char* MPEG4Extractor::getDrmTrackInfo(size_t trackID, int *len) {
509 if (mFirstSINF == NULL) {
510 return NULL;
511 }
512
513 SINF *sinf = mFirstSINF;
514 while (sinf && (trackID != sinf->trackID)) {
515 sinf = sinf->next;
516 }
517
518 if (sinf == NULL) {
519 return NULL;
520 }
521
522 *len = sinf->len;
523 return sinf->IPMPData;
524}
525
526// Reads an encoded integer 7 bits at a time until it encounters the high bit clear.
Marco Nelissen1e9ee012012-08-28 15:09:49 -0700527static int32_t readSize(off64_t offset,
Gloria Wangdcd25ef2010-06-22 13:55:38 -0700528 const sp<DataSource> DataSource, uint8_t *numOfBytes) {
529 uint32_t size = 0;
530 uint8_t data;
531 bool moreData = true;
532 *numOfBytes = 0;
533
534 while (moreData) {
535 if (DataSource->readAt(offset, &data, 1) < 1) {
536 return -1;
537 }
538 offset ++;
539 moreData = (data >= 128) ? true : false;
540 size = (size << 7) | (data & 0x7f); // Take last 7 bits
541 (*numOfBytes) ++;
542 }
543
544 return size;
545}
546
James Dongc7fc37a2010-11-16 14:04:54 -0800547status_t MPEG4Extractor::parseDrmSINF(off64_t *offset, off64_t data_offset) {
Gloria Wangdcd25ef2010-06-22 13:55:38 -0700548 uint8_t updateIdTag;
549 if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
550 return ERROR_IO;
551 }
552 data_offset ++;
553
554 if (0x01/*OBJECT_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
555 return ERROR_MALFORMED;
556 }
557
558 uint8_t numOfBytes;
559 int32_t size = readSize(data_offset, mDataSource, &numOfBytes);
560 if (size < 0) {
561 return ERROR_IO;
562 }
563 int32_t classSize = size;
564 data_offset += numOfBytes;
565
566 while(size >= 11 ) {
567 uint8_t descriptorTag;
568 if (mDataSource->readAt(data_offset, &descriptorTag, 1) < 1) {
569 return ERROR_IO;
570 }
571 data_offset ++;
572
573 if (0x11/*OBJECT_DESCRIPTOR_ID_TAG*/ != descriptorTag) {
574 return ERROR_MALFORMED;
575 }
576
577 uint8_t buffer[8];
578 //ObjectDescriptorID and ObjectDescriptor url flag
579 if (mDataSource->readAt(data_offset, buffer, 2) < 2) {
580 return ERROR_IO;
581 }
582 data_offset += 2;
583
584 if ((buffer[1] >> 5) & 0x0001) { //url flag is set
585 return ERROR_MALFORMED;
586 }
587
588 if (mDataSource->readAt(data_offset, buffer, 8) < 8) {
589 return ERROR_IO;
590 }
591 data_offset += 8;
592
593 if ((0x0F/*ES_ID_REF_TAG*/ != buffer[1])
594 || ( 0x0A/*IPMP_DESCRIPTOR_POINTER_ID_TAG*/ != buffer[5])) {
595 return ERROR_MALFORMED;
596 }
597
598 SINF *sinf = new SINF;
599 sinf->trackID = U16_AT(&buffer[3]);
600 sinf->IPMPDescriptorID = buffer[7];
601 sinf->next = mFirstSINF;
602 mFirstSINF = sinf;
603
604 size -= (8 + 2 + 1);
605 }
606
607 if (size != 0) {
608 return ERROR_MALFORMED;
609 }
610
611 if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
612 return ERROR_IO;
613 }
614 data_offset ++;
615
616 if(0x05/*IPMP_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
617 return ERROR_MALFORMED;
618 }
619
620 size = readSize(data_offset, mDataSource, &numOfBytes);
621 if (size < 0) {
622 return ERROR_IO;
623 }
624 classSize = size;
625 data_offset += numOfBytes;
626
627 while (size > 0) {
628 uint8_t tag;
629 int32_t dataLen;
630 if (mDataSource->readAt(data_offset, &tag, 1) < 1) {
631 return ERROR_IO;
632 }
633 data_offset ++;
634
635 if (0x0B/*IPMP_DESCRIPTOR_ID_TAG*/ == tag) {
636 uint8_t id;
637 dataLen = readSize(data_offset, mDataSource, &numOfBytes);
638 if (dataLen < 0) {
639 return ERROR_IO;
640 } else if (dataLen < 4) {
641 return ERROR_MALFORMED;
642 }
643 data_offset += numOfBytes;
644
645 if (mDataSource->readAt(data_offset, &id, 1) < 1) {
646 return ERROR_IO;
647 }
648 data_offset ++;
649
650 SINF *sinf = mFirstSINF;
651 while (sinf && (sinf->IPMPDescriptorID != id)) {
652 sinf = sinf->next;
653 }
654 if (sinf == NULL) {
655 return ERROR_MALFORMED;
656 }
657 sinf->len = dataLen - 3;
658 sinf->IPMPData = new char[sinf->len];
659
660 if (mDataSource->readAt(data_offset + 2, sinf->IPMPData, sinf->len) < sinf->len) {
661 return ERROR_IO;
662 }
663 data_offset += sinf->len;
664
665 size -= (dataLen + numOfBytes + 1);
666 }
667 }
668
669 if (size != 0) {
670 return ERROR_MALFORMED;
671 }
672
673 return UNKNOWN_ERROR; // Return a dummy error.
674}
675
Andreas Huber20111aa2009-07-14 16:56:47 -0700676static void MakeFourCCString(uint32_t x, char *s) {
677 s[0] = x >> 24;
678 s[1] = (x >> 16) & 0xff;
679 s[2] = (x >> 8) & 0xff;
680 s[3] = x & 0xff;
681 s[4] = '\0';
682}
683
Andreas Huber72b8c5a2010-01-19 16:43:53 -0800684struct PathAdder {
685 PathAdder(Vector<uint32_t> *path, uint32_t chunkType)
686 : mPath(path) {
687 mPath->push(chunkType);
688 }
689
690 ~PathAdder() {
691 mPath->pop();
692 }
693
694private:
695 Vector<uint32_t> *mPath;
696
697 PathAdder(const PathAdder &);
698 PathAdder &operator=(const PathAdder &);
699};
700
701static bool underMetaDataPath(const Vector<uint32_t> &path) {
702 return path.size() >= 5
703 && path[0] == FOURCC('m', 'o', 'o', 'v')
704 && path[1] == FOURCC('u', 'd', 't', 'a')
705 && path[2] == FOURCC('m', 'e', 't', 'a')
706 && path[3] == FOURCC('i', 'l', 's', 't');
707}
708
709// Given a time in seconds since Jan 1 1904, produce a human-readable string.
710static void convertTimeToDate(int64_t time_1904, String8 *s) {
711 time_t time_1970 = time_1904 - (((66 * 365 + 17) * 24) * 3600);
712
713 char tmp[32];
714 strftime(tmp, sizeof(tmp), "%Y%m%dT%H%M%S.000Z", gmtime(&time_1970));
715
716 s->setTo(tmp);
717}
718
James Dongc7fc37a2010-11-16 14:04:54 -0800719status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
Marco Nelissen5d2f8ba2012-03-20 10:05:06 -0700720 ALOGV("entering parseChunk %lld/%d", *offset, depth);
Andreas Huber20111aa2009-07-14 16:56:47 -0700721 uint32_t hdr[2];
Andreas Huber34769bc2009-10-23 10:22:30 -0700722 if (mDataSource->readAt(*offset, hdr, 8) < 8) {
Andreas Huber20111aa2009-07-14 16:56:47 -0700723 return ERROR_IO;
724 }
725 uint64_t chunk_size = ntohl(hdr[0]);
726 uint32_t chunk_type = ntohl(hdr[1]);
James Dongc7fc37a2010-11-16 14:04:54 -0800727 off64_t data_offset = *offset + 8;
Andreas Huber20111aa2009-07-14 16:56:47 -0700728
729 if (chunk_size == 1) {
Andreas Huber34769bc2009-10-23 10:22:30 -0700730 if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
Andreas Huber20111aa2009-07-14 16:56:47 -0700731 return ERROR_IO;
732 }
733 chunk_size = ntoh64(chunk_size);
734 data_offset += 8;
Andreas Huber71b1a4e2010-06-24 12:16:25 -0700735
736 if (chunk_size < 16) {
737 // The smallest valid chunk is 16 bytes long in this case.
738 return ERROR_MALFORMED;
739 }
740 } else if (chunk_size < 8) {
741 // The smallest valid chunk is 8 bytes long.
742 return ERROR_MALFORMED;
Andreas Huber20111aa2009-07-14 16:56:47 -0700743 }
744
745 char chunk[5];
746 MakeFourCCString(chunk_type, chunk);
Marco Nelissen62ad9072013-02-13 09:27:28 -0800747 ALOGV("chunk: %s @ %lld, %d", chunk, *offset, depth);
Andreas Huber20111aa2009-07-14 16:56:47 -0700748
749#if 0
750 static const char kWhitespace[] = " ";
751 const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth];
752 printf("%sfound chunk '%s' of size %lld\n", indent, chunk, chunk_size);
753
754 char buffer[256];
Andreas Huberea5ea102010-02-25 15:59:24 -0800755 size_t n = chunk_size;
756 if (n > sizeof(buffer)) {
757 n = sizeof(buffer);
Andreas Huber20111aa2009-07-14 16:56:47 -0700758 }
Andreas Huberea5ea102010-02-25 15:59:24 -0800759 if (mDataSource->readAt(*offset, buffer, n)
760 < (ssize_t)n) {
761 return ERROR_IO;
762 }
763
764 hexdump(buffer, n);
Andreas Huber20111aa2009-07-14 16:56:47 -0700765#endif
766
Andreas Huber72b8c5a2010-01-19 16:43:53 -0800767 PathAdder autoAdder(&mPath, chunk_type);
768
James Dongc7fc37a2010-11-16 14:04:54 -0800769 off64_t chunk_data_size = *offset + chunk_size - data_offset;
Andreas Huber20111aa2009-07-14 16:56:47 -0700770
Andreas Huber72b8c5a2010-01-19 16:43:53 -0800771 if (chunk_type != FOURCC('c', 'p', 'r', 't')
James Dong515e8552011-05-25 15:02:50 -0700772 && chunk_type != FOURCC('c', 'o', 'v', 'r')
Andreas Huber72b8c5a2010-01-19 16:43:53 -0800773 && mPath.size() == 5 && underMetaDataPath(mPath)) {
James Dongc7fc37a2010-11-16 14:04:54 -0800774 off64_t stop_offset = *offset + chunk_size;
Andreas Huber72b8c5a2010-01-19 16:43:53 -0800775 *offset = data_offset;
776 while (*offset < stop_offset) {
777 status_t err = parseChunk(offset, depth + 1);
778 if (err != OK) {
779 return err;
780 }
781 }
Andreas Huberbd5d93f2010-02-23 10:12:02 -0800782
783 if (*offset != stop_offset) {
784 return ERROR_MALFORMED;
785 }
Andreas Huber72b8c5a2010-01-19 16:43:53 -0800786
787 return OK;
788 }
789
Andreas Huber20111aa2009-07-14 16:56:47 -0700790 switch(chunk_type) {
791 case FOURCC('m', 'o', 'o', 'v'):
792 case FOURCC('t', 'r', 'a', 'k'):
793 case FOURCC('m', 'd', 'i', 'a'):
794 case FOURCC('m', 'i', 'n', 'f'):
795 case FOURCC('d', 'i', 'n', 'f'):
796 case FOURCC('s', 't', 'b', 'l'):
797 case FOURCC('m', 'v', 'e', 'x'):
798 case FOURCC('m', 'o', 'o', 'f'):
799 case FOURCC('t', 'r', 'a', 'f'):
800 case FOURCC('m', 'f', 'r', 'a'):
Andreas Huber72b8c5a2010-01-19 16:43:53 -0800801 case FOURCC('u', 'd', 't', 'a'):
802 case FOURCC('i', 'l', 's', 't'):
Marco Nelissen5544c662013-04-08 14:30:57 -0700803 case FOURCC('s', 'i', 'n', 'f'):
804 case FOURCC('s', 'c', 'h', 'i'):
Andreas Huber20111aa2009-07-14 16:56:47 -0700805 {
Andreas Huber50a99762010-01-28 14:27:37 -0800806 if (chunk_type == FOURCC('s', 't', 'b', 'l')) {
Steve Block3856b092011-10-20 11:56:00 +0100807 ALOGV("sampleTable chunk is %d bytes long.", (size_t)chunk_size);
Andreas Huber50a99762010-01-28 14:27:37 -0800808
Andreas Huberb9d30382010-10-15 08:38:49 -0700809 if (mDataSource->flags()
810 & (DataSource::kWantsPrefetching
811 | DataSource::kIsCachingDataSource)) {
Andreas Huber50a99762010-01-28 14:27:37 -0800812 sp<MPEG4DataSource> cachedSource =
813 new MPEG4DataSource(mDataSource);
814
815 if (cachedSource->setCachedRange(*offset, chunk_size) == OK) {
816 mDataSource = cachedSource;
817 }
818 }
Andreas Huber1edbcb22010-05-14 15:28:51 -0700819
820 mLastTrack->sampleTable = new SampleTable(mDataSource);
Andreas Huber50a99762010-01-28 14:27:37 -0800821 }
822
Andreas Huber6f3a0c22010-03-12 16:15:53 -0800823 bool isTrack = false;
Andreas Huberbd5d93f2010-02-23 10:12:02 -0800824 if (chunk_type == FOURCC('t', 'r', 'a', 'k')) {
Andreas Huber6f3a0c22010-03-12 16:15:53 -0800825 isTrack = true;
826
Andreas Huberbd5d93f2010-02-23 10:12:02 -0800827 Track *track = new Track;
828 track->next = NULL;
829 if (mLastTrack) {
830 mLastTrack->next = track;
831 } else {
832 mFirstTrack = track;
833 }
834 mLastTrack = track;
835
836 track->meta = new MetaData;
837 track->includes_expensive_metadata = false;
Andreas Huber6f3a0c22010-03-12 16:15:53 -0800838 track->skipTrack = false;
Andreas Huberbd5d93f2010-02-23 10:12:02 -0800839 track->timescale = 0;
Andreas Huberbd5d93f2010-02-23 10:12:02 -0800840 track->meta->setCString(kKeyMIMEType, "application/octet-stream");
841 }
842
James Dongc7fc37a2010-11-16 14:04:54 -0800843 off64_t stop_offset = *offset + chunk_size;
Andreas Huber20111aa2009-07-14 16:56:47 -0700844 *offset = data_offset;
845 while (*offset < stop_offset) {
846 status_t err = parseChunk(offset, depth + 1);
847 if (err != OK) {
848 return err;
849 }
850 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700851
Andreas Huberbd5d93f2010-02-23 10:12:02 -0800852 if (*offset != stop_offset) {
853 return ERROR_MALFORMED;
854 }
855
Andreas Huber6f3a0c22010-03-12 16:15:53 -0800856 if (isTrack) {
857 if (mLastTrack->skipTrack) {
858 Track *cur = mFirstTrack;
859
860 if (cur == mLastTrack) {
861 delete cur;
862 mFirstTrack = mLastTrack = NULL;
863 } else {
864 while (cur && cur->next != mLastTrack) {
865 cur = cur->next;
866 }
867 cur->next = NULL;
868 delete mLastTrack;
869 mLastTrack = cur;
870 }
871
872 return OK;
873 }
874
Andreas Huberbd5d93f2010-02-23 10:12:02 -0800875 status_t err = verifyTrack(mLastTrack);
876
877 if (err != OK) {
878 return err;
879 }
880 } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
Andreas Huberbdba1f22011-03-03 13:48:41 -0800881 mInitCheck = OK;
Andreas Huber20111aa2009-07-14 16:56:47 -0700882
Gloria Wangdcd25ef2010-06-22 13:55:38 -0700883 if (!mIsDrm) {
884 return UNKNOWN_ERROR; // Return a dummy error.
885 } else {
886 return OK;
887 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700888 }
889 break;
890 }
891
Marco Nelissen5544c662013-04-08 14:30:57 -0700892 case FOURCC('f', 'r', 'm', 'a'):
893 {
894 int32_t original_fourcc;
895 if (mDataSource->readAt(data_offset, &original_fourcc, 4) < 4) {
896 return ERROR_IO;
897 }
898 original_fourcc = ntohl(original_fourcc);
899 ALOGV("read original format: %d", original_fourcc);
900 mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(original_fourcc));
901 *offset += chunk_size;
902 break;
903 }
904
905 case FOURCC('t', 'e', 'n', 'c'):
906 {
907 if (chunk_size < 32) {
908 return ERROR_MALFORMED;
909 }
910
911 // tenc box contains 1 byte version, 3 byte flags, 3 byte default algorithm id, one byte
912 // default IV size, 16 bytes default KeyID
913 // (ISO 23001-7)
914 char buf[4];
915 memset(buf, 0, 4);
916 if (mDataSource->readAt(data_offset + 4, buf + 1, 3) < 3) {
917 return ERROR_IO;
918 }
919 uint32_t defaultAlgorithmId = ntohl(*((int32_t*)buf));
920 if (defaultAlgorithmId > 1) {
921 // only 0 (clear) and 1 (AES-128) are valid
922 return ERROR_MALFORMED;
923 }
924
925 memset(buf, 0, 4);
926 if (mDataSource->readAt(data_offset + 7, buf + 3, 1) < 1) {
927 return ERROR_IO;
928 }
929 uint32_t defaultIVSize = ntohl(*((int32_t*)buf));
930
931 if ((defaultAlgorithmId == 0 && defaultIVSize != 0) ||
932 (defaultAlgorithmId != 0 && defaultIVSize == 0)) {
933 // only unencrypted data must have 0 IV size
934 return ERROR_MALFORMED;
935 } else if (defaultIVSize != 0 &&
936 defaultIVSize != 8 &&
937 defaultIVSize != 16) {
938 // only supported sizes are 0, 8 and 16
939 return ERROR_MALFORMED;
940 }
941
942 uint8_t defaultKeyId[16];
943
944 if (mDataSource->readAt(data_offset + 8, &defaultKeyId, 16) < 16) {
945 return ERROR_IO;
946 }
947
948 mLastTrack->meta->setInt32(kKeyCryptoMode, defaultAlgorithmId);
949 mLastTrack->meta->setInt32(kKeyCryptoDefaultIVSize, defaultIVSize);
950 mLastTrack->meta->setData(kKeyCryptoKey, 'tenc', defaultKeyId, 16);
951 *offset += chunk_size;
952 break;
953 }
954
Andreas Huber20111aa2009-07-14 16:56:47 -0700955 case FOURCC('t', 'k', 'h', 'd'):
956 {
Andreas Huberba529e42010-11-16 15:26:30 -0800957 status_t err;
958 if ((err = parseTrackHeader(data_offset, chunk_data_size)) != OK) {
959 return err;
Andreas Huberbd5d93f2010-02-23 10:12:02 -0800960 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700961
Andreas Huber20111aa2009-07-14 16:56:47 -0700962 *offset += chunk_size;
963 break;
964 }
965
Marco Nelissen5544c662013-04-08 14:30:57 -0700966 case FOURCC('p', 's', 's', 'h'):
967 {
968 PsshInfo pssh;
969
970 if (mDataSource->readAt(data_offset + 4, &pssh.uuid, 16) < 16) {
971 return ERROR_IO;
972 }
973
974 uint32_t psshdatalen = 0;
975 if (mDataSource->readAt(data_offset + 20, &psshdatalen, 4) < 4) {
976 return ERROR_IO;
977 }
978 pssh.datalen = ntohl(psshdatalen);
979 ALOGV("pssh data size: %d", pssh.datalen);
980 if (pssh.datalen + 20 > chunk_size) {
981 // pssh data length exceeds size of containing box
982 return ERROR_MALFORMED;
983 }
984
985 pssh.data = new uint8_t[pssh.datalen];
986 ALOGV("allocated pssh @ %p", pssh.data);
987 ssize_t requested = (ssize_t) pssh.datalen;
988 if (mDataSource->readAt(data_offset + 24, pssh.data, requested) < requested) {
989 return ERROR_IO;
990 }
991 mPssh.push_back(pssh);
992
993 *offset += chunk_size;
994 break;
995 }
996
Andreas Huber20111aa2009-07-14 16:56:47 -0700997 case FOURCC('m', 'd', 'h', 'd'):
998 {
999 if (chunk_data_size < 4) {
1000 return ERROR_MALFORMED;
1001 }
1002
1003 uint8_t version;
Andreas Huber34769bc2009-10-23 10:22:30 -07001004 if (mDataSource->readAt(
Andreas Huber20111aa2009-07-14 16:56:47 -07001005 data_offset, &version, sizeof(version))
1006 < (ssize_t)sizeof(version)) {
1007 return ERROR_IO;
1008 }
1009
James Dongc7fc37a2010-11-16 14:04:54 -08001010 off64_t timescale_offset;
Andreas Huber20111aa2009-07-14 16:56:47 -07001011
1012 if (version == 1) {
1013 timescale_offset = data_offset + 4 + 16;
1014 } else if (version == 0) {
1015 timescale_offset = data_offset + 4 + 8;
1016 } else {
1017 return ERROR_IO;
1018 }
1019
1020 uint32_t timescale;
Andreas Huber34769bc2009-10-23 10:22:30 -07001021 if (mDataSource->readAt(
Andreas Huber20111aa2009-07-14 16:56:47 -07001022 timescale_offset, &timescale, sizeof(timescale))
1023 < (ssize_t)sizeof(timescale)) {
1024 return ERROR_IO;
1025 }
1026
1027 mLastTrack->timescale = ntohl(timescale);
Andreas Huber20111aa2009-07-14 16:56:47 -07001028
Marco Nelissen62ad9072013-02-13 09:27:28 -08001029 int64_t duration = 0;
Andreas Huber20111aa2009-07-14 16:56:47 -07001030 if (version == 1) {
Andreas Huber34769bc2009-10-23 10:22:30 -07001031 if (mDataSource->readAt(
Andreas Huber20111aa2009-07-14 16:56:47 -07001032 timescale_offset + 4, &duration, sizeof(duration))
1033 < (ssize_t)sizeof(duration)) {
1034 return ERROR_IO;
1035 }
1036 duration = ntoh64(duration);
1037 } else {
Marco Nelissen62ad9072013-02-13 09:27:28 -08001038 uint32_t duration32;
Andreas Huber34769bc2009-10-23 10:22:30 -07001039 if (mDataSource->readAt(
Andreas Huber20111aa2009-07-14 16:56:47 -07001040 timescale_offset + 4, &duration32, sizeof(duration32))
1041 < (ssize_t)sizeof(duration32)) {
1042 return ERROR_IO;
1043 }
Marco Nelissen62ad9072013-02-13 09:27:28 -08001044 // ffmpeg sets duration to -1, which is incorrect.
1045 if (duration32 != 0xffffffff) {
1046 duration = ntohl(duration32);
1047 }
Andreas Huber20111aa2009-07-14 16:56:47 -07001048 }
Andreas Huber48c948b2009-10-08 10:07:49 -07001049 mLastTrack->meta->setInt64(
1050 kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
Andreas Huber20111aa2009-07-14 16:56:47 -07001051
Gloria Wang7a1e3e82011-05-03 15:59:03 -07001052 uint8_t lang[2];
1053 off64_t lang_offset;
1054 if (version == 1) {
1055 lang_offset = timescale_offset + 4 + 8;
1056 } else if (version == 0) {
1057 lang_offset = timescale_offset + 4 + 4;
1058 } else {
1059 return ERROR_IO;
1060 }
1061
1062 if (mDataSource->readAt(lang_offset, &lang, sizeof(lang))
1063 < (ssize_t)sizeof(lang)) {
1064 return ERROR_IO;
1065 }
1066
1067 // To get the ISO-639-2/T three character language code
1068 // 1 bit pad followed by 3 5-bits characters. Each character
1069 // is packed as the difference between its ASCII value and 0x60.
1070 char lang_code[4];
1071 lang_code[0] = ((lang[0] >> 2) & 0x1f) + 0x60;
1072 lang_code[1] = ((lang[0] & 0x3) << 3 | (lang[1] >> 5)) + 0x60;
1073 lang_code[2] = (lang[1] & 0x1f) + 0x60;
1074 lang_code[3] = '\0';
1075
1076 mLastTrack->meta->setCString(
1077 kKeyMediaLanguage, lang_code);
1078
Andreas Huber20111aa2009-07-14 16:56:47 -07001079 *offset += chunk_size;
1080 break;
1081 }
1082
Andreas Huber20111aa2009-07-14 16:56:47 -07001083 case FOURCC('s', 't', 's', 'd'):
1084 {
1085 if (chunk_data_size < 8) {
1086 return ERROR_MALFORMED;
1087 }
1088
1089 uint8_t buffer[8];
James Dongc7fc37a2010-11-16 14:04:54 -08001090 if (chunk_data_size < (off64_t)sizeof(buffer)) {
Andreas Huberbd5d93f2010-02-23 10:12:02 -08001091 return ERROR_MALFORMED;
1092 }
1093
Andreas Huber34769bc2009-10-23 10:22:30 -07001094 if (mDataSource->readAt(
Andreas Huber20111aa2009-07-14 16:56:47 -07001095 data_offset, buffer, 8) < 8) {
1096 return ERROR_IO;
1097 }
1098
1099 if (U32_AT(buffer) != 0) {
1100 // Should be version 0, flags 0.
1101 return ERROR_MALFORMED;
1102 }
1103
1104 uint32_t entry_count = U32_AT(&buffer[4]);
1105
1106 if (entry_count > 1) {
Gloria Wang3b573f72011-05-31 16:08:47 -07001107 // For 3GPP timed text, there could be multiple tx3g boxes contain
1108 // multiple text display formats. These formats will be used to
1109 // display the timed text.
Marco Nelissen5544c662013-04-08 14:30:57 -07001110 // For encrypted files, there may also be more than one entry.
Gloria Wang3b573f72011-05-31 16:08:47 -07001111 const char *mime;
1112 CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
Marco Nelissen5544c662013-04-08 14:30:57 -07001113 if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) &&
1114 strcasecmp(mime, "application/octet-stream")) {
Gloria Wang3b573f72011-05-31 16:08:47 -07001115 // For now we only support a single type of media per track.
1116 mLastTrack->skipTrack = true;
1117 *offset += chunk_size;
1118 break;
1119 }
Andreas Huber20111aa2009-07-14 16:56:47 -07001120 }
James Dongc7fc37a2010-11-16 14:04:54 -08001121 off64_t stop_offset = *offset + chunk_size;
Andreas Huber20111aa2009-07-14 16:56:47 -07001122 *offset = data_offset + 8;
1123 for (uint32_t i = 0; i < entry_count; ++i) {
1124 status_t err = parseChunk(offset, depth + 1);
1125 if (err != OK) {
1126 return err;
1127 }
1128 }
Andreas Huberbd5d93f2010-02-23 10:12:02 -08001129
1130 if (*offset != stop_offset) {
1131 return ERROR_MALFORMED;
1132 }
Andreas Huber20111aa2009-07-14 16:56:47 -07001133 break;
1134 }
1135
1136 case FOURCC('m', 'p', '4', 'a'):
1137 case FOURCC('s', 'a', 'm', 'r'):
Andreas Huber371e2432009-09-09 16:32:59 -07001138 case FOURCC('s', 'a', 'w', 'b'):
Andreas Huber20111aa2009-07-14 16:56:47 -07001139 {
Andreas Huber20111aa2009-07-14 16:56:47 -07001140 uint8_t buffer[8 + 20];
1141 if (chunk_data_size < (ssize_t)sizeof(buffer)) {
1142 // Basic AudioSampleEntry size.
1143 return ERROR_MALFORMED;
1144 }
1145
Andreas Huber34769bc2009-10-23 10:22:30 -07001146 if (mDataSource->readAt(
Andreas Huber20111aa2009-07-14 16:56:47 -07001147 data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
1148 return ERROR_IO;
1149 }
1150
1151 uint16_t data_ref_index = U16_AT(&buffer[6]);
1152 uint16_t num_channels = U16_AT(&buffer[16]);
1153
Andreas Huber20111aa2009-07-14 16:56:47 -07001154 uint16_t sample_size = U16_AT(&buffer[18]);
1155 uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
1156
Andreas Huber81f82c32010-04-12 16:05:57 -07001157 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB,
1158 FourCC2MIME(chunk_type))) {
1159 // AMR NB audio is always mono, 8kHz
1160 num_channels = 1;
1161 sample_rate = 8000;
1162 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB,
1163 FourCC2MIME(chunk_type))) {
1164 // AMR WB audio is always mono, 16kHz
1165 num_channels = 1;
1166 sample_rate = 16000;
1167 }
1168
1169#if 0
1170 printf("*** coding='%s' %d channels, size %d, rate %d\n",
1171 chunk, num_channels, sample_size, sample_rate);
1172#endif
Andreas Huber20111aa2009-07-14 16:56:47 -07001173
1174 mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
1175 mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
1176 mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
1177
James Dongc7fc37a2010-11-16 14:04:54 -08001178 off64_t stop_offset = *offset + chunk_size;
Andreas Huber20111aa2009-07-14 16:56:47 -07001179 *offset = data_offset + sizeof(buffer);
1180 while (*offset < stop_offset) {
1181 status_t err = parseChunk(offset, depth + 1);
1182 if (err != OK) {
1183 return err;
1184 }
1185 }
Andreas Huberbd5d93f2010-02-23 10:12:02 -08001186
1187 if (*offset != stop_offset) {
1188 return ERROR_MALFORMED;
1189 }
Andreas Huber20111aa2009-07-14 16:56:47 -07001190 break;
1191 }
1192
1193 case FOURCC('m', 'p', '4', 'v'):
Marco Nelissen5544c662013-04-08 14:30:57 -07001194 case FOURCC('e', 'n', 'c', 'v'):
Andreas Huber20111aa2009-07-14 16:56:47 -07001195 case FOURCC('s', '2', '6', '3'):
James Donge071b052010-12-15 15:49:46 -08001196 case FOURCC('H', '2', '6', '3'):
1197 case FOURCC('h', '2', '6', '3'):
Andreas Huber20111aa2009-07-14 16:56:47 -07001198 case FOURCC('a', 'v', 'c', '1'):
1199 {
Andreas Huber7be64072010-01-13 11:25:10 -08001200 mHasVideo = true;
1201
Andreas Huber20111aa2009-07-14 16:56:47 -07001202 uint8_t buffer[78];
1203 if (chunk_data_size < (ssize_t)sizeof(buffer)) {
1204 // Basic VideoSampleEntry size.
1205 return ERROR_MALFORMED;
1206 }
1207
Andreas Huber34769bc2009-10-23 10:22:30 -07001208 if (mDataSource->readAt(
Andreas Huber20111aa2009-07-14 16:56:47 -07001209 data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
1210 return ERROR_IO;
1211 }
1212
1213 uint16_t data_ref_index = U16_AT(&buffer[6]);
1214 uint16_t width = U16_AT(&buffer[6 + 18]);
1215 uint16_t height = U16_AT(&buffer[6 + 20]);
1216
Marco Nelissen5544c662013-04-08 14:30:57 -07001217 // The video sample is not standard-compliant if it has invalid dimension.
James Donga6256232010-12-15 17:32:45 -08001218 // Use some default width and height value, and
1219 // let the decoder figure out the actual width and height (and thus
1220 // be prepared for INFO_FOMRAT_CHANGED event).
1221 if (width == 0) width = 352;
1222 if (height == 0) height = 288;
1223
Andreas Huber134ee6a2009-12-16 09:30:55 -08001224 // printf("*** coding='%s' width=%d height=%d\n",
1225 // chunk, width, height);
Andreas Huber20111aa2009-07-14 16:56:47 -07001226
Marco Nelissen5544c662013-04-08 14:30:57 -07001227 if (chunk_type != FOURCC('e', 'n', 'c', 'v')) {
1228 // if the chunk type is encv, we'll get the type from the sinf/frma box later
1229 mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
1230 }
Andreas Huber20111aa2009-07-14 16:56:47 -07001231 mLastTrack->meta->setInt32(kKeyWidth, width);
1232 mLastTrack->meta->setInt32(kKeyHeight, height);
1233
James Dongc7fc37a2010-11-16 14:04:54 -08001234 off64_t stop_offset = *offset + chunk_size;
Andreas Huber20111aa2009-07-14 16:56:47 -07001235 *offset = data_offset + sizeof(buffer);
1236 while (*offset < stop_offset) {
1237 status_t err = parseChunk(offset, depth + 1);
1238 if (err != OK) {
1239 return err;
1240 }
1241 }
Andreas Huberbd5d93f2010-02-23 10:12:02 -08001242
1243 if (*offset != stop_offset) {
1244 return ERROR_MALFORMED;
1245 }
Andreas Huber20111aa2009-07-14 16:56:47 -07001246 break;
1247 }
1248
1249 case FOURCC('s', 't', 'c', 'o'):
1250 case FOURCC('c', 'o', '6', '4'):
1251 {
1252 status_t err =
1253 mLastTrack->sampleTable->setChunkOffsetParams(
1254 chunk_type, data_offset, chunk_data_size);
1255
1256 if (err != OK) {
1257 return err;
1258 }
1259
1260 *offset += chunk_size;
1261 break;
1262 }
1263
1264 case FOURCC('s', 't', 's', 'c'):
1265 {
1266 status_t err =
1267 mLastTrack->sampleTable->setSampleToChunkParams(
1268 data_offset, chunk_data_size);
1269
1270 if (err != OK) {
1271 return err;
1272 }
1273
1274 *offset += chunk_size;
1275 break;
1276 }
1277
1278 case FOURCC('s', 't', 's', 'z'):
1279 case FOURCC('s', 't', 'z', '2'):
1280 {
1281 status_t err =
1282 mLastTrack->sampleTable->setSampleSizeParams(
1283 chunk_type, data_offset, chunk_data_size);
1284
1285 if (err != OK) {
1286 return err;
1287 }
1288
Andreas Huber738c4312009-11-23 14:03:32 -08001289 size_t max_size;
Andreas Huber49110ce2010-09-09 10:10:15 -07001290 err = mLastTrack->sampleTable->getMaxSampleSize(&max_size);
1291
1292 if (err != OK) {
1293 return err;
1294 }
Andreas Huber738c4312009-11-23 14:03:32 -08001295
Marco Nelissen62ad9072013-02-13 09:27:28 -08001296 if (max_size != 0) {
1297 // Assume that a given buffer only contains at most 10 chunks,
1298 // each chunk originally prefixed with a 2 byte length will
1299 // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
1300 // and thus will grow by 2 bytes per chunk.
1301 mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
1302 } else {
1303 // No size was specified. Pick a conservatively large size.
1304 int32_t width, height;
1305 if (mLastTrack->meta->findInt32(kKeyWidth, &width) &&
1306 mLastTrack->meta->findInt32(kKeyHeight, &height)) {
1307 mLastTrack->meta->setInt32(kKeyMaxInputSize, width * height * 3 / 2);
1308 } else {
1309 ALOGE("No width or height, assuming worst case 1080p");
1310 mLastTrack->meta->setInt32(kKeyMaxInputSize, 3110400);
1311 }
1312 }
Andreas Huber20111aa2009-07-14 16:56:47 -07001313 *offset += chunk_size;
James Dong113a9542011-01-19 00:13:55 -08001314
1315 // Calculate average frame rate.
1316 const char *mime;
1317 CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1318 if (!strncasecmp("video/", mime, 6)) {
1319 size_t nSamples = mLastTrack->sampleTable->countSamples();
1320 int64_t durationUs;
1321 if (mLastTrack->meta->findInt64(kKeyDuration, &durationUs)) {
1322 if (durationUs > 0) {
1323 int32_t frameRate = (nSamples * 1000000LL +
1324 (durationUs >> 1)) / durationUs;
1325 mLastTrack->meta->setInt32(kKeyFrameRate, frameRate);
1326 }
1327 }
1328 }
1329
Andreas Huber20111aa2009-07-14 16:56:47 -07001330 break;
1331 }
1332
1333 case FOURCC('s', 't', 't', 's'):
1334 {
1335 status_t err =
1336 mLastTrack->sampleTable->setTimeToSampleParams(
1337 data_offset, chunk_data_size);
1338
1339 if (err != OK) {
1340 return err;
1341 }
1342
1343 *offset += chunk_size;
1344 break;
1345 }
1346
Andreas Huber4931bb52011-02-03 13:18:16 -08001347 case FOURCC('c', 't', 't', 's'):
1348 {
1349 status_t err =
1350 mLastTrack->sampleTable->setCompositionTimeToSampleParams(
1351 data_offset, chunk_data_size);
1352
1353 if (err != OK) {
1354 return err;
1355 }
1356
1357 *offset += chunk_size;
1358 break;
1359 }
1360
Andreas Huber20111aa2009-07-14 16:56:47 -07001361 case FOURCC('s', 't', 's', 's'):
1362 {
1363 status_t err =
1364 mLastTrack->sampleTable->setSyncSampleParams(
1365 data_offset, chunk_data_size);
1366
1367 if (err != OK) {
1368 return err;
1369 }
1370
1371 *offset += chunk_size;
1372 break;
1373 }
1374
James Dong49488182011-11-09 00:48:56 -08001375 // @xyz
1376 case FOURCC('\xA9', 'x', 'y', 'z'):
1377 {
1378 // Best case the total data length inside "@xyz" box
1379 // would be 8, for instance "@xyz" + "\x00\x04\x15\xc7" + "0+0/",
1380 // where "\x00\x04" is the text string length with value = 4,
1381 // "\0x15\xc7" is the language code = en, and "0+0" is a
1382 // location (string) value with longitude = 0 and latitude = 0.
1383 if (chunk_data_size < 8) {
1384 return ERROR_MALFORMED;
1385 }
1386
1387 // Worst case the location string length would be 18,
1388 // for instance +90.0000-180.0000, without the trailing "/" and
1389 // the string length + language code.
1390 char buffer[18];
1391
1392 // Substracting 5 from the data size is because the text string length +
1393 // language code takes 4 bytes, and the trailing slash "/" takes 1 byte.
1394 off64_t location_length = chunk_data_size - 5;
1395 if (location_length >= (off64_t) sizeof(buffer)) {
1396 return ERROR_MALFORMED;
1397 }
1398
1399 if (mDataSource->readAt(
1400 data_offset + 4, buffer, location_length) < location_length) {
1401 return ERROR_IO;
1402 }
1403
1404 buffer[location_length] = '\0';
1405 mFileMetaData->setCString(kKeyLocation, buffer);
1406 *offset += chunk_size;
1407 break;
1408 }
1409
Andreas Huber20111aa2009-07-14 16:56:47 -07001410 case FOURCC('e', 's', 'd', 's'):
1411 {
1412 if (chunk_data_size < 4) {
1413 return ERROR_MALFORMED;
1414 }
1415
1416 uint8_t buffer[256];
James Dongc7fc37a2010-11-16 14:04:54 -08001417 if (chunk_data_size > (off64_t)sizeof(buffer)) {
Andreas Huber20111aa2009-07-14 16:56:47 -07001418 return ERROR_BUFFER_TOO_SMALL;
1419 }
1420
Andreas Huber34769bc2009-10-23 10:22:30 -07001421 if (mDataSource->readAt(
Andreas Huber20111aa2009-07-14 16:56:47 -07001422 data_offset, buffer, chunk_data_size) < chunk_data_size) {
1423 return ERROR_IO;
1424 }
1425
1426 if (U32_AT(buffer) != 0) {
1427 // Should be version 0, flags 0.
1428 return ERROR_MALFORMED;
1429 }
1430
1431 mLastTrack->meta->setData(
1432 kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
1433
Andreas Huberba7c7ee2010-01-29 14:46:59 -08001434 if (mPath.size() >= 2
1435 && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) {
1436 // Information from the ESDS must be relied on for proper
1437 // setup of sample rate and channel count for MPEG4 Audio.
1438 // The generic header appears to only contain generic
1439 // information...
1440
1441 status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio(
1442 &buffer[4], chunk_data_size - 4);
1443
1444 if (err != OK) {
1445 return err;
1446 }
1447 }
1448
Andreas Huber20111aa2009-07-14 16:56:47 -07001449 *offset += chunk_size;
1450 break;
1451 }
1452
1453 case FOURCC('a', 'v', 'c', 'C'):
1454 {
Jan Olof Svensson0fd28832012-09-26 09:08:11 +02001455 sp<ABuffer> buffer = new ABuffer(chunk_data_size);
Andreas Huber20111aa2009-07-14 16:56:47 -07001456
Andreas Huber34769bc2009-10-23 10:22:30 -07001457 if (mDataSource->readAt(
Jan Olof Svensson0fd28832012-09-26 09:08:11 +02001458 data_offset, buffer->data(), chunk_data_size) < chunk_data_size) {
Andreas Huber20111aa2009-07-14 16:56:47 -07001459 return ERROR_IO;
1460 }
1461
1462 mLastTrack->meta->setData(
Jan Olof Svensson0fd28832012-09-26 09:08:11 +02001463 kKeyAVCC, kTypeAVCC, buffer->data(), chunk_data_size);
Andreas Huber20111aa2009-07-14 16:56:47 -07001464
1465 *offset += chunk_size;
1466 break;
1467 }
1468
James Dong244ba872011-02-11 15:21:45 -08001469 case FOURCC('d', '2', '6', '3'):
1470 {
James Dong17e89b52011-02-23 17:07:49 -08001471 /*
1472 * d263 contains a fixed 7 bytes part:
1473 * vendor - 4 bytes
1474 * version - 1 byte
1475 * level - 1 byte
1476 * profile - 1 byte
1477 * optionally, "d263" box itself may contain a 16-byte
1478 * bit rate box (bitr)
1479 * average bit rate - 4 bytes
1480 * max bit rate - 4 bytes
1481 */
1482 char buffer[23];
1483 if (chunk_data_size != 7 &&
1484 chunk_data_size != 23) {
Steve Block29357bc2012-01-06 19:20:56 +00001485 ALOGE("Incorrect D263 box size %lld", chunk_data_size);
James Dong244ba872011-02-11 15:21:45 -08001486 return ERROR_MALFORMED;
1487 }
1488
1489 if (mDataSource->readAt(
1490 data_offset, buffer, chunk_data_size) < chunk_data_size) {
1491 return ERROR_IO;
1492 }
1493
1494 mLastTrack->meta->setData(kKeyD263, kTypeD263, buffer, chunk_data_size);
1495
1496 *offset += chunk_size;
1497 break;
1498 }
1499
Andreas Huber72b8c5a2010-01-19 16:43:53 -08001500 case FOURCC('m', 'e', 't', 'a'):
1501 {
1502 uint8_t buffer[4];
James Dongc7fc37a2010-11-16 14:04:54 -08001503 if (chunk_data_size < (off64_t)sizeof(buffer)) {
Andreas Huberbd5d93f2010-02-23 10:12:02 -08001504 return ERROR_MALFORMED;
1505 }
1506
Andreas Huber72b8c5a2010-01-19 16:43:53 -08001507 if (mDataSource->readAt(
1508 data_offset, buffer, 4) < 4) {
1509 return ERROR_IO;
1510 }
1511
1512 if (U32_AT(buffer) != 0) {
1513 // Should be version 0, flags 0.
Andreas Huberea5ea102010-02-25 15:59:24 -08001514
1515 // If it's not, let's assume this is one of those
1516 // apparently malformed chunks that don't have flags
1517 // and completely different semantics than what's
1518 // in the MPEG4 specs and skip it.
1519 *offset += chunk_size;
1520 return OK;
Andreas Huber72b8c5a2010-01-19 16:43:53 -08001521 }
1522
James Dongc7fc37a2010-11-16 14:04:54 -08001523 off64_t stop_offset = *offset + chunk_size;
Andreas Huber72b8c5a2010-01-19 16:43:53 -08001524 *offset = data_offset + sizeof(buffer);
1525 while (*offset < stop_offset) {
1526 status_t err = parseChunk(offset, depth + 1);
1527 if (err != OK) {
1528 return err;
1529 }
1530 }
Andreas Huberbd5d93f2010-02-23 10:12:02 -08001531
1532 if (*offset != stop_offset) {
1533 return ERROR_MALFORMED;
1534 }
Andreas Huber72b8c5a2010-01-19 16:43:53 -08001535 break;
1536 }
1537
Marco Nelissen5d2f8ba2012-03-20 10:05:06 -07001538 case FOURCC('m', 'e', 'a', 'n'):
1539 case FOURCC('n', 'a', 'm', 'e'):
Andreas Huber72b8c5a2010-01-19 16:43:53 -08001540 case FOURCC('d', 'a', 't', 'a'):
1541 {
1542 if (mPath.size() == 6 && underMetaDataPath(mPath)) {
1543 status_t err = parseMetaData(data_offset, chunk_data_size);
1544
1545 if (err != OK) {
1546 return err;
1547 }
1548 }
1549
1550 *offset += chunk_size;
1551 break;
1552 }
1553
1554 case FOURCC('m', 'v', 'h', 'd'):
1555 {
1556 if (chunk_data_size < 12) {
1557 return ERROR_MALFORMED;
1558 }
1559
1560 uint8_t header[12];
1561 if (mDataSource->readAt(
1562 data_offset, header, sizeof(header))
1563 < (ssize_t)sizeof(header)) {
1564 return ERROR_IO;
1565 }
1566
1567 int64_t creationTime;
1568 if (header[0] == 1) {
1569 creationTime = U64_AT(&header[4]);
Andreas Huberbd5d93f2010-02-23 10:12:02 -08001570 } else if (header[0] != 0) {
1571 return ERROR_MALFORMED;
Andreas Huber72b8c5a2010-01-19 16:43:53 -08001572 } else {
Andreas Huber72b8c5a2010-01-19 16:43:53 -08001573 creationTime = U32_AT(&header[4]);
1574 }
1575
1576 String8 s;
1577 convertTimeToDate(creationTime, &s);
1578
1579 mFileMetaData->setCString(kKeyDate, s.string());
1580
1581 *offset += chunk_size;
1582 break;
1583 }
1584
Gloria Wangdcd25ef2010-06-22 13:55:38 -07001585 case FOURCC('m', 'd', 'a', 't'):
1586 {
Marco Nelissen5544c662013-04-08 14:30:57 -07001587 ALOGV("mdat chunk, drm: %d", mIsDrm);
Gloria Wangdcd25ef2010-06-22 13:55:38 -07001588 if (!mIsDrm) {
1589 *offset += chunk_size;
1590 break;
1591 }
1592
1593 if (chunk_size < 8) {
1594 return ERROR_MALFORMED;
1595 }
1596
1597 return parseDrmSINF(offset, data_offset);
1598 }
1599
Gloria Wang3b573f72011-05-31 16:08:47 -07001600 case FOURCC('h', 'd', 'l', 'r'):
1601 {
1602 uint32_t buffer;
1603 if (mDataSource->readAt(
1604 data_offset + 8, &buffer, 4) < 4) {
1605 return ERROR_IO;
1606 }
1607
1608 uint32_t type = ntohl(buffer);
1609 // For the 3GPP file format, the handler-type within the 'hdlr' box
Insun Kange26dd872011-11-10 16:11:26 +09001610 // shall be 'text'. We also want to support 'sbtl' handler type
1611 // for a practical reason as various MPEG4 containers use it.
1612 if (type == FOURCC('t', 'e', 'x', 't') || type == FOURCC('s', 'b', 't', 'l')) {
Gloria Wang3b573f72011-05-31 16:08:47 -07001613 mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP);
1614 }
1615
1616 *offset += chunk_size;
1617 break;
1618 }
1619
Gloria Wang7a1e3e82011-05-03 15:59:03 -07001620 case FOURCC('t', 'x', '3', 'g'):
1621 {
Gloria Wang3b573f72011-05-31 16:08:47 -07001622 uint32_t type;
1623 const void *data;
1624 size_t size = 0;
1625 if (!mLastTrack->meta->findData(
1626 kKeyTextFormatData, &type, &data, &size)) {
1627 size = 0;
1628 }
1629
1630 uint8_t *buffer = new uint8_t[size + chunk_size];
1631
1632 if (size > 0) {
1633 memcpy(buffer, data, size);
1634 }
1635
1636 if ((size_t)(mDataSource->readAt(*offset, buffer + size, chunk_size))
1637 < chunk_size) {
1638 delete[] buffer;
1639 buffer = NULL;
1640
1641 return ERROR_IO;
1642 }
1643
1644 mLastTrack->meta->setData(
1645 kKeyTextFormatData, 0, buffer, size + chunk_size);
1646
1647 delete[] buffer;
Gloria Wang7a1e3e82011-05-03 15:59:03 -07001648
1649 *offset += chunk_size;
1650 break;
1651 }
1652
James Dong515e8552011-05-25 15:02:50 -07001653 case FOURCC('c', 'o', 'v', 'r'):
1654 {
1655 if (mFileMetaData != NULL) {
Steve Block3856b092011-10-20 11:56:00 +01001656 ALOGV("chunk_data_size = %lld and data_offset = %lld",
James Dong515e8552011-05-25 15:02:50 -07001657 chunk_data_size, data_offset);
Jens Gulin2cac3fc2012-09-10 15:54:40 +02001658 sp<ABuffer> buffer = new ABuffer(chunk_data_size + 1);
James Dong515e8552011-05-25 15:02:50 -07001659 if (mDataSource->readAt(
Jens Gulin2cac3fc2012-09-10 15:54:40 +02001660 data_offset, buffer->data(), chunk_data_size) != (ssize_t)chunk_data_size) {
James Dong515e8552011-05-25 15:02:50 -07001661 return ERROR_IO;
1662 }
1663 const int kSkipBytesOfDataBox = 16;
1664 mFileMetaData->setData(
1665 kKeyAlbumArt, MetaData::TYPE_NONE,
Jens Gulin2cac3fc2012-09-10 15:54:40 +02001666 buffer->data() + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox);
James Dong515e8552011-05-25 15:02:50 -07001667 }
1668
1669 *offset += chunk_size;
1670 break;
1671 }
1672
Marco Nelissen5d2f8ba2012-03-20 10:05:06 -07001673 case FOURCC('-', '-', '-', '-'):
1674 {
1675 mLastCommentMean.clear();
1676 mLastCommentName.clear();
1677 mLastCommentData.clear();
1678 *offset += chunk_size;
1679 break;
1680 }
1681
Marco Nelissen62ad9072013-02-13 09:27:28 -08001682 case FOURCC('s', 'i', 'd', 'x'):
1683 {
1684 parseSegmentIndex(data_offset, chunk_data_size);
1685 *offset += chunk_size;
1686 return UNKNOWN_ERROR; // stop parsing after sidx
1687 }
1688
Andreas Huber20111aa2009-07-14 16:56:47 -07001689 default:
1690 {
1691 *offset += chunk_size;
1692 break;
1693 }
1694 }
1695
1696 return OK;
1697}
1698
Marco Nelissen62ad9072013-02-13 09:27:28 -08001699status_t MPEG4Extractor::parseSegmentIndex(off64_t offset, size_t size) {
1700 ALOGV("MPEG4Extractor::parseSegmentIndex");
1701
1702 if (size < 12) {
1703 return -EINVAL;
1704 }
1705
1706 uint32_t flags;
1707 if (!mDataSource->getUInt32(offset, &flags)) {
1708 return ERROR_MALFORMED;
1709 }
1710
1711 uint32_t version = flags >> 24;
1712 flags &= 0xffffff;
1713
1714 ALOGV("sidx version %d", version);
1715
1716 uint32_t referenceId;
1717 if (!mDataSource->getUInt32(offset + 4, &referenceId)) {
1718 return ERROR_MALFORMED;
1719 }
1720
1721 uint32_t timeScale;
1722 if (!mDataSource->getUInt32(offset + 8, &timeScale)) {
1723 return ERROR_MALFORMED;
1724 }
1725 ALOGV("sidx refid/timescale: %d/%d", referenceId, timeScale);
1726
1727 uint64_t earliestPresentationTime;
1728 uint64_t firstOffset;
1729
1730 offset += 12;
1731 size -= 12;
1732
1733 if (version == 0) {
1734 if (size < 8) {
1735 return -EINVAL;
1736 }
1737 uint32_t tmp;
1738 if (!mDataSource->getUInt32(offset, &tmp)) {
1739 return ERROR_MALFORMED;
1740 }
1741 earliestPresentationTime = tmp;
1742 if (!mDataSource->getUInt32(offset + 4, &tmp)) {
1743 return ERROR_MALFORMED;
1744 }
1745 firstOffset = tmp;
1746 offset += 8;
1747 size -= 8;
1748 } else {
1749 if (size < 16) {
1750 return -EINVAL;
1751 }
1752 if (!mDataSource->getUInt64(offset, &earliestPresentationTime)) {
1753 return ERROR_MALFORMED;
1754 }
1755 if (!mDataSource->getUInt64(offset + 8, &firstOffset)) {
1756 return ERROR_MALFORMED;
1757 }
1758 offset += 16;
1759 size -= 16;
1760 }
1761 ALOGV("sidx pres/off: %Ld/%Ld", earliestPresentationTime, firstOffset);
1762
1763 if (size < 4) {
1764 return -EINVAL;
1765 }
1766
1767 uint16_t referenceCount;
1768 if (!mDataSource->getUInt16(offset + 2, &referenceCount)) {
1769 return ERROR_MALFORMED;
1770 }
1771 offset += 4;
1772 size -= 4;
1773 ALOGV("refcount: %d", referenceCount);
1774
1775 if (size < referenceCount * 12) {
1776 return -EINVAL;
1777 }
1778
1779 uint64_t total_duration = 0;
1780 for (unsigned int i = 0; i < referenceCount; i++) {
1781 uint32_t d1, d2, d3;
1782
1783 if (!mDataSource->getUInt32(offset, &d1) || // size
1784 !mDataSource->getUInt32(offset + 4, &d2) || // duration
1785 !mDataSource->getUInt32(offset + 8, &d3)) { // flags
1786 return ERROR_MALFORMED;
1787 }
1788
1789 if (d1 & 0x80000000) {
1790 ALOGW("sub-sidx boxes not supported yet");
1791 }
1792 bool sap = d3 & 0x80000000;
1793 bool saptype = d3 >> 28;
1794 if (!sap || saptype > 2) {
1795 ALOGW("not a stream access point, or unsupported type");
1796 }
1797 total_duration += d2;
1798 offset += 12;
1799 ALOGV(" item %d, %08x %08x %08x", i, d1, d2, d3);
1800 SidxEntry se;
1801 se.mSize = d1 & 0x7fffffff;
1802 se.mDurationUs = 1000000LL * d2 / timeScale;
1803 mSidxEntries.add(se);
1804 }
1805
1806 mSidxDuration = total_duration * 1000000 / timeScale;
1807 ALOGV("duration: %lld", mSidxDuration);
1808
1809 int64_t metaDuration;
1810 if (!mLastTrack->meta->findInt64(kKeyDuration, &metaDuration) || metaDuration == 0) {
1811 mLastTrack->meta->setInt64(kKeyDuration, mSidxDuration);
1812 }
1813 return OK;
1814}
1815
1816
1817
Andreas Huberba529e42010-11-16 15:26:30 -08001818status_t MPEG4Extractor::parseTrackHeader(
James Dongc7fc37a2010-11-16 14:04:54 -08001819 off64_t data_offset, off64_t data_size) {
Andreas Huberba529e42010-11-16 15:26:30 -08001820 if (data_size < 4) {
1821 return ERROR_MALFORMED;
1822 }
1823
1824 uint8_t version;
1825 if (mDataSource->readAt(data_offset, &version, 1) < 1) {
1826 return ERROR_IO;
1827 }
1828
1829 size_t dynSize = (version == 1) ? 36 : 24;
1830
1831 uint8_t buffer[36 + 60];
1832
James Dongc7fc37a2010-11-16 14:04:54 -08001833 if (data_size != (off64_t)dynSize + 60) {
Andreas Huberba529e42010-11-16 15:26:30 -08001834 return ERROR_MALFORMED;
1835 }
1836
1837 if (mDataSource->readAt(
1838 data_offset, buffer, data_size) < (ssize_t)data_size) {
1839 return ERROR_IO;
1840 }
1841
1842 uint64_t ctime, mtime, duration;
1843 int32_t id;
1844
1845 if (version == 1) {
1846 ctime = U64_AT(&buffer[4]);
1847 mtime = U64_AT(&buffer[12]);
1848 id = U32_AT(&buffer[20]);
1849 duration = U64_AT(&buffer[28]);
1850 } else {
1851 CHECK_EQ((unsigned)version, 0u);
1852
1853 ctime = U32_AT(&buffer[4]);
1854 mtime = U32_AT(&buffer[8]);
1855 id = U32_AT(&buffer[12]);
1856 duration = U32_AT(&buffer[20]);
1857 }
1858
1859 mLastTrack->meta->setInt32(kKeyTrackID, id);
1860
1861 size_t matrixOffset = dynSize + 16;
1862 int32_t a00 = U32_AT(&buffer[matrixOffset]);
1863 int32_t a01 = U32_AT(&buffer[matrixOffset + 4]);
1864 int32_t dx = U32_AT(&buffer[matrixOffset + 8]);
1865 int32_t a10 = U32_AT(&buffer[matrixOffset + 12]);
1866 int32_t a11 = U32_AT(&buffer[matrixOffset + 16]);
1867 int32_t dy = U32_AT(&buffer[matrixOffset + 20]);
1868
1869#if 0
Steve Blockdf64d152012-01-04 20:05:49 +00001870 ALOGI("x' = %.2f * x + %.2f * y + %.2f",
Andreas Huberba529e42010-11-16 15:26:30 -08001871 a00 / 65536.0f, a01 / 65536.0f, dx / 65536.0f);
Steve Blockdf64d152012-01-04 20:05:49 +00001872 ALOGI("y' = %.2f * x + %.2f * y + %.2f",
Andreas Huberba529e42010-11-16 15:26:30 -08001873 a10 / 65536.0f, a11 / 65536.0f, dy / 65536.0f);
1874#endif
1875
1876 uint32_t rotationDegrees;
1877
1878 static const int32_t kFixedOne = 0x10000;
1879 if (a00 == kFixedOne && a01 == 0 && a10 == 0 && a11 == kFixedOne) {
1880 // Identity, no rotation
1881 rotationDegrees = 0;
1882 } else if (a00 == 0 && a01 == kFixedOne && a10 == -kFixedOne && a11 == 0) {
1883 rotationDegrees = 90;
1884 } else if (a00 == 0 && a01 == -kFixedOne && a10 == kFixedOne && a11 == 0) {
1885 rotationDegrees = 270;
1886 } else if (a00 == -kFixedOne && a01 == 0 && a10 == 0 && a11 == -kFixedOne) {
1887 rotationDegrees = 180;
1888 } else {
Steve Block5ff1dd52012-01-05 23:22:43 +00001889 ALOGW("We only support 0,90,180,270 degree rotation matrices");
Andreas Huberba529e42010-11-16 15:26:30 -08001890 rotationDegrees = 0;
1891 }
1892
1893 if (rotationDegrees != 0) {
1894 mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees);
1895 }
1896
James Dongb45c01c2011-01-16 11:30:13 -08001897 // Handle presentation display size, which could be different
1898 // from the image size indicated by kKeyWidth and kKeyHeight.
Andreas Huberba529e42010-11-16 15:26:30 -08001899 uint32_t width = U32_AT(&buffer[dynSize + 52]);
1900 uint32_t height = U32_AT(&buffer[dynSize + 56]);
James Dongb45c01c2011-01-16 11:30:13 -08001901 mLastTrack->meta->setInt32(kKeyDisplayWidth, width >> 16);
1902 mLastTrack->meta->setInt32(kKeyDisplayHeight, height >> 16);
Andreas Huberba529e42010-11-16 15:26:30 -08001903
1904 return OK;
1905}
1906
James Dongc7fc37a2010-11-16 14:04:54 -08001907status_t MPEG4Extractor::parseMetaData(off64_t offset, size_t size) {
Andreas Huber72b8c5a2010-01-19 16:43:53 -08001908 if (size < 4) {
1909 return ERROR_MALFORMED;
1910 }
1911
1912 uint8_t *buffer = new uint8_t[size + 1];
1913 if (mDataSource->readAt(
1914 offset, buffer, size) != (ssize_t)size) {
1915 delete[] buffer;
1916 buffer = NULL;
1917
1918 return ERROR_IO;
1919 }
1920
1921 uint32_t flags = U32_AT(buffer);
1922
1923 uint32_t metadataKey = 0;
Marco Nelissen5d2f8ba2012-03-20 10:05:06 -07001924 char chunk[5];
1925 MakeFourCCString(mPath[4], chunk);
1926 ALOGV("meta: %s @ %lld", chunk, offset);
Andreas Huber72b8c5a2010-01-19 16:43:53 -08001927 switch (mPath[4]) {
1928 case FOURCC(0xa9, 'a', 'l', 'b'):
1929 {
1930 metadataKey = kKeyAlbum;
1931 break;
1932 }
1933 case FOURCC(0xa9, 'A', 'R', 'T'):
1934 {
1935 metadataKey = kKeyArtist;
1936 break;
1937 }
Marco Nelissen66ac4df2010-02-11 13:31:44 -08001938 case FOURCC('a', 'A', 'R', 'T'):
1939 {
1940 metadataKey = kKeyAlbumArtist;
1941 break;
1942 }
Andreas Huber72b8c5a2010-01-19 16:43:53 -08001943 case FOURCC(0xa9, 'd', 'a', 'y'):
1944 {
1945 metadataKey = kKeyYear;
1946 break;
1947 }
1948 case FOURCC(0xa9, 'n', 'a', 'm'):
1949 {
1950 metadataKey = kKeyTitle;
1951 break;
1952 }
1953 case FOURCC(0xa9, 'w', 'r', 't'):
1954 {
1955 metadataKey = kKeyWriter;
1956 break;
1957 }
1958 case FOURCC('c', 'o', 'v', 'r'):
1959 {
1960 metadataKey = kKeyAlbumArt;
1961 break;
1962 }
1963 case FOURCC('g', 'n', 'r', 'e'):
1964 {
1965 metadataKey = kKeyGenre;
1966 break;
1967 }
Marco Nelissen26bae542010-02-09 14:02:16 -08001968 case FOURCC(0xa9, 'g', 'e', 'n'):
1969 {
1970 metadataKey = kKeyGenre;
1971 break;
1972 }
Marco Nelissen11f81092011-01-06 11:12:17 -08001973 case FOURCC('c', 'p', 'i', 'l'):
1974 {
1975 if (size == 9 && flags == 21) {
1976 char tmp[16];
1977 sprintf(tmp, "%d",
1978 (int)buffer[size - 1]);
1979
1980 mFileMetaData->setCString(kKeyCompilation, tmp);
1981 }
1982 break;
1983 }
Andreas Huber72b8c5a2010-01-19 16:43:53 -08001984 case FOURCC('t', 'r', 'k', 'n'):
1985 {
1986 if (size == 16 && flags == 0) {
1987 char tmp[16];
Andreas Lillvik791841a2010-10-13 15:37:01 +02001988 uint16_t* pTrack = (uint16_t*)&buffer[10];
1989 uint16_t* pTotalTracks = (uint16_t*)&buffer[12];
1990 sprintf(tmp, "%d/%d", ntohs(*pTrack), ntohs(*pTotalTracks));
Andreas Huber72b8c5a2010-01-19 16:43:53 -08001991
Andreas Huber72b8c5a2010-01-19 16:43:53 -08001992 mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
1993 }
1994 break;
1995 }
Marco Nelissen26bae542010-02-09 14:02:16 -08001996 case FOURCC('d', 'i', 's', 'k'):
1997 {
Andreas Lillvik791841a2010-10-13 15:37:01 +02001998 if ((size == 14 || size == 16) && flags == 0) {
Marco Nelissen26bae542010-02-09 14:02:16 -08001999 char tmp[16];
Andreas Lillvik791841a2010-10-13 15:37:01 +02002000 uint16_t* pDisc = (uint16_t*)&buffer[10];
2001 uint16_t* pTotalDiscs = (uint16_t*)&buffer[12];
2002 sprintf(tmp, "%d/%d", ntohs(*pDisc), ntohs(*pTotalDiscs));
Marco Nelissen26bae542010-02-09 14:02:16 -08002003
2004 mFileMetaData->setCString(kKeyDiscNumber, tmp);
2005 }
2006 break;
2007 }
Marco Nelissen5d2f8ba2012-03-20 10:05:06 -07002008 case FOURCC('-', '-', '-', '-'):
2009 {
2010 buffer[size] = '\0';
2011 switch (mPath[5]) {
2012 case FOURCC('m', 'e', 'a', 'n'):
2013 mLastCommentMean.setTo((const char *)buffer + 4);
2014 break;
2015 case FOURCC('n', 'a', 'm', 'e'):
2016 mLastCommentName.setTo((const char *)buffer + 4);
2017 break;
2018 case FOURCC('d', 'a', 't', 'a'):
2019 mLastCommentData.setTo((const char *)buffer + 8);
2020 break;
2021 }
John Grossman7abab132012-09-07 11:41:07 -07002022
2023 // Once we have a set of mean/name/data info, go ahead and process
2024 // it to see if its something we are interested in. Whether or not
2025 // were are interested in the specific tag, make sure to clear out
2026 // the set so we can be ready to process another tuple should one
2027 // show up later in the file.
2028 if ((mLastCommentMean.length() != 0) &&
2029 (mLastCommentName.length() != 0) &&
2030 (mLastCommentData.length() != 0)) {
2031
2032 if (mLastCommentMean == "com.apple.iTunes"
2033 && mLastCommentName == "iTunSMPB") {
2034 int32_t delay, padding;
2035 if (sscanf(mLastCommentData,
2036 " %*x %x %x %*x", &delay, &padding) == 2) {
2037 mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
2038 mLastTrack->meta->setInt32(kKeyEncoderPadding, padding);
2039 }
Marco Nelissen5d2f8ba2012-03-20 10:05:06 -07002040 }
John Grossman7abab132012-09-07 11:41:07 -07002041
Marco Nelissen5d2f8ba2012-03-20 10:05:06 -07002042 mLastCommentMean.clear();
2043 mLastCommentName.clear();
2044 mLastCommentData.clear();
2045 }
2046 break;
2047 }
Marco Nelissen26bae542010-02-09 14:02:16 -08002048
Andreas Huber72b8c5a2010-01-19 16:43:53 -08002049 default:
2050 break;
2051 }
2052
2053 if (size >= 8 && metadataKey) {
2054 if (metadataKey == kKeyAlbumArt) {
2055 mFileMetaData->setData(
2056 kKeyAlbumArt, MetaData::TYPE_NONE,
2057 buffer + 8, size - 8);
2058 } else if (metadataKey == kKeyGenre) {
2059 if (flags == 0) {
Marco Nelissen26bae542010-02-09 14:02:16 -08002060 // uint8_t genre code, iTunes genre codes are
2061 // the standard id3 codes, except they start
2062 // at 1 instead of 0 (e.g. Pop is 14, not 13)
2063 // We use standard id3 numbering, so subtract 1.
2064 int genrecode = (int)buffer[size - 1];
2065 genrecode--;
2066 if (genrecode < 0) {
2067 genrecode = 255; // reserved for 'unknown genre'
2068 }
Andreas Huber72b8c5a2010-01-19 16:43:53 -08002069 char genre[10];
Marco Nelissen26bae542010-02-09 14:02:16 -08002070 sprintf(genre, "%d", genrecode);
Andreas Huber72b8c5a2010-01-19 16:43:53 -08002071
2072 mFileMetaData->setCString(metadataKey, genre);
Marco Nelissen26bae542010-02-09 14:02:16 -08002073 } else if (flags == 1) {
2074 // custom genre string
2075 buffer[size] = '\0';
2076
2077 mFileMetaData->setCString(
2078 metadataKey, (const char *)buffer + 8);
Andreas Huber72b8c5a2010-01-19 16:43:53 -08002079 }
2080 } else {
2081 buffer[size] = '\0';
2082
2083 mFileMetaData->setCString(
2084 metadataKey, (const char *)buffer + 8);
2085 }
2086 }
2087
2088 delete[] buffer;
2089 buffer = NULL;
2090
2091 return OK;
2092}
2093
Andreas Huber693d2712009-08-14 14:37:10 -07002094sp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
Andreas Huber20111aa2009-07-14 16:56:47 -07002095 status_t err;
2096 if ((err = readMetaData()) != OK) {
Andreas Huber693d2712009-08-14 14:37:10 -07002097 return NULL;
Andreas Huber20111aa2009-07-14 16:56:47 -07002098 }
2099
2100 Track *track = mFirstTrack;
2101 while (index > 0) {
2102 if (track == NULL) {
Andreas Huber693d2712009-08-14 14:37:10 -07002103 return NULL;
Andreas Huber20111aa2009-07-14 16:56:47 -07002104 }
2105
2106 track = track->next;
2107 --index;
2108 }
2109
Andreas Huber371e2432009-09-09 16:32:59 -07002110 if (track == NULL) {
2111 return NULL;
2112 }
2113
Marco Nelissen5544c662013-04-08 14:30:57 -07002114 ALOGV("getTrack called, pssh: %d", mPssh.size());
2115
Andreas Huber693d2712009-08-14 14:37:10 -07002116 return new MPEG4Source(
Marco Nelissen62ad9072013-02-13 09:27:28 -08002117 track->meta, mDataSource, track->timescale, track->sampleTable,
2118 mSidxEntries, mMoofOffset);
Andreas Huber20111aa2009-07-14 16:56:47 -07002119}
2120
Andreas Huberbd5d93f2010-02-23 10:12:02 -08002121// static
2122status_t MPEG4Extractor::verifyTrack(Track *track) {
2123 const char *mime;
2124 CHECK(track->meta->findCString(kKeyMIMEType, &mime));
2125
2126 uint32_t type;
2127 const void *data;
2128 size_t size;
2129 if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
2130 if (!track->meta->findData(kKeyAVCC, &type, &data, &size)
2131 || type != kTypeAVCC) {
2132 return ERROR_MALFORMED;
2133 }
2134 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
2135 || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
2136 if (!track->meta->findData(kKeyESDS, &type, &data, &size)
2137 || type != kTypeESDS) {
2138 return ERROR_MALFORMED;
2139 }
2140 }
2141
Andreas Huber169c2862011-08-17 13:03:51 -07002142 if (!track->sampleTable->isValid()) {
2143 // Make sure we have all the metadata we need.
2144 return ERROR_MALFORMED;
2145 }
2146
Andreas Huberbd5d93f2010-02-23 10:12:02 -08002147 return OK;
2148}
2149
Andreas Huberba7c7ee2010-01-29 14:46:59 -08002150status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(
2151 const void *esds_data, size_t esds_size) {
2152 ESDS esds(esds_data, esds_size);
Andreas Huber81f82c32010-04-12 16:05:57 -07002153
2154 uint8_t objectTypeIndication;
2155 if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) {
2156 return ERROR_MALFORMED;
2157 }
2158
2159 if (objectTypeIndication == 0xe1) {
2160 // This isn't MPEG4 audio at all, it's QCELP 14k...
2161 mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
2162 return OK;
2163 }
2164
James Dong633b4c82011-02-24 21:16:54 -08002165 if (objectTypeIndication == 0x6b) {
2166 // The media subtype is MP3 audio
2167 // Our software MP3 audio decoder may not be able to handle
2168 // packetized MP3 audio; for now, lets just return ERROR_UNSUPPORTED
Steve Block29357bc2012-01-06 19:20:56 +00002169 ALOGE("MP3 track in MP4/3GPP file is not supported");
James Dong633b4c82011-02-24 21:16:54 -08002170 return ERROR_UNSUPPORTED;
2171 }
2172
Andreas Huberba7c7ee2010-01-29 14:46:59 -08002173 const uint8_t *csd;
2174 size_t csd_size;
2175 if (esds.getCodecSpecificInfo(
2176 (const void **)&csd, &csd_size) != OK) {
2177 return ERROR_MALFORMED;
2178 }
2179
2180#if 0
2181 printf("ESD of size %d\n", csd_size);
2182 hexdump(csd, csd_size);
2183#endif
2184
Andreas Hubera65ccbf2010-08-18 09:58:30 -07002185 if (csd_size == 0) {
2186 // There's no further information, i.e. no codec specific data
2187 // Let's assume that the information provided in the mpeg4 headers
2188 // is accurate and hope for the best.
2189
2190 return OK;
2191 }
2192
Andreas Huberba7c7ee2010-01-29 14:46:59 -08002193 if (csd_size < 2) {
2194 return ERROR_MALFORMED;
2195 }
2196
Dave Burkeaeb8fd42012-04-19 00:14:27 -07002197 ABitReader br(csd, csd_size);
2198 uint32_t objectType = br.getBits(5);
Andreas Huberba7c7ee2010-01-29 14:46:59 -08002199
Dave Burkeaeb8fd42012-04-19 00:14:27 -07002200 if (objectType == 31) { // AAC-ELD => additional 6 bits
2201 objectType = 32 + br.getBits(6);
Andreas Huberba7c7ee2010-01-29 14:46:59 -08002202 }
2203
Dave Burkeaeb8fd42012-04-19 00:14:27 -07002204 uint32_t freqIndex = br.getBits(4);
2205
Andreas Huberba7c7ee2010-01-29 14:46:59 -08002206 int32_t sampleRate = 0;
2207 int32_t numChannels = 0;
2208 if (freqIndex == 15) {
2209 if (csd_size < 5) {
2210 return ERROR_MALFORMED;
2211 }
Dave Burkeaeb8fd42012-04-19 00:14:27 -07002212 sampleRate = br.getBits(24);
2213 numChannels = br.getBits(4);
Andreas Huberba7c7ee2010-01-29 14:46:59 -08002214 } else {
Marco Nelissen0364a912013-03-14 14:50:47 -07002215 numChannels = br.getBits(4);
2216 if (objectType == 5) {
2217 // SBR specific config per 14496-3 table 1.13
2218 freqIndex = br.getBits(4);
2219 if (freqIndex == 15) {
2220 if (csd_size < 8) {
2221 return ERROR_MALFORMED;
2222 }
2223 sampleRate = br.getBits(24);
2224 }
Andreas Huberba7c7ee2010-01-29 14:46:59 -08002225 }
2226
Marco Nelissen0364a912013-03-14 14:50:47 -07002227 if (sampleRate == 0) {
2228 static uint32_t kSamplingRate[] = {
2229 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
2230 16000, 12000, 11025, 8000, 7350
2231 };
2232
2233 if (freqIndex == 13 || freqIndex == 14) {
2234 return ERROR_MALFORMED;
2235 }
2236
2237 sampleRate = kSamplingRate[freqIndex];
2238 }
Andreas Huberba7c7ee2010-01-29 14:46:59 -08002239 }
2240
2241 if (numChannels == 0) {
2242 return ERROR_UNSUPPORTED;
2243 }
2244
2245 int32_t prevSampleRate;
2246 CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));
2247
2248 if (prevSampleRate != sampleRate) {
Steve Block3856b092011-10-20 11:56:00 +01002249 ALOGV("mpeg4 audio sample rate different from previous setting. "
Andreas Huberba7c7ee2010-01-29 14:46:59 -08002250 "was: %d, now: %d", prevSampleRate, sampleRate);
2251 }
2252
2253 mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
2254
2255 int32_t prevChannelCount;
2256 CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount));
2257
2258 if (prevChannelCount != numChannels) {
Steve Block3856b092011-10-20 11:56:00 +01002259 ALOGV("mpeg4 audio channel count different from previous setting. "
Andreas Huberba7c7ee2010-01-29 14:46:59 -08002260 "was: %d, now: %d", prevChannelCount, numChannels);
2261 }
2262
2263 mLastTrack->meta->setInt32(kKeyChannelCount, numChannels);
2264
2265 return OK;
2266}
2267
Andreas Huber20111aa2009-07-14 16:56:47 -07002268////////////////////////////////////////////////////////////////////////////////
2269
2270MPEG4Source::MPEG4Source(
2271 const sp<MetaData> &format,
Andreas Huber693d2712009-08-14 14:37:10 -07002272 const sp<DataSource> &dataSource,
Andreas Huber48c948b2009-10-08 10:07:49 -07002273 int32_t timeScale,
Marco Nelissen62ad9072013-02-13 09:27:28 -08002274 const sp<SampleTable> &sampleTable,
2275 Vector<SidxEntry> &sidx,
2276 off64_t firstMoofOffset)
Andreas Huber20111aa2009-07-14 16:56:47 -07002277 : mFormat(format),
2278 mDataSource(dataSource),
Andreas Huber48c948b2009-10-08 10:07:49 -07002279 mTimescale(timeScale),
Andreas Huber20111aa2009-07-14 16:56:47 -07002280 mSampleTable(sampleTable),
2281 mCurrentSampleIndex(0),
Marco Nelissen62ad9072013-02-13 09:27:28 -08002282 mCurrentFragmentIndex(0),
2283 mSegments(sidx),
2284 mFirstMoofOffset(firstMoofOffset),
2285 mCurrentMoofOffset(firstMoofOffset),
2286 mCurrentTime(0),
Marco Nelissen5544c662013-04-08 14:30:57 -07002287 mCurrentSampleInfoAllocSize(0),
2288 mCurrentSampleInfoSizes(NULL),
2289 mCurrentSampleInfoOffsetsAllocSize(0),
2290 mCurrentSampleInfoOffsets(NULL),
Andreas Huber20111aa2009-07-14 16:56:47 -07002291 mIsAVC(false),
Andreas Huber60640172010-01-12 16:30:44 -08002292 mNALLengthSize(0),
Andreas Huber20111aa2009-07-14 16:56:47 -07002293 mStarted(false),
2294 mGroup(NULL),
2295 mBuffer(NULL),
Andreas Huberdbc03442009-08-19 09:29:34 -07002296 mWantsNALFragments(false),
Andreas Huber00242452009-07-28 10:03:13 -07002297 mSrcBuffer(NULL) {
Marco Nelissen5544c662013-04-08 14:30:57 -07002298
2299 mFormat->findInt32(kKeyCryptoMode, &mCryptoMode);
2300 mFormat->findInt32(kKeyCryptoDefaultIVSize, &mDefaultIVSize);
2301 uint32_t keytype;
2302 const void *key;
2303 size_t keysize;
2304 if (mFormat->findData(kKeyCryptoKey, &keytype, &key, &keysize)) {
2305 CHECK(keysize <= 16);
2306 memset(mCryptoKey, 0, 16);
2307 memcpy(mCryptoKey, key, keysize);
2308 }
2309
Andreas Huber20111aa2009-07-14 16:56:47 -07002310 const char *mime;
2311 bool success = mFormat->findCString(kKeyMIMEType, &mime);
Andreas Huberdbc03442009-08-19 09:29:34 -07002312 CHECK(success);
Andreas Huber20111aa2009-07-14 16:56:47 -07002313
Andreas Huber18291bc2009-09-10 14:13:30 -07002314 mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
Andreas Huber60640172010-01-12 16:30:44 -08002315
2316 if (mIsAVC) {
2317 uint32_t type;
2318 const void *data;
2319 size_t size;
2320 CHECK(format->findData(kKeyAVCC, &type, &data, &size));
2321
2322 const uint8_t *ptr = (const uint8_t *)data;
2323
2324 CHECK(size >= 7);
Andreas Huberba529e42010-11-16 15:26:30 -08002325 CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1
Andreas Huber60640172010-01-12 16:30:44 -08002326
2327 // The number of bytes used to encode the length of a NAL unit.
2328 mNALLengthSize = 1 + (ptr[4] & 3);
2329 }
Marco Nelissen62ad9072013-02-13 09:27:28 -08002330
2331 CHECK(format->findInt32(kKeyTrackID, &mTrackId));
2332
2333 if (mFirstMoofOffset != 0) {
2334 off64_t offset = mFirstMoofOffset;
2335 parseChunk(&offset);
2336 }
Andreas Huber20111aa2009-07-14 16:56:47 -07002337}
2338
2339MPEG4Source::~MPEG4Source() {
2340 if (mStarted) {
2341 stop();
2342 }
Marco Nelissen5544c662013-04-08 14:30:57 -07002343 free(mCurrentSampleInfoSizes);
2344 free(mCurrentSampleInfoOffsets);
Andreas Huber20111aa2009-07-14 16:56:47 -07002345}
2346
2347status_t MPEG4Source::start(MetaData *params) {
Andreas Huber7b3396a2010-02-12 10:42:02 -08002348 Mutex::Autolock autoLock(mLock);
2349
Andreas Huberdbc03442009-08-19 09:29:34 -07002350 CHECK(!mStarted);
Andreas Huber20111aa2009-07-14 16:56:47 -07002351
2352 int32_t val;
Andreas Huberdbc03442009-08-19 09:29:34 -07002353 if (params && params->findInt32(kKeyWantsNALFragments, &val)
Andreas Huber20111aa2009-07-14 16:56:47 -07002354 && val != 0) {
Andreas Huberdbc03442009-08-19 09:29:34 -07002355 mWantsNALFragments = true;
Andreas Huber20111aa2009-07-14 16:56:47 -07002356 } else {
Andreas Huberdbc03442009-08-19 09:29:34 -07002357 mWantsNALFragments = false;
Andreas Huber20111aa2009-07-14 16:56:47 -07002358 }
2359
2360 mGroup = new MediaBufferGroup;
2361
Andreas Huber738c4312009-11-23 14:03:32 -08002362 int32_t max_size;
2363 CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size));
Andreas Huber20111aa2009-07-14 16:56:47 -07002364
Andreas Huber738c4312009-11-23 14:03:32 -08002365 mGroup->add_buffer(new MediaBuffer(max_size));
Andreas Huber00242452009-07-28 10:03:13 -07002366
2367 mSrcBuffer = new uint8_t[max_size];
Andreas Huber20111aa2009-07-14 16:56:47 -07002368
2369 mStarted = true;
2370
2371 return OK;
2372}
2373
2374status_t MPEG4Source::stop() {
Andreas Huber7b3396a2010-02-12 10:42:02 -08002375 Mutex::Autolock autoLock(mLock);
2376
Andreas Huberdbc03442009-08-19 09:29:34 -07002377 CHECK(mStarted);
Andreas Huber20111aa2009-07-14 16:56:47 -07002378
2379 if (mBuffer != NULL) {
2380 mBuffer->release();
2381 mBuffer = NULL;
2382 }
2383
Andreas Huber00242452009-07-28 10:03:13 -07002384 delete[] mSrcBuffer;
2385 mSrcBuffer = NULL;
2386
Andreas Huber20111aa2009-07-14 16:56:47 -07002387 delete mGroup;
2388 mGroup = NULL;
2389
2390 mStarted = false;
2391 mCurrentSampleIndex = 0;
2392
2393 return OK;
2394}
2395
Marco Nelissen62ad9072013-02-13 09:27:28 -08002396status_t MPEG4Source::parseChunk(off64_t *offset) {
2397 uint32_t hdr[2];
2398 if (mDataSource->readAt(*offset, hdr, 8) < 8) {
2399 return ERROR_IO;
2400 }
2401 uint64_t chunk_size = ntohl(hdr[0]);
2402 uint32_t chunk_type = ntohl(hdr[1]);
2403 off64_t data_offset = *offset + 8;
2404
2405 if (chunk_size == 1) {
2406 if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
2407 return ERROR_IO;
2408 }
2409 chunk_size = ntoh64(chunk_size);
2410 data_offset += 8;
2411
2412 if (chunk_size < 16) {
2413 // The smallest valid chunk is 16 bytes long in this case.
2414 return ERROR_MALFORMED;
2415 }
2416 } else if (chunk_size < 8) {
2417 // The smallest valid chunk is 8 bytes long.
2418 return ERROR_MALFORMED;
2419 }
2420
2421 char chunk[5];
2422 MakeFourCCString(chunk_type, chunk);
2423 ALOGV("MPEG4Source chunk %s @ %llx", chunk, *offset);
2424
2425 off64_t chunk_data_size = *offset + chunk_size - data_offset;
2426
2427 switch(chunk_type) {
2428
2429 case FOURCC('t', 'r', 'a', 'f'):
2430 case FOURCC('m', 'o', 'o', 'f'): {
2431 off64_t stop_offset = *offset + chunk_size;
2432 *offset = data_offset;
2433 while (*offset < stop_offset) {
2434 status_t err = parseChunk(offset);
2435 if (err != OK) {
2436 return err;
2437 }
2438 }
2439 if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
Marco Nelissen5544c662013-04-08 14:30:57 -07002440 // *offset points to the mdat box following this moof
Marco Nelissen62ad9072013-02-13 09:27:28 -08002441 parseChunk(offset); // doesn't actually parse it, just updates offset
2442 mNextMoofOffset = *offset;
2443 }
2444 break;
2445 }
2446
2447 case FOURCC('t', 'f', 'h', 'd'): {
2448 status_t err;
2449 if ((err = parseTrackFragmentHeader(data_offset, chunk_data_size)) != OK) {
2450 return err;
2451 }
2452 *offset += chunk_size;
2453 break;
2454 }
2455
2456 case FOURCC('t', 'r', 'u', 'n'): {
2457 status_t err;
2458 if (mLastParsedTrackId == mTrackId) {
2459 if ((err = parseTrackFragmentRun(data_offset, chunk_data_size)) != OK) {
2460 return err;
2461 }
2462 }
2463
2464 *offset += chunk_size;
2465 break;
2466 }
2467
Marco Nelissen5544c662013-04-08 14:30:57 -07002468 case FOURCC('s', 'a', 'i', 'z'): {
2469 status_t err;
2470 if ((err = parseSampleAuxiliaryInformationSizes(data_offset, chunk_data_size)) != OK) {
2471 return err;
2472 }
2473 *offset += chunk_size;
2474 break;
2475 }
2476 case FOURCC('s', 'a', 'i', 'o'): {
2477 status_t err;
2478 if ((err = parseSampleAuxiliaryInformationOffsets(data_offset, chunk_data_size)) != OK) {
2479 return err;
2480 }
2481 *offset += chunk_size;
2482 break;
2483 }
2484
2485 case FOURCC('m', 'd', 'a', 't'): {
2486 // parse DRM info if present
2487 ALOGV("MPEG4Source::parseChunk mdat");
2488 // if saiz/saoi was previously observed, do something with the sampleinfos
2489 *offset += chunk_size;
2490 break;
2491 }
2492
Marco Nelissen62ad9072013-02-13 09:27:28 -08002493 default: {
2494 *offset += chunk_size;
2495 break;
2496 }
2497 }
2498 return OK;
2499}
2500
Marco Nelissen5544c662013-04-08 14:30:57 -07002501status_t MPEG4Source::parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size) {
2502 ALOGV("parseSampleAuxiliaryInformationSizes");
2503 // 14496-12 8.7.12
2504 uint8_t version;
2505 if (mDataSource->readAt(
2506 offset, &version, sizeof(version))
2507 < (ssize_t)sizeof(version)) {
2508 return ERROR_IO;
2509 }
2510
2511 if (version != 0) {
2512 return ERROR_UNSUPPORTED;
2513 }
2514 offset++;
2515
2516 uint32_t flags;
2517 if (!mDataSource->getUInt24(offset, &flags)) {
2518 return ERROR_IO;
2519 }
2520 offset += 3;
2521
2522 if (flags & 1) {
2523 uint32_t tmp;
2524 if (!mDataSource->getUInt32(offset, &tmp)) {
2525 return ERROR_MALFORMED;
2526 }
2527 mCurrentAuxInfoType = tmp;
2528 offset += 4;
2529 if (!mDataSource->getUInt32(offset, &tmp)) {
2530 return ERROR_MALFORMED;
2531 }
2532 mCurrentAuxInfoTypeParameter = tmp;
2533 offset += 4;
2534 }
2535
2536 uint8_t defsize;
2537 if (mDataSource->readAt(offset, &defsize, 1) != 1) {
2538 return ERROR_MALFORMED;
2539 }
2540 mCurrentDefaultSampleInfoSize = defsize;
2541 offset++;
2542
2543 uint32_t smplcnt;
2544 if (!mDataSource->getUInt32(offset, &smplcnt)) {
2545 return ERROR_MALFORMED;
2546 }
2547 offset += 4;
2548
2549 if (smplcnt > mCurrentSampleInfoAllocSize) {
2550 mCurrentSampleInfoSizes = (uint8_t*) realloc(mCurrentSampleInfoSizes, smplcnt);
2551 mCurrentSampleInfoAllocSize = smplcnt;
2552 }
2553 mCurrentSampleInfoCount = smplcnt;
2554
2555 mDataSource->readAt(offset, mCurrentSampleInfoSizes, smplcnt);
2556 return OK;
2557}
2558
2559status_t MPEG4Source::parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size) {
2560 ALOGV("parseSampleAuxiliaryInformationOffsets");
2561 // 14496-12 8.7.13
2562 uint8_t version;
2563 if (mDataSource->readAt(offset, &version, sizeof(version)) != 1) {
2564 return ERROR_IO;
2565 }
2566 offset++;
2567
2568 uint32_t flags;
2569 if (!mDataSource->getUInt24(offset, &flags)) {
2570 return ERROR_IO;
2571 }
2572 offset += 3;
2573
2574 uint32_t entrycount;
2575 if (!mDataSource->getUInt32(offset, &entrycount)) {
2576 return ERROR_IO;
2577 }
2578 offset += 4;
2579
2580 if (entrycount > mCurrentSampleInfoOffsetsAllocSize) {
2581 mCurrentSampleInfoOffsets = (uint64_t*) realloc(mCurrentSampleInfoOffsets, entrycount * 8);
2582 mCurrentSampleInfoOffsetsAllocSize = entrycount;
2583 }
2584 mCurrentSampleInfoOffsetCount = entrycount;
2585
2586 for (size_t i = 0; i < entrycount; i++) {
2587 if (version == 0) {
2588 uint32_t tmp;
2589 if (!mDataSource->getUInt32(offset, &tmp)) {
2590 return ERROR_IO;
2591 }
2592 mCurrentSampleInfoOffsets[i] = tmp;
2593 offset += 4;
2594 } else {
2595 uint64_t tmp;
2596 if (!mDataSource->getUInt64(offset, &tmp)) {
2597 return ERROR_IO;
2598 }
2599 mCurrentSampleInfoOffsets[i] = tmp;
2600 offset += 8;
2601 }
2602 }
2603
2604 // parse clear/encrypted data
2605
2606 off64_t drmoffset = mCurrentSampleInfoOffsets[0]; // from moof
2607
2608 drmoffset += mCurrentMoofOffset;
2609 int ivlength;
2610 CHECK(mFormat->findInt32(kKeyCryptoDefaultIVSize, &ivlength));
2611 int foo = 1;
2612 for (size_t i = 0; i < mCurrentSampleInfoCount; i++) {
2613 Sample *smpl = &mCurrentSamples.editItemAt(i);
2614
2615 memset(smpl->iv, 0, 16);
2616 if (mDataSource->readAt(drmoffset, smpl->iv, ivlength) != ivlength) {
2617 return ERROR_IO;
2618 }
2619
2620 drmoffset += ivlength;
2621
2622 uint16_t numsubsamples;
2623 if (!mDataSource->getUInt16(drmoffset, &numsubsamples)) {
2624 return ERROR_IO;
2625 }
2626 drmoffset += 2;
2627 for (size_t j = 0; j < numsubsamples; j++) {
2628 uint16_t numclear;
2629 uint32_t numencrypted;
2630 if (!mDataSource->getUInt16(drmoffset, &numclear)) {
2631 return ERROR_IO;
2632 }
2633 drmoffset += 2;
2634 if (!mDataSource->getUInt32(drmoffset, &numencrypted)) {
2635 return ERROR_IO;
2636 }
2637 drmoffset += 4;
2638 smpl->clearsizes.add(numclear);
2639 smpl->encryptedsizes.add(numencrypted);
2640 }
2641 }
2642
2643
2644 return OK;
2645}
2646
Marco Nelissen62ad9072013-02-13 09:27:28 -08002647status_t MPEG4Source::parseTrackFragmentHeader(off64_t offset, off64_t size) {
2648
2649 if (size < 8) {
2650 return -EINVAL;
2651 }
2652
2653 uint32_t flags;
Marco Nelissen5544c662013-04-08 14:30:57 -07002654 if (!mDataSource->getUInt32(offset, &flags)) { // actually version + flags
Marco Nelissen62ad9072013-02-13 09:27:28 -08002655 return ERROR_MALFORMED;
2656 }
2657
2658 if (flags & 0xff000000) {
2659 return -EINVAL;
2660 }
2661
2662 if (!mDataSource->getUInt32(offset + 4, (uint32_t*)&mLastParsedTrackId)) {
2663 return ERROR_MALFORMED;
2664 }
2665
2666 if (mLastParsedTrackId != mTrackId) {
2667 // this is not the right track, skip it
2668 return OK;
2669 }
2670
2671 mTrackFragmentHeaderInfo.mFlags = flags;
2672 mTrackFragmentHeaderInfo.mTrackID = mLastParsedTrackId;
2673 offset += 8;
2674 size -= 8;
2675
2676 ALOGV("fragment header: %08x %08x", flags, mTrackFragmentHeaderInfo.mTrackID);
2677
2678 if (flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent) {
2679 if (size < 8) {
2680 return -EINVAL;
2681 }
2682
2683 if (!mDataSource->getUInt64(offset, &mTrackFragmentHeaderInfo.mBaseDataOffset)) {
2684 return ERROR_MALFORMED;
2685 }
2686 offset += 8;
2687 size -= 8;
2688 }
2689
2690 if (flags & TrackFragmentHeaderInfo::kSampleDescriptionIndexPresent) {
2691 if (size < 4) {
2692 return -EINVAL;
2693 }
2694
2695 if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mSampleDescriptionIndex)) {
2696 return ERROR_MALFORMED;
2697 }
2698 offset += 4;
2699 size -= 4;
2700 }
2701
2702 if (flags & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
2703 if (size < 4) {
2704 return -EINVAL;
2705 }
2706
2707 if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleDuration)) {
2708 return ERROR_MALFORMED;
2709 }
2710 offset += 4;
2711 size -= 4;
2712 }
2713
2714 if (flags & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
2715 if (size < 4) {
2716 return -EINVAL;
2717 }
2718
2719 if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleSize)) {
2720 return ERROR_MALFORMED;
2721 }
2722 offset += 4;
2723 size -= 4;
2724 }
2725
2726 if (flags & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
2727 if (size < 4) {
2728 return -EINVAL;
2729 }
2730
2731 if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleFlags)) {
2732 return ERROR_MALFORMED;
2733 }
2734 offset += 4;
2735 size -= 4;
2736 }
2737
2738 if (!(flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent)) {
2739 mTrackFragmentHeaderInfo.mBaseDataOffset = mCurrentMoofOffset;
2740 }
2741
2742 mTrackFragmentHeaderInfo.mDataOffset = 0;
2743 return OK;
2744}
2745
2746status_t MPEG4Source::parseTrackFragmentRun(off64_t offset, off64_t size) {
2747
2748 ALOGV("MPEG4Extractor::parseTrackFragmentRun");
2749 if (size < 8) {
2750 return -EINVAL;
2751 }
2752
2753 enum {
2754 kDataOffsetPresent = 0x01,
2755 kFirstSampleFlagsPresent = 0x04,
2756 kSampleDurationPresent = 0x100,
2757 kSampleSizePresent = 0x200,
2758 kSampleFlagsPresent = 0x400,
2759 kSampleCompositionTimeOffsetPresent = 0x800,
2760 };
2761
2762 uint32_t flags;
2763 if (!mDataSource->getUInt32(offset, &flags)) {
2764 return ERROR_MALFORMED;
2765 }
2766 ALOGV("fragment run flags: %08x", flags);
2767
2768 if (flags & 0xff000000) {
2769 return -EINVAL;
2770 }
2771
2772 if ((flags & kFirstSampleFlagsPresent) && (flags & kSampleFlagsPresent)) {
2773 // These two shall not be used together.
2774 return -EINVAL;
2775 }
2776
2777 uint32_t sampleCount;
2778 if (!mDataSource->getUInt32(offset + 4, &sampleCount)) {
2779 return ERROR_MALFORMED;
2780 }
2781 offset += 8;
2782 size -= 8;
2783
2784 uint64_t dataOffset = mTrackFragmentHeaderInfo.mDataOffset;
2785
2786 uint32_t firstSampleFlags = 0;
2787
2788 if (flags & kDataOffsetPresent) {
2789 if (size < 4) {
2790 return -EINVAL;
2791 }
2792
2793 int32_t dataOffsetDelta;
2794 if (!mDataSource->getUInt32(offset, (uint32_t*)&dataOffsetDelta)) {
2795 return ERROR_MALFORMED;
2796 }
2797
2798 dataOffset = mTrackFragmentHeaderInfo.mBaseDataOffset + dataOffsetDelta;
2799
2800 offset += 4;
2801 size -= 4;
2802 }
2803
2804 if (flags & kFirstSampleFlagsPresent) {
2805 if (size < 4) {
2806 return -EINVAL;
2807 }
2808
2809 if (!mDataSource->getUInt32(offset, &firstSampleFlags)) {
2810 return ERROR_MALFORMED;
2811 }
2812 offset += 4;
2813 size -= 4;
2814 }
2815
2816 uint32_t sampleDuration = 0, sampleSize = 0, sampleFlags = 0,
2817 sampleCtsOffset = 0;
2818
2819 size_t bytesPerSample = 0;
2820 if (flags & kSampleDurationPresent) {
2821 bytesPerSample += 4;
2822 } else if (mTrackFragmentHeaderInfo.mFlags
2823 & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
2824 sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration;
2825 } else {
2826 sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration;
2827 }
2828
2829 if (flags & kSampleSizePresent) {
2830 bytesPerSample += 4;
2831 } else if (mTrackFragmentHeaderInfo.mFlags
2832 & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
2833 sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
2834 } else {
2835 sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
2836 }
2837
2838 if (flags & kSampleFlagsPresent) {
2839 bytesPerSample += 4;
2840 } else if (mTrackFragmentHeaderInfo.mFlags
2841 & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
2842 sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
2843 } else {
2844 sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
2845 }
2846
2847 if (flags & kSampleCompositionTimeOffsetPresent) {
2848 bytesPerSample += 4;
2849 } else {
2850 sampleCtsOffset = 0;
2851 }
2852
2853 if (size < sampleCount * bytesPerSample) {
2854 return -EINVAL;
2855 }
2856
2857 Sample tmp;
2858 for (uint32_t i = 0; i < sampleCount; ++i) {
2859 if (flags & kSampleDurationPresent) {
2860 if (!mDataSource->getUInt32(offset, &sampleDuration)) {
2861 return ERROR_MALFORMED;
2862 }
2863 offset += 4;
2864 }
2865
2866 if (flags & kSampleSizePresent) {
2867 if (!mDataSource->getUInt32(offset, &sampleSize)) {
2868 return ERROR_MALFORMED;
2869 }
2870 offset += 4;
2871 }
2872
2873 if (flags & kSampleFlagsPresent) {
2874 if (!mDataSource->getUInt32(offset, &sampleFlags)) {
2875 return ERROR_MALFORMED;
2876 }
2877 offset += 4;
2878 }
2879
2880 if (flags & kSampleCompositionTimeOffsetPresent) {
2881 if (!mDataSource->getUInt32(offset, &sampleCtsOffset)) {
2882 return ERROR_MALFORMED;
2883 }
2884 offset += 4;
2885 }
2886
Marco Nelissen5544c662013-04-08 14:30:57 -07002887 ALOGV("adding sample %d at offset 0x%08llx, size %u, duration %u, "
2888 " flags 0x%08x", i + 1,
Marco Nelissen62ad9072013-02-13 09:27:28 -08002889 dataOffset, sampleSize, sampleDuration,
2890 (flags & kFirstSampleFlagsPresent) && i == 0
2891 ? firstSampleFlags : sampleFlags);
2892 tmp.offset = dataOffset;
2893 tmp.size = sampleSize;
2894 tmp.duration = sampleDuration;
2895 mCurrentSamples.add(tmp);
2896
2897 dataOffset += sampleSize;
2898 }
2899
2900 mTrackFragmentHeaderInfo.mDataOffset = dataOffset;
2901
2902 return OK;
2903}
2904
Andreas Huber20111aa2009-07-14 16:56:47 -07002905sp<MetaData> MPEG4Source::getFormat() {
Andreas Huber7b3396a2010-02-12 10:42:02 -08002906 Mutex::Autolock autoLock(mLock);
2907
Andreas Huber20111aa2009-07-14 16:56:47 -07002908 return mFormat;
2909}
2910
Andreas Huber60640172010-01-12 16:30:44 -08002911size_t MPEG4Source::parseNALSize(const uint8_t *data) const {
2912 switch (mNALLengthSize) {
2913 case 1:
2914 return *data;
2915 case 2:
2916 return U16_AT(data);
2917 case 3:
2918 return ((size_t)data[0] << 16) | U16_AT(&data[1]);
2919 case 4:
2920 return U32_AT(data);
2921 }
2922
2923 // This cannot happen, mNALLengthSize springs to life by adding 1 to
2924 // a 2-bit integer.
2925 CHECK(!"Should not be here.");
2926
2927 return 0;
2928}
2929
Andreas Huber20111aa2009-07-14 16:56:47 -07002930status_t MPEG4Source::read(
2931 MediaBuffer **out, const ReadOptions *options) {
Andreas Huber7b3396a2010-02-12 10:42:02 -08002932 Mutex::Autolock autoLock(mLock);
2933
Andreas Huberdbc03442009-08-19 09:29:34 -07002934 CHECK(mStarted);
Andreas Huber20111aa2009-07-14 16:56:47 -07002935
Marco Nelissen62ad9072013-02-13 09:27:28 -08002936 if (mFirstMoofOffset > 0) {
2937 return fragmentedRead(out, options);
2938 }
2939
Andreas Huber20111aa2009-07-14 16:56:47 -07002940 *out = NULL;
2941
Andreas Huberabd1f4f2010-07-20 15:04:28 -07002942 int64_t targetSampleTimeUs = -1;
2943
Andreas Huber20111aa2009-07-14 16:56:47 -07002944 int64_t seekTimeUs;
Andreas Huberabd1f4f2010-07-20 15:04:28 -07002945 ReadOptions::SeekMode mode;
2946 if (options && options->getSeekTo(&seekTimeUs, &mode)) {
2947 uint32_t findFlags = 0;
2948 switch (mode) {
2949 case ReadOptions::SEEK_PREVIOUS_SYNC:
2950 findFlags = SampleTable::kFlagBefore;
2951 break;
2952 case ReadOptions::SEEK_NEXT_SYNC:
2953 findFlags = SampleTable::kFlagAfter;
2954 break;
2955 case ReadOptions::SEEK_CLOSEST_SYNC:
2956 case ReadOptions::SEEK_CLOSEST:
2957 findFlags = SampleTable::kFlagClosest;
2958 break;
2959 default:
2960 CHECK(!"Should not be here.");
2961 break;
2962 }
2963
Andreas Huber20111aa2009-07-14 16:56:47 -07002964 uint32_t sampleIndex;
Andreas Huberabd1f4f2010-07-20 15:04:28 -07002965 status_t err = mSampleTable->findSampleAtTime(
Andreas Huber20111aa2009-07-14 16:56:47 -07002966 seekTimeUs * mTimescale / 1000000,
Andreas Huberabd1f4f2010-07-20 15:04:28 -07002967 &sampleIndex, findFlags);
2968
2969 if (mode == ReadOptions::SEEK_CLOSEST) {
2970 // We found the closest sample already, now we want the sync
2971 // sample preceding it (or the sample itself of course), even
2972 // if the subsequent sync sample is closer.
2973 findFlags = SampleTable::kFlagBefore;
2974 }
2975
2976 uint32_t syncSampleIndex;
2977 if (err == OK) {
2978 err = mSampleTable->findSyncSampleNear(
2979 sampleIndex, &syncSampleIndex, findFlags);
2980 }
Andreas Huber20111aa2009-07-14 16:56:47 -07002981
Andreas Huber788a07f2011-10-06 09:07:12 -07002982 uint32_t sampleTime;
2983 if (err == OK) {
2984 err = mSampleTable->getMetaDataForSample(
2985 sampleIndex, NULL, NULL, &sampleTime);
2986 }
2987
Andreas Huber20111aa2009-07-14 16:56:47 -07002988 if (err != OK) {
Andreas Huber5295c0c2010-02-23 13:45:33 -08002989 if (err == ERROR_OUT_OF_RANGE) {
2990 // An attempt to seek past the end of the stream would
2991 // normally cause this ERROR_OUT_OF_RANGE error. Propagating
2992 // this all the way to the MediaPlayer would cause abnormal
2993 // termination. Legacy behaviour appears to be to behave as if
2994 // we had seeked to the end of stream, ending normally.
2995 err = ERROR_END_OF_STREAM;
2996 }
Marco Nelissen62ad9072013-02-13 09:27:28 -08002997 ALOGV("end of stream");
Andreas Huber20111aa2009-07-14 16:56:47 -07002998 return err;
2999 }
3000
Andreas Huberabd1f4f2010-07-20 15:04:28 -07003001 if (mode == ReadOptions::SEEK_CLOSEST) {
3002 targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
3003 }
3004
3005#if 0
3006 uint32_t syncSampleTime;
3007 CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
3008 syncSampleIndex, NULL, NULL, &syncSampleTime));
3009
Steve Blockdf64d152012-01-04 20:05:49 +00003010 ALOGI("seek to time %lld us => sample at time %lld us, "
Andreas Huberabd1f4f2010-07-20 15:04:28 -07003011 "sync sample at time %lld us",
3012 seekTimeUs,
3013 sampleTime * 1000000ll / mTimescale,
3014 syncSampleTime * 1000000ll / mTimescale);
3015#endif
3016
3017 mCurrentSampleIndex = syncSampleIndex;
Andreas Huber20111aa2009-07-14 16:56:47 -07003018 if (mBuffer != NULL) {
3019 mBuffer->release();
3020 mBuffer = NULL;
3021 }
3022
3023 // fall through
3024 }
3025
James Dongc7fc37a2010-11-16 14:04:54 -08003026 off64_t offset;
Andreas Huber00242452009-07-28 10:03:13 -07003027 size_t size;
Andreas Huber4678a6d2011-04-15 11:52:29 -07003028 uint32_t cts;
Andreas Huber8bf59e72010-08-06 14:13:10 -07003029 bool isSyncSample;
Andreas Huberdbc03442009-08-19 09:29:34 -07003030 bool newBuffer = false;
3031 if (mBuffer == NULL) {
3032 newBuffer = true;
Andreas Huber20111aa2009-07-14 16:56:47 -07003033
Andreas Huberc57b6792010-01-19 10:39:21 -08003034 status_t err =
3035 mSampleTable->getMetaDataForSample(
Andreas Huber4678a6d2011-04-15 11:52:29 -07003036 mCurrentSampleIndex, &offset, &size, &cts, &isSyncSample);
Andreas Huberdbc03442009-08-19 09:29:34 -07003037
3038 if (err != OK) {
3039 return err;
3040 }
3041
3042 err = mGroup->acquire_buffer(&mBuffer);
Andreas Huberc57b6792010-01-19 10:39:21 -08003043
Andreas Huberdbc03442009-08-19 09:29:34 -07003044 if (err != OK) {
Andreas Huberba529e42010-11-16 15:26:30 -08003045 CHECK(mBuffer == NULL);
Andreas Huberdbc03442009-08-19 09:29:34 -07003046 return err;
3047 }
Andreas Huber00242452009-07-28 10:03:13 -07003048 }
Andreas Huber20111aa2009-07-14 16:56:47 -07003049
Andreas Huberdbc03442009-08-19 09:29:34 -07003050 if (!mIsAVC || mWantsNALFragments) {
3051 if (newBuffer) {
3052 ssize_t num_bytes_read =
Andreas Huber34769bc2009-10-23 10:22:30 -07003053 mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
Andreas Huber20111aa2009-07-14 16:56:47 -07003054
Andreas Huberdbc03442009-08-19 09:29:34 -07003055 if (num_bytes_read < (ssize_t)size) {
3056 mBuffer->release();
3057 mBuffer = NULL;
3058
3059 return ERROR_IO;
3060 }
3061
Andreas Huber7b3396a2010-02-12 10:42:02 -08003062 CHECK(mBuffer != NULL);
Andreas Huberdbc03442009-08-19 09:29:34 -07003063 mBuffer->set_range(0, size);
3064 mBuffer->meta_data()->clear();
Andreas Huber48c948b2009-10-08 10:07:49 -07003065 mBuffer->meta_data()->setInt64(
Andreas Huber4678a6d2011-04-15 11:52:29 -07003066 kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
Andreas Huberabd1f4f2010-07-20 15:04:28 -07003067
3068 if (targetSampleTimeUs >= 0) {
3069 mBuffer->meta_data()->setInt64(
3070 kKeyTargetTime, targetSampleTimeUs);
3071 }
3072
Andreas Huber8bf59e72010-08-06 14:13:10 -07003073 if (isSyncSample) {
3074 mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
3075 }
3076
Andreas Huberdbc03442009-08-19 09:29:34 -07003077 ++mCurrentSampleIndex;
3078 }
3079
3080 if (!mIsAVC) {
3081 *out = mBuffer;
3082 mBuffer = NULL;
3083
3084 return OK;
3085 }
3086
3087 // Each NAL unit is split up into its constituent fragments and
3088 // each one of them returned in its own buffer.
3089
Andreas Huber60640172010-01-12 16:30:44 -08003090 CHECK(mBuffer->range_length() >= mNALLengthSize);
Andreas Huberdbc03442009-08-19 09:29:34 -07003091
3092 const uint8_t *src =
3093 (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
3094
Andreas Huber60640172010-01-12 16:30:44 -08003095 size_t nal_size = parseNALSize(src);
Andreas Hubere8a08492010-01-14 14:13:15 -08003096 if (mBuffer->range_length() < mNALLengthSize + nal_size) {
Steve Block29357bc2012-01-06 19:20:56 +00003097 ALOGE("incomplete NAL unit.");
Andreas Hubere8a08492010-01-14 14:13:15 -08003098
3099 mBuffer->release();
3100 mBuffer = NULL;
3101
3102 return ERROR_MALFORMED;
3103 }
Andreas Huberdbc03442009-08-19 09:29:34 -07003104
3105 MediaBuffer *clone = mBuffer->clone();
Andreas Huber7b3396a2010-02-12 10:42:02 -08003106 CHECK(clone != NULL);
Andreas Huber60640172010-01-12 16:30:44 -08003107 clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
Andreas Huberdbc03442009-08-19 09:29:34 -07003108
Andreas Huber7b3396a2010-02-12 10:42:02 -08003109 CHECK(mBuffer != NULL);
Andreas Huberdbc03442009-08-19 09:29:34 -07003110 mBuffer->set_range(
Andreas Huber60640172010-01-12 16:30:44 -08003111 mBuffer->range_offset() + mNALLengthSize + nal_size,
3112 mBuffer->range_length() - mNALLengthSize - nal_size);
Andreas Huberdbc03442009-08-19 09:29:34 -07003113
3114 if (mBuffer->range_length() == 0) {
3115 mBuffer->release();
3116 mBuffer = NULL;
3117 }
3118
3119 *out = clone;
3120
3121 return OK;
3122 } else {
3123 // Whole NAL units are returned but each fragment is prefixed by
3124 // the start code (0x00 00 00 01).
Gloria Wangdcd25ef2010-06-22 13:55:38 -07003125 ssize_t num_bytes_read = 0;
3126 int32_t drm = 0;
3127 bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
3128 if (usesDRM) {
3129 num_bytes_read =
3130 mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
3131 } else {
3132 num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
3133 }
Andreas Huber20111aa2009-07-14 16:56:47 -07003134
3135 if (num_bytes_read < (ssize_t)size) {
3136 mBuffer->release();
3137 mBuffer = NULL;
3138
Andreas Huberdbc03442009-08-19 09:29:34 -07003139 return ERROR_IO;
Andreas Huber20111aa2009-07-14 16:56:47 -07003140 }
3141
Gloria Wangdcd25ef2010-06-22 13:55:38 -07003142 if (usesDRM) {
3143 CHECK(mBuffer != NULL);
3144 mBuffer->set_range(0, size);
Andreas Huber60640172010-01-12 16:30:44 -08003145
Gloria Wangdcd25ef2010-06-22 13:55:38 -07003146 } else {
3147 uint8_t *dstData = (uint8_t *)mBuffer->data();
3148 size_t srcOffset = 0;
3149 size_t dstOffset = 0;
Andreas Hubere8a08492010-01-14 14:13:15 -08003150
Gloria Wangdcd25ef2010-06-22 13:55:38 -07003151 while (srcOffset < size) {
James Dong34fe2522011-04-22 13:21:03 -07003152 bool isMalFormed = (srcOffset + mNALLengthSize > size);
3153 size_t nalLength = 0;
3154 if (!isMalFormed) {
3155 nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
3156 srcOffset += mNALLengthSize;
3157 isMalFormed = srcOffset + nalLength > size;
3158 }
Andreas Hubere8a08492010-01-14 14:13:15 -08003159
James Dong34fe2522011-04-22 13:21:03 -07003160 if (isMalFormed) {
Steve Block29357bc2012-01-06 19:20:56 +00003161 ALOGE("Video is malformed");
Gloria Wangdcd25ef2010-06-22 13:55:38 -07003162 mBuffer->release();
3163 mBuffer = NULL;
Gloria Wangdcd25ef2010-06-22 13:55:38 -07003164 return ERROR_MALFORMED;
3165 }
3166
3167 if (nalLength == 0) {
3168 continue;
3169 }
3170
3171 CHECK(dstOffset + 4 <= mBuffer->size());
3172
3173 dstData[dstOffset++] = 0;
3174 dstData[dstOffset++] = 0;
3175 dstData[dstOffset++] = 0;
3176 dstData[dstOffset++] = 1;
3177 memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
3178 srcOffset += nalLength;
3179 dstOffset += nalLength;
Andreas Hubere8a08492010-01-14 14:13:15 -08003180 }
Gloria Wangdcd25ef2010-06-22 13:55:38 -07003181 CHECK_EQ(srcOffset, size);
3182 CHECK(mBuffer != NULL);
3183 mBuffer->set_range(0, dstOffset);
Andreas Huberdbc03442009-08-19 09:29:34 -07003184 }
3185
Andreas Huber20111aa2009-07-14 16:56:47 -07003186 mBuffer->meta_data()->clear();
Andreas Huber48c948b2009-10-08 10:07:49 -07003187 mBuffer->meta_data()->setInt64(
Andreas Huber4678a6d2011-04-15 11:52:29 -07003188 kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
Andreas Huberabd1f4f2010-07-20 15:04:28 -07003189
3190 if (targetSampleTimeUs >= 0) {
3191 mBuffer->meta_data()->setInt64(
3192 kKeyTargetTime, targetSampleTimeUs);
3193 }
3194
Andreas Huber8bf59e72010-08-06 14:13:10 -07003195 if (isSyncSample) {
3196 mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
3197 }
3198
Andreas Huber20111aa2009-07-14 16:56:47 -07003199 ++mCurrentSampleIndex;
3200
Andreas Huber20111aa2009-07-14 16:56:47 -07003201 *out = mBuffer;
3202 mBuffer = NULL;
3203
3204 return OK;
3205 }
Andreas Huber20111aa2009-07-14 16:56:47 -07003206}
3207
Marco Nelissen62ad9072013-02-13 09:27:28 -08003208status_t MPEG4Source::fragmentedRead(
3209 MediaBuffer **out, const ReadOptions *options) {
3210
3211 ALOGV("MPEG4Source::fragmentedRead");
3212
3213 CHECK(mStarted);
3214
3215 *out = NULL;
3216
3217 int64_t targetSampleTimeUs = -1;
3218
3219 int64_t seekTimeUs;
3220 ReadOptions::SeekMode mode;
3221 if (options && options->getSeekTo(&seekTimeUs, &mode)) {
3222
3223 int numSidxEntries = mSegments.size();
3224 if (numSidxEntries != 0) {
3225 int64_t totalTime = 0;
3226 off64_t totalOffset = mFirstMoofOffset;
3227 for (int i = 0; i < numSidxEntries; i++) {
3228 const SidxEntry *se = &mSegments[i];
3229 if (totalTime + se->mDurationUs > seekTimeUs) {
3230 // The requested time is somewhere in this segment
3231 if ((mode == ReadOptions::SEEK_NEXT_SYNC) ||
3232 (mode == ReadOptions::SEEK_CLOSEST_SYNC &&
3233 (seekTimeUs - totalTime) > (totalTime + se->mDurationUs - seekTimeUs))) {
3234 // requested next sync, or closest sync and it was closer to the end of
3235 // this segment
3236 totalTime += se->mDurationUs;
3237 totalOffset += se->mSize;
3238 }
3239 break;
3240 }
3241 totalTime += se->mDurationUs;
3242 totalOffset += se->mSize;
3243 }
3244 mCurrentMoofOffset = totalOffset;
3245 mCurrentSamples.clear();
3246 mCurrentSampleIndex = 0;
3247 parseChunk(&totalOffset);
3248 mCurrentTime = totalTime * mTimescale / 1000000ll;
3249 }
3250
3251 if (mBuffer != NULL) {
3252 mBuffer->release();
3253 mBuffer = NULL;
3254 }
3255
3256 // fall through
3257 }
3258
3259 off64_t offset = 0;
3260 size_t size;
3261 uint32_t cts = 0;
3262 bool isSyncSample = false;
3263 bool newBuffer = false;
3264 if (mBuffer == NULL) {
3265 newBuffer = true;
3266
3267 if (mCurrentSampleIndex >= mCurrentSamples.size()) {
3268 // move to next fragment
3269 Sample lastSample = mCurrentSamples[mCurrentSamples.size() - 1];
3270 off64_t nextMoof = mNextMoofOffset; // lastSample.offset + lastSample.size;
3271 mCurrentMoofOffset = nextMoof;
3272 mCurrentSamples.clear();
3273 mCurrentSampleIndex = 0;
3274 parseChunk(&nextMoof);
3275 if (mCurrentSampleIndex >= mCurrentSamples.size()) {
3276 return ERROR_END_OF_STREAM;
3277 }
3278 }
3279
3280 const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
3281 offset = smpl->offset;
3282 size = smpl->size;
3283 cts = mCurrentTime;
3284 mCurrentTime += smpl->duration;
3285 isSyncSample = (mCurrentSampleIndex == 0); // XXX
3286
3287 status_t err = mGroup->acquire_buffer(&mBuffer);
3288
3289 if (err != OK) {
3290 CHECK(mBuffer == NULL);
3291 ALOGV("acquire_buffer returned %d", err);
3292 return err;
3293 }
3294 }
3295
3296 if (!mIsAVC || mWantsNALFragments) {
3297 if (newBuffer) {
3298 ssize_t num_bytes_read =
3299 mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
3300
3301 if (num_bytes_read < (ssize_t)size) {
3302 mBuffer->release();
3303 mBuffer = NULL;
3304
3305 ALOGV("i/o error");
3306 return ERROR_IO;
3307 }
3308
3309 CHECK(mBuffer != NULL);
3310 mBuffer->set_range(0, size);
3311 mBuffer->meta_data()->clear();
3312 mBuffer->meta_data()->setInt64(
3313 kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
3314
3315 if (targetSampleTimeUs >= 0) {
3316 mBuffer->meta_data()->setInt64(
3317 kKeyTargetTime, targetSampleTimeUs);
3318 }
3319
3320 if (isSyncSample) {
3321 mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
3322 }
3323
3324 ++mCurrentSampleIndex;
3325 }
3326
3327 if (!mIsAVC) {
3328 *out = mBuffer;
3329 mBuffer = NULL;
3330
3331 return OK;
3332 }
3333
3334 // Each NAL unit is split up into its constituent fragments and
3335 // each one of them returned in its own buffer.
3336
3337 CHECK(mBuffer->range_length() >= mNALLengthSize);
3338
3339 const uint8_t *src =
3340 (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
3341
3342 size_t nal_size = parseNALSize(src);
3343 if (mBuffer->range_length() < mNALLengthSize + nal_size) {
3344 ALOGE("incomplete NAL unit.");
3345
3346 mBuffer->release();
3347 mBuffer = NULL;
3348
3349 return ERROR_MALFORMED;
3350 }
3351
3352 MediaBuffer *clone = mBuffer->clone();
3353 CHECK(clone != NULL);
3354 clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
3355
3356 CHECK(mBuffer != NULL);
3357 mBuffer->set_range(
3358 mBuffer->range_offset() + mNALLengthSize + nal_size,
3359 mBuffer->range_length() - mNALLengthSize - nal_size);
3360
3361 if (mBuffer->range_length() == 0) {
3362 mBuffer->release();
3363 mBuffer = NULL;
3364 }
3365
3366 *out = clone;
3367
3368 return OK;
3369 } else {
3370 ALOGV("whole NAL");
3371 // Whole NAL units are returned but each fragment is prefixed by
3372 // the start code (0x00 00 00 01).
3373 ssize_t num_bytes_read = 0;
3374 int32_t drm = 0;
3375 bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
3376 if (usesDRM) {
3377 num_bytes_read =
3378 mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
3379 } else {
3380 num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
3381 }
3382
3383 if (num_bytes_read < (ssize_t)size) {
3384 mBuffer->release();
3385 mBuffer = NULL;
3386
3387 ALOGV("i/o error");
3388 return ERROR_IO;
3389 }
3390
3391 if (usesDRM) {
3392 CHECK(mBuffer != NULL);
3393 mBuffer->set_range(0, size);
3394
3395 } else {
3396 uint8_t *dstData = (uint8_t *)mBuffer->data();
3397 size_t srcOffset = 0;
3398 size_t dstOffset = 0;
3399
3400 while (srcOffset < size) {
3401 bool isMalFormed = (srcOffset + mNALLengthSize > size);
3402 size_t nalLength = 0;
3403 if (!isMalFormed) {
3404 nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
3405 srcOffset += mNALLengthSize;
3406 isMalFormed = srcOffset + nalLength > size;
3407 }
3408
3409 if (isMalFormed) {
3410 ALOGE("Video is malformed");
3411 mBuffer->release();
3412 mBuffer = NULL;
3413 return ERROR_MALFORMED;
3414 }
3415
3416 if (nalLength == 0) {
3417 continue;
3418 }
3419
3420 CHECK(dstOffset + 4 <= mBuffer->size());
3421
3422 dstData[dstOffset++] = 0;
3423 dstData[dstOffset++] = 0;
3424 dstData[dstOffset++] = 0;
3425 dstData[dstOffset++] = 1;
3426 memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
3427 srcOffset += nalLength;
3428 dstOffset += nalLength;
3429 }
3430 CHECK_EQ(srcOffset, size);
3431 CHECK(mBuffer != NULL);
3432 mBuffer->set_range(0, dstOffset);
3433 }
3434
3435 mBuffer->meta_data()->clear();
3436 mBuffer->meta_data()->setInt64(
3437 kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
3438
3439 if (targetSampleTimeUs >= 0) {
3440 mBuffer->meta_data()->setInt64(
3441 kKeyTargetTime, targetSampleTimeUs);
3442 }
3443
3444 if (isSyncSample) {
3445 mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
3446 }
3447
Marco Nelissen5544c662013-04-08 14:30:57 -07003448 const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
3449 if (smpl->encryptedsizes.size()) {
3450 // store clear/encrypted lengths in metadata
3451 sp<MetaData> bufmeta = mBuffer->meta_data();
3452 bufmeta->setData(kKeyPlainSizes, 0,
3453 smpl->clearsizes.array(), smpl->clearsizes.size() * 4);
3454 bufmeta->setData(kKeyEncryptedSizes, 0,
3455 smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4);
3456 bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size?
3457 bufmeta->setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize);
3458 bufmeta->setInt32(kKeyCryptoMode, mCryptoMode);
3459 bufmeta->setData(kKeyCryptoKey, 0, mCryptoKey, 16);
3460 }
3461
Marco Nelissen62ad9072013-02-13 09:27:28 -08003462 ++mCurrentSampleIndex;
3463
3464 *out = mBuffer;
3465 mBuffer = NULL;
3466
3467 return OK;
3468 }
3469}
3470
Andreas Huberbdba1f22011-03-03 13:48:41 -08003471MPEG4Extractor::Track *MPEG4Extractor::findTrackByMimePrefix(
3472 const char *mimePrefix) {
3473 for (Track *track = mFirstTrack; track != NULL; track = track->next) {
3474 const char *mime;
3475 if (track->meta != NULL
3476 && track->meta->findCString(kKeyMIMEType, &mime)
3477 && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) {
3478 return track;
3479 }
3480 }
3481
3482 return NULL;
3483}
3484
Andreas Huber1b52bd22010-05-27 09:59:54 -07003485static bool LegacySniffMPEG4(
Andreas Huber693d2712009-08-14 14:37:10 -07003486 const sp<DataSource> &source, String8 *mimeType, float *confidence) {
Andreas Huber20111aa2009-07-14 16:56:47 -07003487 uint8_t header[8];
3488
Andreas Huber34769bc2009-10-23 10:22:30 -07003489 ssize_t n = source->readAt(4, header, sizeof(header));
Andreas Huber20111aa2009-07-14 16:56:47 -07003490 if (n < (ssize_t)sizeof(header)) {
3491 return false;
3492 }
3493
3494 if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
James Dongb9dbba92010-04-13 15:06:41 -07003495 || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8)
3496 || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8)
Andreas Huber0dba7372009-11-03 16:00:58 -08003497 || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
Andreas Huberea5ea102010-02-25 15:59:24 -08003498 || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)
Andreas Huber983b4492010-04-01 11:42:50 -07003499 || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) {
Andreas Huber18291bc2009-09-10 14:13:30 -07003500 *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
Andreas Huber5a1c3522010-08-25 11:09:41 -07003501 *confidence = 0.4;
Andreas Huber20111aa2009-07-14 16:56:47 -07003502
3503 return true;
3504 }
3505
3506 return false;
3507}
3508
Andreas Huber1b52bd22010-05-27 09:59:54 -07003509static bool isCompatibleBrand(uint32_t fourcc) {
3510 static const uint32_t kCompatibleBrands[] = {
3511 FOURCC('i', 's', 'o', 'm'),
3512 FOURCC('i', 's', 'o', '2'),
3513 FOURCC('a', 'v', 'c', '1'),
3514 FOURCC('3', 'g', 'p', '4'),
3515 FOURCC('m', 'p', '4', '1'),
3516 FOURCC('m', 'p', '4', '2'),
James Dong4cb2c4d2011-04-07 17:57:04 -07003517
3518 // Won't promise that the following file types can be played.
3519 // Just give these file types a chance.
3520 FOURCC('q', 't', ' ', ' '), // Apple's QuickTime
3521 FOURCC('M', 'S', 'N', 'V'), // Sony's PSP
Andreas Huber58fb3912011-05-17 10:12:34 -07003522
3523 FOURCC('3', 'g', '2', 'a'), // 3GPP2
3524 FOURCC('3', 'g', '2', 'b'),
Andreas Huber1b52bd22010-05-27 09:59:54 -07003525 };
3526
3527 for (size_t i = 0;
3528 i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]);
3529 ++i) {
3530 if (kCompatibleBrands[i] == fourcc) {
3531 return true;
3532 }
3533 }
3534
3535 return false;
3536}
3537
3538// Attempt to actually parse the 'ftyp' atom and determine if a suitable
3539// compatible brand is present.
Andreas Hubera0f2bf52011-12-05 11:34:43 -08003540// Also try to identify where this file's metadata ends
3541// (end of the 'moov' atom) and report it to the caller as part of
3542// the metadata.
Andreas Huber1b52bd22010-05-27 09:59:54 -07003543static bool BetterSniffMPEG4(
Andreas Hubera0f2bf52011-12-05 11:34:43 -08003544 const sp<DataSource> &source, String8 *mimeType, float *confidence,
3545 sp<AMessage> *meta) {
3546 // We scan up to 128 bytes to identify this file as an MP4.
3547 static const off64_t kMaxScanOffset = 128ll;
Andreas Huber1b52bd22010-05-27 09:59:54 -07003548
Andreas Hubera0f2bf52011-12-05 11:34:43 -08003549 off64_t offset = 0ll;
3550 bool foundGoodFileType = false;
3551 off64_t moovAtomEndOffset = -1ll;
3552 bool done = false;
Andreas Huber1b52bd22010-05-27 09:59:54 -07003553
Andreas Hubera0f2bf52011-12-05 11:34:43 -08003554 while (!done && offset < kMaxScanOffset) {
3555 uint32_t hdr[2];
3556 if (source->readAt(offset, hdr, 8) < 8) {
3557 return false;
3558 }
3559
3560 uint64_t chunkSize = ntohl(hdr[0]);
3561 uint32_t chunkType = ntohl(hdr[1]);
3562 off64_t chunkDataOffset = offset + 8;
3563
3564 if (chunkSize == 1) {
3565 if (source->readAt(offset + 8, &chunkSize, 8) < 8) {
Andreas Huber1b52bd22010-05-27 09:59:54 -07003566 return false;
3567 }
3568
Andreas Hubera0f2bf52011-12-05 11:34:43 -08003569 chunkSize = ntoh64(chunkSize);
3570 chunkDataOffset += 8;
3571
3572 if (chunkSize < 16) {
3573 // The smallest valid chunk is 16 bytes long in this case.
3574 return false;
3575 }
3576 } else if (chunkSize < 8) {
3577 // The smallest valid chunk is 8 bytes long.
3578 return false;
3579 }
3580
3581 off64_t chunkDataSize = offset + chunkSize - chunkDataOffset;
3582
Marco Nelissen62ad9072013-02-13 09:27:28 -08003583 char chunkstring[5];
3584 MakeFourCCString(chunkType, chunkstring);
3585 ALOGV("saw chunk type %s, size %lld @ %lld", chunkstring, chunkSize, offset);
Andreas Hubera0f2bf52011-12-05 11:34:43 -08003586 switch (chunkType) {
3587 case FOURCC('f', 't', 'y', 'p'):
3588 {
3589 if (chunkDataSize < 8) {
3590 return false;
3591 }
3592
3593 uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4;
3594 for (size_t i = 0; i < numCompatibleBrands + 2; ++i) {
3595 if (i == 1) {
3596 // Skip this index, it refers to the minorVersion,
3597 // not a brand.
3598 continue;
3599 }
3600
3601 uint32_t brand;
3602 if (source->readAt(
3603 chunkDataOffset + 4 * i, &brand, 4) < 4) {
3604 return false;
3605 }
3606
3607 brand = ntohl(brand);
3608
3609 if (isCompatibleBrand(brand)) {
3610 foundGoodFileType = true;
3611 break;
3612 }
3613 }
3614
3615 if (!foundGoodFileType) {
3616 return false;
3617 }
3618
Andreas Huber1b52bd22010-05-27 09:59:54 -07003619 break;
3620 }
Andreas Hubera0f2bf52011-12-05 11:34:43 -08003621
3622 case FOURCC('m', 'o', 'o', 'v'):
3623 {
3624 moovAtomEndOffset = offset + chunkSize;
3625
3626 done = true;
3627 break;
3628 }
3629
3630 default:
3631 break;
Andreas Huber1b52bd22010-05-27 09:59:54 -07003632 }
Andreas Hubera0f2bf52011-12-05 11:34:43 -08003633
3634 offset += chunkSize;
Andreas Huber1b52bd22010-05-27 09:59:54 -07003635 }
3636
Andreas Hubera0f2bf52011-12-05 11:34:43 -08003637 if (!foundGoodFileType) {
Andreas Huber1b52bd22010-05-27 09:59:54 -07003638 return false;
3639 }
3640
3641 *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
Andreas Huber5a1c3522010-08-25 11:09:41 -07003642 *confidence = 0.4f;
Andreas Huber1b52bd22010-05-27 09:59:54 -07003643
Andreas Hubera0f2bf52011-12-05 11:34:43 -08003644 if (moovAtomEndOffset >= 0) {
3645 *meta = new AMessage;
3646 (*meta)->setInt64("meta-data-size", moovAtomEndOffset);
3647
Andreas Huber456caf32011-12-05 13:30:52 -08003648 ALOGV("found metadata size: %lld", moovAtomEndOffset);
Andreas Hubera0f2bf52011-12-05 11:34:43 -08003649 }
3650
Andreas Huber1b52bd22010-05-27 09:59:54 -07003651 return true;
3652}
3653
3654bool SniffMPEG4(
Andreas Huber5a1c3522010-08-25 11:09:41 -07003655 const sp<DataSource> &source, String8 *mimeType, float *confidence,
Andreas Hubera0f2bf52011-12-05 11:34:43 -08003656 sp<AMessage> *meta) {
3657 if (BetterSniffMPEG4(source, mimeType, confidence, meta)) {
Andreas Huber1b52bd22010-05-27 09:59:54 -07003658 return true;
3659 }
3660
3661 if (LegacySniffMPEG4(source, mimeType, confidence)) {
Steve Block5ff1dd52012-01-05 23:22:43 +00003662 ALOGW("Identified supported mpeg4 through LegacySniffMPEG4.");
Andreas Huber1b52bd22010-05-27 09:59:54 -07003663 return true;
3664 }
3665
3666 return false;
3667}
3668
Andreas Huber20111aa2009-07-14 16:56:47 -07003669} // namespace android