blob: 7b96d01325a6c55a932cc93db614e709fa1a14fd [file] [log] [blame]
Andreas Hubere46b7be2009-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
17#define LOG_TAG "MPEG4Extractor"
18#include <utils/Log.h>
19
Andreas Huber57515f32009-10-23 09:55:10 -070020#include "include/MPEG4Extractor.h"
Andreas Huberbd7b43b2009-10-13 10:22:55 -070021#include "include/SampleTable.h"
22
Andreas Hubere46b7be2009-07-14 16:56:47 -070023#include <arpa/inet.h>
24
Andreas Hubere46b7be2009-07-14 16:56:47 -070025#include <ctype.h>
26#include <stdint.h>
27#include <stdlib.h>
28#include <string.h>
29
Andreas Huber940c8662010-11-16 15:26:30 -080030#include <media/stagefright/foundation/ADebug.h>
Andreas Hubere46b7be2009-07-14 16:56:47 -070031#include <media/stagefright/DataSource.h>
Andreas Huberd2315962010-01-29 14:46:59 -080032#include "include/ESDS.h"
Andreas Hubere46b7be2009-07-14 16:56:47 -070033#include <media/stagefright/MediaBuffer.h>
34#include <media/stagefright/MediaBufferGroup.h>
Andreas Hubere6c40962009-09-10 14:13:30 -070035#include <media/stagefright/MediaDefs.h>
Andreas Hubere46b7be2009-07-14 16:56:47 -070036#include <media/stagefright/MediaSource.h>
37#include <media/stagefright/MetaData.h>
Andreas Hubere46b7be2009-07-14 16:56:47 -070038#include <media/stagefright/Utils.h>
39#include <utils/String8.h>
40
41namespace android {
42
43class MPEG4Source : public MediaSource {
44public:
45 // Caller retains ownership of both "dataSource" and "sampleTable".
Andreas Huberbe06d262009-08-14 14:37:10 -070046 MPEG4Source(const sp<MetaData> &format,
47 const sp<DataSource> &dataSource,
Andreas Huberfa8de752009-10-08 10:07:49 -070048 int32_t timeScale,
Andreas Huberbe06d262009-08-14 14:37:10 -070049 const sp<SampleTable> &sampleTable);
Andreas Hubere46b7be2009-07-14 16:56:47 -070050
51 virtual status_t start(MetaData *params = NULL);
52 virtual status_t stop();
53
54 virtual sp<MetaData> getFormat();
55
56 virtual status_t read(
57 MediaBuffer **buffer, const ReadOptions *options = NULL);
58
Andreas Huberbe06d262009-08-14 14:37:10 -070059protected:
60 virtual ~MPEG4Source();
61
Andreas Hubere46b7be2009-07-14 16:56:47 -070062private:
Andreas Huberba7ec912010-02-12 10:42:02 -080063 Mutex mLock;
64
Andreas Hubere46b7be2009-07-14 16:56:47 -070065 sp<MetaData> mFormat;
Andreas Huberbe06d262009-08-14 14:37:10 -070066 sp<DataSource> mDataSource;
Andreas Hubere46b7be2009-07-14 16:56:47 -070067 int32_t mTimescale;
Andreas Huberbe06d262009-08-14 14:37:10 -070068 sp<SampleTable> mSampleTable;
Andreas Hubere46b7be2009-07-14 16:56:47 -070069 uint32_t mCurrentSampleIndex;
70
71 bool mIsAVC;
Andreas Huberdb5d6622010-01-12 16:30:44 -080072 size_t mNALLengthSize;
73
Andreas Hubere46b7be2009-07-14 16:56:47 -070074 bool mStarted;
75
76 MediaBufferGroup *mGroup;
77
78 MediaBuffer *mBuffer;
Andreas Hubere46b7be2009-07-14 16:56:47 -070079
Andreas Huber4f5e6022009-08-19 09:29:34 -070080 bool mWantsNALFragments;
Andreas Hubere46b7be2009-07-14 16:56:47 -070081
Andreas Huber8a432772009-07-28 10:03:13 -070082 uint8_t *mSrcBuffer;
83
Andreas Huberdb5d6622010-01-12 16:30:44 -080084 size_t parseNALSize(const uint8_t *data) const;
85
Andreas Hubere46b7be2009-07-14 16:56:47 -070086 MPEG4Source(const MPEG4Source &);
87 MPEG4Source &operator=(const MPEG4Source &);
88};
89
Andreas Huberaffa99c2010-01-28 14:27:37 -080090// This custom data source wraps an existing one and satisfies requests
91// falling entirely within a cached range from the cache while forwarding
92// all remaining requests to the wrapped datasource.
93// This is used to cache the full sampletable metadata for a single track,
94// possibly wrapping multiple times to cover all tracks, i.e.
95// Each MPEG4DataSource caches the sampletable metadata for a single track.
96
97struct MPEG4DataSource : public DataSource {
98 MPEG4DataSource(const sp<DataSource> &source);
99
100 virtual status_t initCheck() const;
James Dongb1262a82010-11-16 14:04:54 -0800101 virtual ssize_t readAt(off64_t offset, void *data, size_t size);
102 virtual status_t getSize(off64_t *size);
Andreas Huberaffa99c2010-01-28 14:27:37 -0800103 virtual uint32_t flags();
104
James Dongb1262a82010-11-16 14:04:54 -0800105 status_t setCachedRange(off64_t offset, size_t size);
Andreas Huberaffa99c2010-01-28 14:27:37 -0800106
107protected:
108 virtual ~MPEG4DataSource();
109
110private:
111 Mutex mLock;
112
113 sp<DataSource> mSource;
James Dongb1262a82010-11-16 14:04:54 -0800114 off64_t mCachedOffset;
Andreas Huberaffa99c2010-01-28 14:27:37 -0800115 size_t mCachedSize;
116 uint8_t *mCache;
117
118 void clearCache();
119
120 MPEG4DataSource(const MPEG4DataSource &);
121 MPEG4DataSource &operator=(const MPEG4DataSource &);
122};
123
124MPEG4DataSource::MPEG4DataSource(const sp<DataSource> &source)
125 : mSource(source),
126 mCachedOffset(0),
127 mCachedSize(0),
128 mCache(NULL) {
129}
130
131MPEG4DataSource::~MPEG4DataSource() {
132 clearCache();
133}
134
135void MPEG4DataSource::clearCache() {
136 if (mCache) {
137 free(mCache);
138 mCache = NULL;
139 }
140
141 mCachedOffset = 0;
142 mCachedSize = 0;
143}
144
145status_t MPEG4DataSource::initCheck() const {
146 return mSource->initCheck();
147}
148
James Dongb1262a82010-11-16 14:04:54 -0800149ssize_t MPEG4DataSource::readAt(off64_t offset, void *data, size_t size) {
Andreas Huberaffa99c2010-01-28 14:27:37 -0800150 Mutex::Autolock autoLock(mLock);
151
152 if (offset >= mCachedOffset
153 && offset + size <= mCachedOffset + mCachedSize) {
154 memcpy(data, &mCache[offset - mCachedOffset], size);
155 return size;
156 }
157
158 return mSource->readAt(offset, data, size);
159}
160
James Dongb1262a82010-11-16 14:04:54 -0800161status_t MPEG4DataSource::getSize(off64_t *size) {
Andreas Huberaffa99c2010-01-28 14:27:37 -0800162 return mSource->getSize(size);
163}
164
165uint32_t MPEG4DataSource::flags() {
166 return mSource->flags();
167}
168
James Dongb1262a82010-11-16 14:04:54 -0800169status_t MPEG4DataSource::setCachedRange(off64_t offset, size_t size) {
Andreas Huberaffa99c2010-01-28 14:27:37 -0800170 Mutex::Autolock autoLock(mLock);
171
172 clearCache();
173
174 mCache = (uint8_t *)malloc(size);
175
176 if (mCache == NULL) {
177 return -ENOMEM;
178 }
179
180 mCachedOffset = offset;
181 mCachedSize = size;
182
183 ssize_t err = mSource->readAt(mCachedOffset, mCache, mCachedSize);
184
185 if (err < (ssize_t)size) {
186 clearCache();
187
188 return ERROR_IO;
189 }
190
191 return OK;
192}
193
194////////////////////////////////////////////////////////////////////////////////
195
Andreas Hubere46b7be2009-07-14 16:56:47 -0700196static void hexdump(const void *_data, size_t size) {
197 const uint8_t *data = (const uint8_t *)_data;
198 size_t offset = 0;
199 while (offset < size) {
200 printf("0x%04x ", offset);
201
202 size_t n = size - offset;
203 if (n > 16) {
204 n = 16;
205 }
206
207 for (size_t i = 0; i < 16; ++i) {
208 if (i == 8) {
209 printf(" ");
210 }
211
212 if (offset + i < size) {
213 printf("%02x ", data[offset + i]);
214 } else {
215 printf(" ");
216 }
217 }
218
219 printf(" ");
220
221 for (size_t i = 0; i < n; ++i) {
222 if (isprint(data[offset + i])) {
223 printf("%c", data[offset + i]);
224 } else {
225 printf(".");
226 }
227 }
228
229 printf("\n");
230
231 offset += 16;
232 }
233}
234
Andreas Hubere6c40962009-09-10 14:13:30 -0700235static const char *FourCC2MIME(uint32_t fourcc) {
Andreas Hubere46b7be2009-07-14 16:56:47 -0700236 switch (fourcc) {
237 case FOURCC('m', 'p', '4', 'a'):
Andreas Hubere6c40962009-09-10 14:13:30 -0700238 return MEDIA_MIMETYPE_AUDIO_AAC;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700239
240 case FOURCC('s', 'a', 'm', 'r'):
Andreas Hubere6c40962009-09-10 14:13:30 -0700241 return MEDIA_MIMETYPE_AUDIO_AMR_NB;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700242
Andreas Huber2a651172009-09-09 16:32:59 -0700243 case FOURCC('s', 'a', 'w', 'b'):
Andreas Hubere6c40962009-09-10 14:13:30 -0700244 return MEDIA_MIMETYPE_AUDIO_AMR_WB;
Andreas Huber2a651172009-09-09 16:32:59 -0700245
Andreas Hubere46b7be2009-07-14 16:56:47 -0700246 case FOURCC('m', 'p', '4', 'v'):
Andreas Hubere6c40962009-09-10 14:13:30 -0700247 return MEDIA_MIMETYPE_VIDEO_MPEG4;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700248
249 case FOURCC('s', '2', '6', '3'):
James Dong0efdc952010-12-15 15:49:46 -0800250 case FOURCC('h', '2', '6', '3'):
251 case FOURCC('H', '2', '6', '3'):
Andreas Hubere6c40962009-09-10 14:13:30 -0700252 return MEDIA_MIMETYPE_VIDEO_H263;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700253
254 case FOURCC('a', 'v', 'c', '1'):
Andreas Hubere6c40962009-09-10 14:13:30 -0700255 return MEDIA_MIMETYPE_VIDEO_AVC;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700256
257 default:
Andreas Huber4f5e6022009-08-19 09:29:34 -0700258 CHECK(!"should not be here.");
Andreas Hubere46b7be2009-07-14 16:56:47 -0700259 return NULL;
260 }
261}
262
Andreas Huberbe06d262009-08-14 14:37:10 -0700263MPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
Andreas Hubere46b7be2009-07-14 16:56:47 -0700264 : mDataSource(source),
265 mHaveMetadata(false),
Andreas Huber1cb02bf2010-01-13 11:25:10 -0800266 mHasVideo(false),
Andreas Hubere46b7be2009-07-14 16:56:47 -0700267 mFirstTrack(NULL),
Andreas Huberc2c9dd32010-01-19 16:43:53 -0800268 mLastTrack(NULL),
Gloria Wangd5770912010-06-22 13:55:38 -0700269 mFileMetaData(new MetaData),
270 mFirstSINF(NULL),
271 mIsDrm(false) {
Andreas Hubere46b7be2009-07-14 16:56:47 -0700272}
273
274MPEG4Extractor::~MPEG4Extractor() {
275 Track *track = mFirstTrack;
276 while (track) {
277 Track *next = track->next;
278
Andreas Hubere46b7be2009-07-14 16:56:47 -0700279 delete track;
280 track = next;
281 }
282 mFirstTrack = mLastTrack = NULL;
Gloria Wangd5770912010-06-22 13:55:38 -0700283
284 SINF *sinf = mFirstSINF;
285 while (sinf) {
286 SINF *next = sinf->next;
287 delete sinf->IPMPData;
288 delete sinf;
289 sinf = next;
290 }
291 mFirstSINF = NULL;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700292}
293
Andreas Huber1cb02bf2010-01-13 11:25:10 -0800294sp<MetaData> MPEG4Extractor::getMetaData() {
Andreas Huber1cb02bf2010-01-13 11:25:10 -0800295 status_t err;
296 if ((err = readMetaData()) != OK) {
Andreas Huberc2c9dd32010-01-19 16:43:53 -0800297 return new MetaData;
Andreas Huber1cb02bf2010-01-13 11:25:10 -0800298 }
299
Andreas Huberc2c9dd32010-01-19 16:43:53 -0800300 return mFileMetaData;
Andreas Huber1cb02bf2010-01-13 11:25:10 -0800301}
302
Andreas Huberbe06d262009-08-14 14:37:10 -0700303size_t MPEG4Extractor::countTracks() {
Andreas Hubere46b7be2009-07-14 16:56:47 -0700304 status_t err;
305 if ((err = readMetaData()) != OK) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700306 return 0;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700307 }
308
Andreas Huberbe06d262009-08-14 14:37:10 -0700309 size_t n = 0;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700310 Track *track = mFirstTrack;
311 while (track) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700312 ++n;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700313 track = track->next;
314 }
315
Andreas Huberbe06d262009-08-14 14:37:10 -0700316 return n;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700317}
318
Andreas Hubere981c332009-10-22 13:49:30 -0700319sp<MetaData> MPEG4Extractor::getTrackMetaData(
320 size_t index, uint32_t flags) {
Andreas Hubere46b7be2009-07-14 16:56:47 -0700321 status_t err;
322 if ((err = readMetaData()) != OK) {
323 return NULL;
324 }
325
326 Track *track = mFirstTrack;
327 while (index > 0) {
328 if (track == NULL) {
329 return NULL;
330 }
331
332 track = track->next;
333 --index;
334 }
335
Andreas Huber2a651172009-09-09 16:32:59 -0700336 if (track == NULL) {
337 return NULL;
338 }
339
Andreas Hubere981c332009-10-22 13:49:30 -0700340 if ((flags & kIncludeExtensiveMetaData)
341 && !track->includes_expensive_metadata) {
342 track->includes_expensive_metadata = true;
343
344 const char *mime;
345 CHECK(track->meta->findCString(kKeyMIMEType, &mime));
346 if (!strncasecmp("video/", mime, 6)) {
347 uint32_t sampleIndex;
348 uint32_t sampleTime;
349 if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK
Andreas Huber1faa92a2010-01-19 10:39:21 -0800350 && track->sampleTable->getMetaDataForSample(
351 sampleIndex, NULL /* offset */, NULL /* size */,
352 &sampleTime) == OK) {
Andreas Hubere981c332009-10-22 13:49:30 -0700353 track->meta->setInt64(
354 kKeyThumbnailTime,
355 ((int64_t)sampleTime * 1000000) / track->timescale);
356 }
357 }
358 }
359
Andreas Hubere46b7be2009-07-14 16:56:47 -0700360 return track->meta;
361}
362
363status_t MPEG4Extractor::readMetaData() {
364 if (mHaveMetadata) {
365 return OK;
366 }
367
James Dongb1262a82010-11-16 14:04:54 -0800368 off64_t offset = 0;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700369 status_t err;
370 while ((err = parseChunk(&offset, 0)) == OK) {
371 }
Andreas Huber1cb02bf2010-01-13 11:25:10 -0800372
Andreas Hubere46b7be2009-07-14 16:56:47 -0700373 if (mHaveMetadata) {
Andreas Huberc2c9dd32010-01-19 16:43:53 -0800374 if (mHasVideo) {
375 mFileMetaData->setCString(kKeyMIMEType, "video/mp4");
376 } else {
377 mFileMetaData->setCString(kKeyMIMEType, "audio/mp4");
378 }
379
Andreas Hubere46b7be2009-07-14 16:56:47 -0700380 return OK;
381 }
382
383 return err;
384}
385
Gloria Wangd5770912010-06-22 13:55:38 -0700386void MPEG4Extractor::setDrmFlag(bool flag) {
387 mIsDrm = flag;
388}
389
390char* MPEG4Extractor::getDrmTrackInfo(size_t trackID, int *len) {
391 if (mFirstSINF == NULL) {
392 return NULL;
393 }
394
395 SINF *sinf = mFirstSINF;
396 while (sinf && (trackID != sinf->trackID)) {
397 sinf = sinf->next;
398 }
399
400 if (sinf == NULL) {
401 return NULL;
402 }
403
404 *len = sinf->len;
405 return sinf->IPMPData;
406}
407
408// Reads an encoded integer 7 bits at a time until it encounters the high bit clear.
James Dongb1262a82010-11-16 14:04:54 -0800409int32_t readSize(off64_t offset,
Gloria Wangd5770912010-06-22 13:55:38 -0700410 const sp<DataSource> DataSource, uint8_t *numOfBytes) {
411 uint32_t size = 0;
412 uint8_t data;
413 bool moreData = true;
414 *numOfBytes = 0;
415
416 while (moreData) {
417 if (DataSource->readAt(offset, &data, 1) < 1) {
418 return -1;
419 }
420 offset ++;
421 moreData = (data >= 128) ? true : false;
422 size = (size << 7) | (data & 0x7f); // Take last 7 bits
423 (*numOfBytes) ++;
424 }
425
426 return size;
427}
428
James Dongb1262a82010-11-16 14:04:54 -0800429status_t MPEG4Extractor::parseDrmSINF(off64_t *offset, off64_t data_offset) {
Gloria Wangd5770912010-06-22 13:55:38 -0700430 uint8_t updateIdTag;
431 if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
432 return ERROR_IO;
433 }
434 data_offset ++;
435
436 if (0x01/*OBJECT_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
437 return ERROR_MALFORMED;
438 }
439
440 uint8_t numOfBytes;
441 int32_t size = readSize(data_offset, mDataSource, &numOfBytes);
442 if (size < 0) {
443 return ERROR_IO;
444 }
445 int32_t classSize = size;
446 data_offset += numOfBytes;
447
448 while(size >= 11 ) {
449 uint8_t descriptorTag;
450 if (mDataSource->readAt(data_offset, &descriptorTag, 1) < 1) {
451 return ERROR_IO;
452 }
453 data_offset ++;
454
455 if (0x11/*OBJECT_DESCRIPTOR_ID_TAG*/ != descriptorTag) {
456 return ERROR_MALFORMED;
457 }
458
459 uint8_t buffer[8];
460 //ObjectDescriptorID and ObjectDescriptor url flag
461 if (mDataSource->readAt(data_offset, buffer, 2) < 2) {
462 return ERROR_IO;
463 }
464 data_offset += 2;
465
466 if ((buffer[1] >> 5) & 0x0001) { //url flag is set
467 return ERROR_MALFORMED;
468 }
469
470 if (mDataSource->readAt(data_offset, buffer, 8) < 8) {
471 return ERROR_IO;
472 }
473 data_offset += 8;
474
475 if ((0x0F/*ES_ID_REF_TAG*/ != buffer[1])
476 || ( 0x0A/*IPMP_DESCRIPTOR_POINTER_ID_TAG*/ != buffer[5])) {
477 return ERROR_MALFORMED;
478 }
479
480 SINF *sinf = new SINF;
481 sinf->trackID = U16_AT(&buffer[3]);
482 sinf->IPMPDescriptorID = buffer[7];
483 sinf->next = mFirstSINF;
484 mFirstSINF = sinf;
485
486 size -= (8 + 2 + 1);
487 }
488
489 if (size != 0) {
490 return ERROR_MALFORMED;
491 }
492
493 if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
494 return ERROR_IO;
495 }
496 data_offset ++;
497
498 if(0x05/*IPMP_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
499 return ERROR_MALFORMED;
500 }
501
502 size = readSize(data_offset, mDataSource, &numOfBytes);
503 if (size < 0) {
504 return ERROR_IO;
505 }
506 classSize = size;
507 data_offset += numOfBytes;
508
509 while (size > 0) {
510 uint8_t tag;
511 int32_t dataLen;
512 if (mDataSource->readAt(data_offset, &tag, 1) < 1) {
513 return ERROR_IO;
514 }
515 data_offset ++;
516
517 if (0x0B/*IPMP_DESCRIPTOR_ID_TAG*/ == tag) {
518 uint8_t id;
519 dataLen = readSize(data_offset, mDataSource, &numOfBytes);
520 if (dataLen < 0) {
521 return ERROR_IO;
522 } else if (dataLen < 4) {
523 return ERROR_MALFORMED;
524 }
525 data_offset += numOfBytes;
526
527 if (mDataSource->readAt(data_offset, &id, 1) < 1) {
528 return ERROR_IO;
529 }
530 data_offset ++;
531
532 SINF *sinf = mFirstSINF;
533 while (sinf && (sinf->IPMPDescriptorID != id)) {
534 sinf = sinf->next;
535 }
536 if (sinf == NULL) {
537 return ERROR_MALFORMED;
538 }
539 sinf->len = dataLen - 3;
540 sinf->IPMPData = new char[sinf->len];
541
542 if (mDataSource->readAt(data_offset + 2, sinf->IPMPData, sinf->len) < sinf->len) {
543 return ERROR_IO;
544 }
545 data_offset += sinf->len;
546
547 size -= (dataLen + numOfBytes + 1);
548 }
549 }
550
551 if (size != 0) {
552 return ERROR_MALFORMED;
553 }
554
555 return UNKNOWN_ERROR; // Return a dummy error.
556}
557
Andreas Hubere46b7be2009-07-14 16:56:47 -0700558static void MakeFourCCString(uint32_t x, char *s) {
559 s[0] = x >> 24;
560 s[1] = (x >> 16) & 0xff;
561 s[2] = (x >> 8) & 0xff;
562 s[3] = x & 0xff;
563 s[4] = '\0';
564}
565
Andreas Huberc2c9dd32010-01-19 16:43:53 -0800566struct PathAdder {
567 PathAdder(Vector<uint32_t> *path, uint32_t chunkType)
568 : mPath(path) {
569 mPath->push(chunkType);
570 }
571
572 ~PathAdder() {
573 mPath->pop();
574 }
575
576private:
577 Vector<uint32_t> *mPath;
578
579 PathAdder(const PathAdder &);
580 PathAdder &operator=(const PathAdder &);
581};
582
583static bool underMetaDataPath(const Vector<uint32_t> &path) {
584 return path.size() >= 5
585 && path[0] == FOURCC('m', 'o', 'o', 'v')
586 && path[1] == FOURCC('u', 'd', 't', 'a')
587 && path[2] == FOURCC('m', 'e', 't', 'a')
588 && path[3] == FOURCC('i', 'l', 's', 't');
589}
590
591// Given a time in seconds since Jan 1 1904, produce a human-readable string.
592static void convertTimeToDate(int64_t time_1904, String8 *s) {
593 time_t time_1970 = time_1904 - (((66 * 365 + 17) * 24) * 3600);
594
595 char tmp[32];
596 strftime(tmp, sizeof(tmp), "%Y%m%dT%H%M%S.000Z", gmtime(&time_1970));
597
598 s->setTo(tmp);
599}
600
James Dongb1262a82010-11-16 14:04:54 -0800601status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
Andreas Hubere46b7be2009-07-14 16:56:47 -0700602 uint32_t hdr[2];
Andreas Huber9a12baf2009-10-23 10:22:30 -0700603 if (mDataSource->readAt(*offset, hdr, 8) < 8) {
Andreas Hubere46b7be2009-07-14 16:56:47 -0700604 return ERROR_IO;
605 }
606 uint64_t chunk_size = ntohl(hdr[0]);
607 uint32_t chunk_type = ntohl(hdr[1]);
James Dongb1262a82010-11-16 14:04:54 -0800608 off64_t data_offset = *offset + 8;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700609
610 if (chunk_size == 1) {
Andreas Huber9a12baf2009-10-23 10:22:30 -0700611 if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
Andreas Hubere46b7be2009-07-14 16:56:47 -0700612 return ERROR_IO;
613 }
614 chunk_size = ntoh64(chunk_size);
615 data_offset += 8;
Andreas Huber736c22d2010-06-24 12:16:25 -0700616
617 if (chunk_size < 16) {
618 // The smallest valid chunk is 16 bytes long in this case.
619 return ERROR_MALFORMED;
620 }
621 } else if (chunk_size < 8) {
622 // The smallest valid chunk is 8 bytes long.
623 return ERROR_MALFORMED;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700624 }
625
626 char chunk[5];
627 MakeFourCCString(chunk_type, chunk);
628
629#if 0
630 static const char kWhitespace[] = " ";
631 const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth];
632 printf("%sfound chunk '%s' of size %lld\n", indent, chunk, chunk_size);
633
634 char buffer[256];
Andreas Huberdfb8eee2010-02-25 15:59:24 -0800635 size_t n = chunk_size;
636 if (n > sizeof(buffer)) {
637 n = sizeof(buffer);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700638 }
Andreas Huberdfb8eee2010-02-25 15:59:24 -0800639 if (mDataSource->readAt(*offset, buffer, n)
640 < (ssize_t)n) {
641 return ERROR_IO;
642 }
643
644 hexdump(buffer, n);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700645#endif
646
Andreas Huberc2c9dd32010-01-19 16:43:53 -0800647 PathAdder autoAdder(&mPath, chunk_type);
648
James Dongb1262a82010-11-16 14:04:54 -0800649 off64_t chunk_data_size = *offset + chunk_size - data_offset;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700650
Andreas Huberc2c9dd32010-01-19 16:43:53 -0800651 if (chunk_type != FOURCC('c', 'p', 'r', 't')
652 && mPath.size() == 5 && underMetaDataPath(mPath)) {
James Dongb1262a82010-11-16 14:04:54 -0800653 off64_t stop_offset = *offset + chunk_size;
Andreas Huberc2c9dd32010-01-19 16:43:53 -0800654 *offset = data_offset;
655 while (*offset < stop_offset) {
656 status_t err = parseChunk(offset, depth + 1);
657 if (err != OK) {
658 return err;
659 }
660 }
Andreas Huber5ee0bce2010-02-23 10:12:02 -0800661
662 if (*offset != stop_offset) {
663 return ERROR_MALFORMED;
664 }
Andreas Huberc2c9dd32010-01-19 16:43:53 -0800665
666 return OK;
667 }
668
Andreas Hubere46b7be2009-07-14 16:56:47 -0700669 switch(chunk_type) {
670 case FOURCC('m', 'o', 'o', 'v'):
671 case FOURCC('t', 'r', 'a', 'k'):
672 case FOURCC('m', 'd', 'i', 'a'):
673 case FOURCC('m', 'i', 'n', 'f'):
674 case FOURCC('d', 'i', 'n', 'f'):
675 case FOURCC('s', 't', 'b', 'l'):
676 case FOURCC('m', 'v', 'e', 'x'):
677 case FOURCC('m', 'o', 'o', 'f'):
678 case FOURCC('t', 'r', 'a', 'f'):
679 case FOURCC('m', 'f', 'r', 'a'):
Andreas Huberc2c9dd32010-01-19 16:43:53 -0800680 case FOURCC('u', 'd', 't', 'a'):
681 case FOURCC('i', 'l', 's', 't'):
Andreas Hubere46b7be2009-07-14 16:56:47 -0700682 {
Andreas Huberaffa99c2010-01-28 14:27:37 -0800683 if (chunk_type == FOURCC('s', 't', 'b', 'l')) {
684 LOGV("sampleTable chunk is %d bytes long.", (size_t)chunk_size);
685
Andreas Huber6da2ae12010-10-15 08:38:49 -0700686 if (mDataSource->flags()
687 & (DataSource::kWantsPrefetching
688 | DataSource::kIsCachingDataSource)) {
Andreas Huberaffa99c2010-01-28 14:27:37 -0800689 sp<MPEG4DataSource> cachedSource =
690 new MPEG4DataSource(mDataSource);
691
692 if (cachedSource->setCachedRange(*offset, chunk_size) == OK) {
693 mDataSource = cachedSource;
694 }
695 }
Andreas Hubereb9128f2010-05-14 15:28:51 -0700696
697 mLastTrack->sampleTable = new SampleTable(mDataSource);
Andreas Huberaffa99c2010-01-28 14:27:37 -0800698 }
699
Andreas Huber4d60fc52010-03-12 16:15:53 -0800700 bool isTrack = false;
Andreas Huber5ee0bce2010-02-23 10:12:02 -0800701 if (chunk_type == FOURCC('t', 'r', 'a', 'k')) {
Andreas Huber4d60fc52010-03-12 16:15:53 -0800702 isTrack = true;
703
Andreas Huber5ee0bce2010-02-23 10:12:02 -0800704 Track *track = new Track;
705 track->next = NULL;
706 if (mLastTrack) {
707 mLastTrack->next = track;
708 } else {
709 mFirstTrack = track;
710 }
711 mLastTrack = track;
712
713 track->meta = new MetaData;
714 track->includes_expensive_metadata = false;
Andreas Huber4d60fc52010-03-12 16:15:53 -0800715 track->skipTrack = false;
Andreas Huber5ee0bce2010-02-23 10:12:02 -0800716 track->timescale = 0;
Andreas Huber5ee0bce2010-02-23 10:12:02 -0800717 track->meta->setCString(kKeyMIMEType, "application/octet-stream");
718 }
719
James Dongb1262a82010-11-16 14:04:54 -0800720 off64_t stop_offset = *offset + chunk_size;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700721 *offset = data_offset;
722 while (*offset < stop_offset) {
723 status_t err = parseChunk(offset, depth + 1);
724 if (err != OK) {
725 return err;
726 }
727 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700728
Andreas Huber5ee0bce2010-02-23 10:12:02 -0800729 if (*offset != stop_offset) {
730 return ERROR_MALFORMED;
731 }
732
Andreas Huber4d60fc52010-03-12 16:15:53 -0800733 if (isTrack) {
734 if (mLastTrack->skipTrack) {
735 Track *cur = mFirstTrack;
736
737 if (cur == mLastTrack) {
738 delete cur;
739 mFirstTrack = mLastTrack = NULL;
740 } else {
741 while (cur && cur->next != mLastTrack) {
742 cur = cur->next;
743 }
744 cur->next = NULL;
745 delete mLastTrack;
746 mLastTrack = cur;
747 }
748
749 return OK;
750 }
751
Andreas Huber5ee0bce2010-02-23 10:12:02 -0800752 status_t err = verifyTrack(mLastTrack);
753
754 if (err != OK) {
755 return err;
756 }
757 } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
Andreas Hubere46b7be2009-07-14 16:56:47 -0700758 mHaveMetadata = true;
759
Gloria Wangd5770912010-06-22 13:55:38 -0700760 if (!mIsDrm) {
761 return UNKNOWN_ERROR; // Return a dummy error.
762 } else {
763 return OK;
764 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700765 }
766 break;
767 }
768
769 case FOURCC('t', 'k', 'h', 'd'):
770 {
Andreas Huber940c8662010-11-16 15:26:30 -0800771 status_t err;
772 if ((err = parseTrackHeader(data_offset, chunk_data_size)) != OK) {
773 return err;
Andreas Huber5ee0bce2010-02-23 10:12:02 -0800774 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700775
Andreas Hubere46b7be2009-07-14 16:56:47 -0700776 *offset += chunk_size;
777 break;
778 }
779
780 case FOURCC('m', 'd', 'h', 'd'):
781 {
782 if (chunk_data_size < 4) {
783 return ERROR_MALFORMED;
784 }
785
786 uint8_t version;
Andreas Huber9a12baf2009-10-23 10:22:30 -0700787 if (mDataSource->readAt(
Andreas Hubere46b7be2009-07-14 16:56:47 -0700788 data_offset, &version, sizeof(version))
789 < (ssize_t)sizeof(version)) {
790 return ERROR_IO;
791 }
792
James Dongb1262a82010-11-16 14:04:54 -0800793 off64_t timescale_offset;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700794
795 if (version == 1) {
796 timescale_offset = data_offset + 4 + 16;
797 } else if (version == 0) {
798 timescale_offset = data_offset + 4 + 8;
799 } else {
800 return ERROR_IO;
801 }
802
803 uint32_t timescale;
Andreas Huber9a12baf2009-10-23 10:22:30 -0700804 if (mDataSource->readAt(
Andreas Hubere46b7be2009-07-14 16:56:47 -0700805 timescale_offset, &timescale, sizeof(timescale))
806 < (ssize_t)sizeof(timescale)) {
807 return ERROR_IO;
808 }
809
810 mLastTrack->timescale = ntohl(timescale);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700811
812 int64_t duration;
813 if (version == 1) {
Andreas Huber9a12baf2009-10-23 10:22:30 -0700814 if (mDataSource->readAt(
Andreas Hubere46b7be2009-07-14 16:56:47 -0700815 timescale_offset + 4, &duration, sizeof(duration))
816 < (ssize_t)sizeof(duration)) {
817 return ERROR_IO;
818 }
819 duration = ntoh64(duration);
820 } else {
821 int32_t duration32;
Andreas Huber9a12baf2009-10-23 10:22:30 -0700822 if (mDataSource->readAt(
Andreas Hubere46b7be2009-07-14 16:56:47 -0700823 timescale_offset + 4, &duration32, sizeof(duration32))
824 < (ssize_t)sizeof(duration32)) {
825 return ERROR_IO;
826 }
827 duration = ntohl(duration32);
828 }
Andreas Huberfa8de752009-10-08 10:07:49 -0700829 mLastTrack->meta->setInt64(
830 kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700831
832 *offset += chunk_size;
833 break;
834 }
835
Andreas Hubere46b7be2009-07-14 16:56:47 -0700836 case FOURCC('s', 't', 's', 'd'):
837 {
838 if (chunk_data_size < 8) {
839 return ERROR_MALFORMED;
840 }
841
842 uint8_t buffer[8];
James Dongb1262a82010-11-16 14:04:54 -0800843 if (chunk_data_size < (off64_t)sizeof(buffer)) {
Andreas Huber5ee0bce2010-02-23 10:12:02 -0800844 return ERROR_MALFORMED;
845 }
846
Andreas Huber9a12baf2009-10-23 10:22:30 -0700847 if (mDataSource->readAt(
Andreas Hubere46b7be2009-07-14 16:56:47 -0700848 data_offset, buffer, 8) < 8) {
849 return ERROR_IO;
850 }
851
852 if (U32_AT(buffer) != 0) {
853 // Should be version 0, flags 0.
854 return ERROR_MALFORMED;
855 }
856
857 uint32_t entry_count = U32_AT(&buffer[4]);
858
859 if (entry_count > 1) {
860 // For now we only support a single type of media per track.
Andreas Huber4d60fc52010-03-12 16:15:53 -0800861
862 mLastTrack->skipTrack = true;
863 *offset += chunk_size;
864 break;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700865 }
866
James Dongb1262a82010-11-16 14:04:54 -0800867 off64_t stop_offset = *offset + chunk_size;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700868 *offset = data_offset + 8;
869 for (uint32_t i = 0; i < entry_count; ++i) {
870 status_t err = parseChunk(offset, depth + 1);
871 if (err != OK) {
872 return err;
873 }
874 }
Andreas Huber5ee0bce2010-02-23 10:12:02 -0800875
876 if (*offset != stop_offset) {
877 return ERROR_MALFORMED;
878 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700879 break;
880 }
881
882 case FOURCC('m', 'p', '4', 'a'):
883 case FOURCC('s', 'a', 'm', 'r'):
Andreas Huber2a651172009-09-09 16:32:59 -0700884 case FOURCC('s', 'a', 'w', 'b'):
Andreas Hubere46b7be2009-07-14 16:56:47 -0700885 {
Andreas Hubere46b7be2009-07-14 16:56:47 -0700886 uint8_t buffer[8 + 20];
887 if (chunk_data_size < (ssize_t)sizeof(buffer)) {
888 // Basic AudioSampleEntry size.
889 return ERROR_MALFORMED;
890 }
891
Andreas Huber9a12baf2009-10-23 10:22:30 -0700892 if (mDataSource->readAt(
Andreas Hubere46b7be2009-07-14 16:56:47 -0700893 data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
894 return ERROR_IO;
895 }
896
897 uint16_t data_ref_index = U16_AT(&buffer[6]);
898 uint16_t num_channels = U16_AT(&buffer[16]);
899
Andreas Hubere46b7be2009-07-14 16:56:47 -0700900 uint16_t sample_size = U16_AT(&buffer[18]);
901 uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
902
Andreas Huberd0332ad2010-04-12 16:05:57 -0700903 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB,
904 FourCC2MIME(chunk_type))) {
905 // AMR NB audio is always mono, 8kHz
906 num_channels = 1;
907 sample_rate = 8000;
908 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB,
909 FourCC2MIME(chunk_type))) {
910 // AMR WB audio is always mono, 16kHz
911 num_channels = 1;
912 sample_rate = 16000;
913 }
914
915#if 0
916 printf("*** coding='%s' %d channels, size %d, rate %d\n",
917 chunk, num_channels, sample_size, sample_rate);
918#endif
Andreas Hubere46b7be2009-07-14 16:56:47 -0700919
920 mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
921 mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
922 mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
923
James Dongb1262a82010-11-16 14:04:54 -0800924 off64_t stop_offset = *offset + chunk_size;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700925 *offset = data_offset + sizeof(buffer);
926 while (*offset < stop_offset) {
927 status_t err = parseChunk(offset, depth + 1);
928 if (err != OK) {
929 return err;
930 }
931 }
Andreas Huber5ee0bce2010-02-23 10:12:02 -0800932
933 if (*offset != stop_offset) {
934 return ERROR_MALFORMED;
935 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700936 break;
937 }
938
939 case FOURCC('m', 'p', '4', 'v'):
940 case FOURCC('s', '2', '6', '3'):
James Dong0efdc952010-12-15 15:49:46 -0800941 case FOURCC('H', '2', '6', '3'):
942 case FOURCC('h', '2', '6', '3'):
Andreas Hubere46b7be2009-07-14 16:56:47 -0700943 case FOURCC('a', 'v', 'c', '1'):
944 {
Andreas Huber1cb02bf2010-01-13 11:25:10 -0800945 mHasVideo = true;
946
Andreas Hubere46b7be2009-07-14 16:56:47 -0700947 uint8_t buffer[78];
948 if (chunk_data_size < (ssize_t)sizeof(buffer)) {
949 // Basic VideoSampleEntry size.
950 return ERROR_MALFORMED;
951 }
952
Andreas Huber9a12baf2009-10-23 10:22:30 -0700953 if (mDataSource->readAt(
Andreas Hubere46b7be2009-07-14 16:56:47 -0700954 data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
955 return ERROR_IO;
956 }
957
958 uint16_t data_ref_index = U16_AT(&buffer[6]);
959 uint16_t width = U16_AT(&buffer[6 + 18]);
960 uint16_t height = U16_AT(&buffer[6 + 20]);
961
James Dongc9e1c802010-12-15 17:32:45 -0800962 // The video sample is not stand-compliant if it has invalid dimension.
963 // Use some default width and height value, and
964 // let the decoder figure out the actual width and height (and thus
965 // be prepared for INFO_FOMRAT_CHANGED event).
966 if (width == 0) width = 352;
967 if (height == 0) height = 288;
968
Andreas Huber2ea14e22009-12-16 09:30:55 -0800969 // printf("*** coding='%s' width=%d height=%d\n",
970 // chunk, width, height);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700971
972 mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
973 mLastTrack->meta->setInt32(kKeyWidth, width);
974 mLastTrack->meta->setInt32(kKeyHeight, height);
975
James Dongb1262a82010-11-16 14:04:54 -0800976 off64_t stop_offset = *offset + chunk_size;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700977 *offset = data_offset + sizeof(buffer);
978 while (*offset < stop_offset) {
979 status_t err = parseChunk(offset, depth + 1);
980 if (err != OK) {
981 return err;
982 }
983 }
Andreas Huber5ee0bce2010-02-23 10:12:02 -0800984
985 if (*offset != stop_offset) {
986 return ERROR_MALFORMED;
987 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700988 break;
989 }
990
991 case FOURCC('s', 't', 'c', 'o'):
992 case FOURCC('c', 'o', '6', '4'):
993 {
994 status_t err =
995 mLastTrack->sampleTable->setChunkOffsetParams(
996 chunk_type, data_offset, chunk_data_size);
997
998 if (err != OK) {
999 return err;
1000 }
1001
1002 *offset += chunk_size;
1003 break;
1004 }
1005
1006 case FOURCC('s', 't', 's', 'c'):
1007 {
1008 status_t err =
1009 mLastTrack->sampleTable->setSampleToChunkParams(
1010 data_offset, chunk_data_size);
1011
1012 if (err != OK) {
1013 return err;
1014 }
1015
1016 *offset += chunk_size;
1017 break;
1018 }
1019
1020 case FOURCC('s', 't', 's', 'z'):
1021 case FOURCC('s', 't', 'z', '2'):
1022 {
1023 status_t err =
1024 mLastTrack->sampleTable->setSampleSizeParams(
1025 chunk_type, data_offset, chunk_data_size);
1026
1027 if (err != OK) {
1028 return err;
1029 }
1030
Andreas Huber1bceff92009-11-23 14:03:32 -08001031 size_t max_size;
Andreas Huberd7f22252010-09-09 10:10:15 -07001032 err = mLastTrack->sampleTable->getMaxSampleSize(&max_size);
1033
1034 if (err != OK) {
1035 return err;
1036 }
Andreas Huber1bceff92009-11-23 14:03:32 -08001037
1038 // Assume that a given buffer only contains at most 10 fragments,
1039 // each fragment originally prefixed with a 2 byte length will
1040 // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
1041 // and thus will grow by 2 bytes per fragment.
1042 mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
Andreas Hubere46b7be2009-07-14 16:56:47 -07001043 *offset += chunk_size;
James Dongcbb488d2011-01-19 00:13:55 -08001044
1045 // Calculate average frame rate.
1046 const char *mime;
1047 CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1048 if (!strncasecmp("video/", mime, 6)) {
1049 size_t nSamples = mLastTrack->sampleTable->countSamples();
1050 int64_t durationUs;
1051 if (mLastTrack->meta->findInt64(kKeyDuration, &durationUs)) {
1052 if (durationUs > 0) {
1053 int32_t frameRate = (nSamples * 1000000LL +
1054 (durationUs >> 1)) / durationUs;
1055 mLastTrack->meta->setInt32(kKeyFrameRate, frameRate);
1056 }
1057 }
1058 }
1059
Andreas Hubere46b7be2009-07-14 16:56:47 -07001060 break;
1061 }
1062
1063 case FOURCC('s', 't', 't', 's'):
1064 {
1065 status_t err =
1066 mLastTrack->sampleTable->setTimeToSampleParams(
1067 data_offset, chunk_data_size);
1068
1069 if (err != OK) {
1070 return err;
1071 }
1072
1073 *offset += chunk_size;
1074 break;
1075 }
1076
Andreas Huberbd352c32011-02-03 13:18:16 -08001077 case FOURCC('c', 't', 't', 's'):
1078 {
1079 status_t err =
1080 mLastTrack->sampleTable->setCompositionTimeToSampleParams(
1081 data_offset, chunk_data_size);
1082
1083 if (err != OK) {
1084 return err;
1085 }
1086
1087 *offset += chunk_size;
1088 break;
1089 }
1090
Andreas Hubere46b7be2009-07-14 16:56:47 -07001091 case FOURCC('s', 't', 's', 's'):
1092 {
1093 status_t err =
1094 mLastTrack->sampleTable->setSyncSampleParams(
1095 data_offset, chunk_data_size);
1096
1097 if (err != OK) {
1098 return err;
1099 }
1100
1101 *offset += chunk_size;
1102 break;
1103 }
1104
1105 case FOURCC('e', 's', 'd', 's'):
1106 {
1107 if (chunk_data_size < 4) {
1108 return ERROR_MALFORMED;
1109 }
1110
1111 uint8_t buffer[256];
James Dongb1262a82010-11-16 14:04:54 -08001112 if (chunk_data_size > (off64_t)sizeof(buffer)) {
Andreas Hubere46b7be2009-07-14 16:56:47 -07001113 return ERROR_BUFFER_TOO_SMALL;
1114 }
1115
Andreas Huber9a12baf2009-10-23 10:22:30 -07001116 if (mDataSource->readAt(
Andreas Hubere46b7be2009-07-14 16:56:47 -07001117 data_offset, buffer, chunk_data_size) < chunk_data_size) {
1118 return ERROR_IO;
1119 }
1120
1121 if (U32_AT(buffer) != 0) {
1122 // Should be version 0, flags 0.
1123 return ERROR_MALFORMED;
1124 }
1125
1126 mLastTrack->meta->setData(
1127 kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
1128
Andreas Huberd2315962010-01-29 14:46:59 -08001129 if (mPath.size() >= 2
1130 && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) {
1131 // Information from the ESDS must be relied on for proper
1132 // setup of sample rate and channel count for MPEG4 Audio.
1133 // The generic header appears to only contain generic
1134 // information...
1135
1136 status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio(
1137 &buffer[4], chunk_data_size - 4);
1138
1139 if (err != OK) {
1140 return err;
1141 }
1142 }
1143
Andreas Hubere46b7be2009-07-14 16:56:47 -07001144 *offset += chunk_size;
1145 break;
1146 }
1147
1148 case FOURCC('a', 'v', 'c', 'C'):
1149 {
1150 char buffer[256];
James Dongb1262a82010-11-16 14:04:54 -08001151 if (chunk_data_size > (off64_t)sizeof(buffer)) {
Andreas Hubere46b7be2009-07-14 16:56:47 -07001152 return ERROR_BUFFER_TOO_SMALL;
1153 }
1154
Andreas Huber9a12baf2009-10-23 10:22:30 -07001155 if (mDataSource->readAt(
Andreas Hubere46b7be2009-07-14 16:56:47 -07001156 data_offset, buffer, chunk_data_size) < chunk_data_size) {
1157 return ERROR_IO;
1158 }
1159
1160 mLastTrack->meta->setData(
1161 kKeyAVCC, kTypeAVCC, buffer, chunk_data_size);
1162
1163 *offset += chunk_size;
1164 break;
1165 }
1166
James Dongfe84cf12011-02-11 15:21:45 -08001167 case FOURCC('d', '2', '6', '3'):
1168 {
James Dongbc5f1f52011-02-23 17:07:49 -08001169 /*
1170 * d263 contains a fixed 7 bytes part:
1171 * vendor - 4 bytes
1172 * version - 1 byte
1173 * level - 1 byte
1174 * profile - 1 byte
1175 * optionally, "d263" box itself may contain a 16-byte
1176 * bit rate box (bitr)
1177 * average bit rate - 4 bytes
1178 * max bit rate - 4 bytes
1179 */
1180 char buffer[23];
1181 if (chunk_data_size != 7 &&
1182 chunk_data_size != 23) {
James Dongfe84cf12011-02-11 15:21:45 -08001183 LOGE("Incorrect D263 box size %lld", chunk_data_size);
1184 return ERROR_MALFORMED;
1185 }
1186
1187 if (mDataSource->readAt(
1188 data_offset, buffer, chunk_data_size) < chunk_data_size) {
1189 return ERROR_IO;
1190 }
1191
1192 mLastTrack->meta->setData(kKeyD263, kTypeD263, buffer, chunk_data_size);
1193
1194 *offset += chunk_size;
1195 break;
1196 }
1197
Andreas Huberc2c9dd32010-01-19 16:43:53 -08001198 case FOURCC('m', 'e', 't', 'a'):
1199 {
1200 uint8_t buffer[4];
James Dongb1262a82010-11-16 14:04:54 -08001201 if (chunk_data_size < (off64_t)sizeof(buffer)) {
Andreas Huber5ee0bce2010-02-23 10:12:02 -08001202 return ERROR_MALFORMED;
1203 }
1204
Andreas Huberc2c9dd32010-01-19 16:43:53 -08001205 if (mDataSource->readAt(
1206 data_offset, buffer, 4) < 4) {
1207 return ERROR_IO;
1208 }
1209
1210 if (U32_AT(buffer) != 0) {
1211 // Should be version 0, flags 0.
Andreas Huberdfb8eee2010-02-25 15:59:24 -08001212
1213 // If it's not, let's assume this is one of those
1214 // apparently malformed chunks that don't have flags
1215 // and completely different semantics than what's
1216 // in the MPEG4 specs and skip it.
1217 *offset += chunk_size;
1218 return OK;
Andreas Huberc2c9dd32010-01-19 16:43:53 -08001219 }
1220
James Dongb1262a82010-11-16 14:04:54 -08001221 off64_t stop_offset = *offset + chunk_size;
Andreas Huberc2c9dd32010-01-19 16:43:53 -08001222 *offset = data_offset + sizeof(buffer);
1223 while (*offset < stop_offset) {
1224 status_t err = parseChunk(offset, depth + 1);
1225 if (err != OK) {
1226 return err;
1227 }
1228 }
Andreas Huber5ee0bce2010-02-23 10:12:02 -08001229
1230 if (*offset != stop_offset) {
1231 return ERROR_MALFORMED;
1232 }
Andreas Huberc2c9dd32010-01-19 16:43:53 -08001233 break;
1234 }
1235
1236 case FOURCC('d', 'a', 't', 'a'):
1237 {
1238 if (mPath.size() == 6 && underMetaDataPath(mPath)) {
1239 status_t err = parseMetaData(data_offset, chunk_data_size);
1240
1241 if (err != OK) {
1242 return err;
1243 }
1244 }
1245
1246 *offset += chunk_size;
1247 break;
1248 }
1249
1250 case FOURCC('m', 'v', 'h', 'd'):
1251 {
1252 if (chunk_data_size < 12) {
1253 return ERROR_MALFORMED;
1254 }
1255
1256 uint8_t header[12];
1257 if (mDataSource->readAt(
1258 data_offset, header, sizeof(header))
1259 < (ssize_t)sizeof(header)) {
1260 return ERROR_IO;
1261 }
1262
1263 int64_t creationTime;
1264 if (header[0] == 1) {
1265 creationTime = U64_AT(&header[4]);
Andreas Huber5ee0bce2010-02-23 10:12:02 -08001266 } else if (header[0] != 0) {
1267 return ERROR_MALFORMED;
Andreas Huberc2c9dd32010-01-19 16:43:53 -08001268 } else {
Andreas Huberc2c9dd32010-01-19 16:43:53 -08001269 creationTime = U32_AT(&header[4]);
1270 }
1271
1272 String8 s;
1273 convertTimeToDate(creationTime, &s);
1274
1275 mFileMetaData->setCString(kKeyDate, s.string());
1276
1277 *offset += chunk_size;
1278 break;
1279 }
1280
Gloria Wangd5770912010-06-22 13:55:38 -07001281 case FOURCC('m', 'd', 'a', 't'):
1282 {
1283 if (!mIsDrm) {
1284 *offset += chunk_size;
1285 break;
1286 }
1287
1288 if (chunk_size < 8) {
1289 return ERROR_MALFORMED;
1290 }
1291
1292 return parseDrmSINF(offset, data_offset);
1293 }
1294
Andreas Hubere46b7be2009-07-14 16:56:47 -07001295 default:
1296 {
1297 *offset += chunk_size;
1298 break;
1299 }
1300 }
1301
1302 return OK;
1303}
1304
Andreas Huber940c8662010-11-16 15:26:30 -08001305status_t MPEG4Extractor::parseTrackHeader(
James Dongb1262a82010-11-16 14:04:54 -08001306 off64_t data_offset, off64_t data_size) {
Andreas Huber940c8662010-11-16 15:26:30 -08001307 if (data_size < 4) {
1308 return ERROR_MALFORMED;
1309 }
1310
1311 uint8_t version;
1312 if (mDataSource->readAt(data_offset, &version, 1) < 1) {
1313 return ERROR_IO;
1314 }
1315
1316 size_t dynSize = (version == 1) ? 36 : 24;
1317
1318 uint8_t buffer[36 + 60];
1319
James Dongb1262a82010-11-16 14:04:54 -08001320 if (data_size != (off64_t)dynSize + 60) {
Andreas Huber940c8662010-11-16 15:26:30 -08001321 return ERROR_MALFORMED;
1322 }
1323
1324 if (mDataSource->readAt(
1325 data_offset, buffer, data_size) < (ssize_t)data_size) {
1326 return ERROR_IO;
1327 }
1328
1329 uint64_t ctime, mtime, duration;
1330 int32_t id;
1331
1332 if (version == 1) {
1333 ctime = U64_AT(&buffer[4]);
1334 mtime = U64_AT(&buffer[12]);
1335 id = U32_AT(&buffer[20]);
1336 duration = U64_AT(&buffer[28]);
1337 } else {
1338 CHECK_EQ((unsigned)version, 0u);
1339
1340 ctime = U32_AT(&buffer[4]);
1341 mtime = U32_AT(&buffer[8]);
1342 id = U32_AT(&buffer[12]);
1343 duration = U32_AT(&buffer[20]);
1344 }
1345
1346 mLastTrack->meta->setInt32(kKeyTrackID, id);
1347
1348 size_t matrixOffset = dynSize + 16;
1349 int32_t a00 = U32_AT(&buffer[matrixOffset]);
1350 int32_t a01 = U32_AT(&buffer[matrixOffset + 4]);
1351 int32_t dx = U32_AT(&buffer[matrixOffset + 8]);
1352 int32_t a10 = U32_AT(&buffer[matrixOffset + 12]);
1353 int32_t a11 = U32_AT(&buffer[matrixOffset + 16]);
1354 int32_t dy = U32_AT(&buffer[matrixOffset + 20]);
1355
1356#if 0
1357 LOGI("x' = %.2f * x + %.2f * y + %.2f",
1358 a00 / 65536.0f, a01 / 65536.0f, dx / 65536.0f);
1359 LOGI("y' = %.2f * x + %.2f * y + %.2f",
1360 a10 / 65536.0f, a11 / 65536.0f, dy / 65536.0f);
1361#endif
1362
1363 uint32_t rotationDegrees;
1364
1365 static const int32_t kFixedOne = 0x10000;
1366 if (a00 == kFixedOne && a01 == 0 && a10 == 0 && a11 == kFixedOne) {
1367 // Identity, no rotation
1368 rotationDegrees = 0;
1369 } else if (a00 == 0 && a01 == kFixedOne && a10 == -kFixedOne && a11 == 0) {
1370 rotationDegrees = 90;
1371 } else if (a00 == 0 && a01 == -kFixedOne && a10 == kFixedOne && a11 == 0) {
1372 rotationDegrees = 270;
1373 } else if (a00 == -kFixedOne && a01 == 0 && a10 == 0 && a11 == -kFixedOne) {
1374 rotationDegrees = 180;
1375 } else {
1376 LOGW("We only support 0,90,180,270 degree rotation matrices");
1377 rotationDegrees = 0;
1378 }
1379
1380 if (rotationDegrees != 0) {
1381 mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees);
1382 }
1383
James Dong08adfd22011-01-16 11:30:13 -08001384 // Handle presentation display size, which could be different
1385 // from the image size indicated by kKeyWidth and kKeyHeight.
Andreas Huber940c8662010-11-16 15:26:30 -08001386 uint32_t width = U32_AT(&buffer[dynSize + 52]);
1387 uint32_t height = U32_AT(&buffer[dynSize + 56]);
James Dong08adfd22011-01-16 11:30:13 -08001388 mLastTrack->meta->setInt32(kKeyDisplayWidth, width >> 16);
1389 mLastTrack->meta->setInt32(kKeyDisplayHeight, height >> 16);
Andreas Huber940c8662010-11-16 15:26:30 -08001390
1391 return OK;
1392}
1393
James Dongb1262a82010-11-16 14:04:54 -08001394status_t MPEG4Extractor::parseMetaData(off64_t offset, size_t size) {
Andreas Huberc2c9dd32010-01-19 16:43:53 -08001395 if (size < 4) {
1396 return ERROR_MALFORMED;
1397 }
1398
1399 uint8_t *buffer = new uint8_t[size + 1];
1400 if (mDataSource->readAt(
1401 offset, buffer, size) != (ssize_t)size) {
1402 delete[] buffer;
1403 buffer = NULL;
1404
1405 return ERROR_IO;
1406 }
1407
1408 uint32_t flags = U32_AT(buffer);
1409
1410 uint32_t metadataKey = 0;
1411 switch (mPath[4]) {
1412 case FOURCC(0xa9, 'a', 'l', 'b'):
1413 {
1414 metadataKey = kKeyAlbum;
1415 break;
1416 }
1417 case FOURCC(0xa9, 'A', 'R', 'T'):
1418 {
1419 metadataKey = kKeyArtist;
1420 break;
1421 }
Marco Nelissenc5d5ee32010-02-11 13:31:44 -08001422 case FOURCC('a', 'A', 'R', 'T'):
1423 {
1424 metadataKey = kKeyAlbumArtist;
1425 break;
1426 }
Andreas Huberc2c9dd32010-01-19 16:43:53 -08001427 case FOURCC(0xa9, 'd', 'a', 'y'):
1428 {
1429 metadataKey = kKeyYear;
1430 break;
1431 }
1432 case FOURCC(0xa9, 'n', 'a', 'm'):
1433 {
1434 metadataKey = kKeyTitle;
1435 break;
1436 }
1437 case FOURCC(0xa9, 'w', 'r', 't'):
1438 {
1439 metadataKey = kKeyWriter;
1440 break;
1441 }
1442 case FOURCC('c', 'o', 'v', 'r'):
1443 {
1444 metadataKey = kKeyAlbumArt;
1445 break;
1446 }
1447 case FOURCC('g', 'n', 'r', 'e'):
1448 {
1449 metadataKey = kKeyGenre;
1450 break;
1451 }
Marco Nelissenfe3b8e92010-02-09 14:02:16 -08001452 case FOURCC(0xa9, 'g', 'e', 'n'):
1453 {
1454 metadataKey = kKeyGenre;
1455 break;
1456 }
Marco Nelissenee35aff2011-01-06 11:12:17 -08001457 case FOURCC('c', 'p', 'i', 'l'):
1458 {
1459 if (size == 9 && flags == 21) {
1460 char tmp[16];
1461 sprintf(tmp, "%d",
1462 (int)buffer[size - 1]);
1463
1464 mFileMetaData->setCString(kKeyCompilation, tmp);
1465 }
1466 break;
1467 }
Andreas Huberc2c9dd32010-01-19 16:43:53 -08001468 case FOURCC('t', 'r', 'k', 'n'):
1469 {
1470 if (size == 16 && flags == 0) {
1471 char tmp[16];
1472 sprintf(tmp, "%d/%d",
1473 (int)buffer[size - 5], (int)buffer[size - 3]);
1474
Andreas Huberc2c9dd32010-01-19 16:43:53 -08001475 mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
1476 }
1477 break;
1478 }
Marco Nelissenfe3b8e92010-02-09 14:02:16 -08001479 case FOURCC('d', 'i', 's', 'k'):
1480 {
1481 if (size == 14 && flags == 0) {
1482 char tmp[16];
1483 sprintf(tmp, "%d/%d",
1484 (int)buffer[size - 3], (int)buffer[size - 1]);
1485
1486 mFileMetaData->setCString(kKeyDiscNumber, tmp);
1487 }
1488 break;
1489 }
1490
Andreas Huberc2c9dd32010-01-19 16:43:53 -08001491 default:
1492 break;
1493 }
1494
1495 if (size >= 8 && metadataKey) {
1496 if (metadataKey == kKeyAlbumArt) {
1497 mFileMetaData->setData(
1498 kKeyAlbumArt, MetaData::TYPE_NONE,
1499 buffer + 8, size - 8);
1500 } else if (metadataKey == kKeyGenre) {
1501 if (flags == 0) {
Marco Nelissenfe3b8e92010-02-09 14:02:16 -08001502 // uint8_t genre code, iTunes genre codes are
1503 // the standard id3 codes, except they start
1504 // at 1 instead of 0 (e.g. Pop is 14, not 13)
1505 // We use standard id3 numbering, so subtract 1.
1506 int genrecode = (int)buffer[size - 1];
1507 genrecode--;
1508 if (genrecode < 0) {
1509 genrecode = 255; // reserved for 'unknown genre'
1510 }
Andreas Huberc2c9dd32010-01-19 16:43:53 -08001511 char genre[10];
Marco Nelissenfe3b8e92010-02-09 14:02:16 -08001512 sprintf(genre, "%d", genrecode);
Andreas Huberc2c9dd32010-01-19 16:43:53 -08001513
1514 mFileMetaData->setCString(metadataKey, genre);
Marco Nelissenfe3b8e92010-02-09 14:02:16 -08001515 } else if (flags == 1) {
1516 // custom genre string
1517 buffer[size] = '\0';
1518
1519 mFileMetaData->setCString(
1520 metadataKey, (const char *)buffer + 8);
Andreas Huberc2c9dd32010-01-19 16:43:53 -08001521 }
1522 } else {
1523 buffer[size] = '\0';
1524
1525 mFileMetaData->setCString(
1526 metadataKey, (const char *)buffer + 8);
1527 }
1528 }
1529
1530 delete[] buffer;
1531 buffer = NULL;
1532
1533 return OK;
1534}
1535
Andreas Huberbe06d262009-08-14 14:37:10 -07001536sp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
Andreas Hubere46b7be2009-07-14 16:56:47 -07001537 status_t err;
1538 if ((err = readMetaData()) != OK) {
Andreas Huberbe06d262009-08-14 14:37:10 -07001539 return NULL;
Andreas Hubere46b7be2009-07-14 16:56:47 -07001540 }
1541
1542 Track *track = mFirstTrack;
1543 while (index > 0) {
1544 if (track == NULL) {
Andreas Huberbe06d262009-08-14 14:37:10 -07001545 return NULL;
Andreas Hubere46b7be2009-07-14 16:56:47 -07001546 }
1547
1548 track = track->next;
1549 --index;
1550 }
1551
Andreas Huber2a651172009-09-09 16:32:59 -07001552 if (track == NULL) {
1553 return NULL;
1554 }
1555
Andreas Huberbe06d262009-08-14 14:37:10 -07001556 return new MPEG4Source(
Andreas Huberfa8de752009-10-08 10:07:49 -07001557 track->meta, mDataSource, track->timescale, track->sampleTable);
Andreas Hubere46b7be2009-07-14 16:56:47 -07001558}
1559
Andreas Huber5ee0bce2010-02-23 10:12:02 -08001560// static
1561status_t MPEG4Extractor::verifyTrack(Track *track) {
1562 const char *mime;
1563 CHECK(track->meta->findCString(kKeyMIMEType, &mime));
1564
1565 uint32_t type;
1566 const void *data;
1567 size_t size;
1568 if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
1569 if (!track->meta->findData(kKeyAVCC, &type, &data, &size)
1570 || type != kTypeAVCC) {
1571 return ERROR_MALFORMED;
1572 }
1573 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
1574 || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
1575 if (!track->meta->findData(kKeyESDS, &type, &data, &size)
1576 || type != kTypeESDS) {
1577 return ERROR_MALFORMED;
1578 }
1579 }
1580
1581 return OK;
1582}
1583
Andreas Huberd2315962010-01-29 14:46:59 -08001584status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(
1585 const void *esds_data, size_t esds_size) {
1586 ESDS esds(esds_data, esds_size);
Andreas Huberd0332ad2010-04-12 16:05:57 -07001587
1588 uint8_t objectTypeIndication;
1589 if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) {
1590 return ERROR_MALFORMED;
1591 }
1592
1593 if (objectTypeIndication == 0xe1) {
1594 // This isn't MPEG4 audio at all, it's QCELP 14k...
1595 mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
1596 return OK;
1597 }
1598
James Donge883d312011-02-24 21:16:54 -08001599 if (objectTypeIndication == 0x6b) {
1600 // The media subtype is MP3 audio
1601 // Our software MP3 audio decoder may not be able to handle
1602 // packetized MP3 audio; for now, lets just return ERROR_UNSUPPORTED
1603 LOGE("MP3 track in MP4/3GPP file is not supported");
1604 return ERROR_UNSUPPORTED;
1605 }
1606
Andreas Huberd2315962010-01-29 14:46:59 -08001607 const uint8_t *csd;
1608 size_t csd_size;
1609 if (esds.getCodecSpecificInfo(
1610 (const void **)&csd, &csd_size) != OK) {
1611 return ERROR_MALFORMED;
1612 }
1613
1614#if 0
1615 printf("ESD of size %d\n", csd_size);
1616 hexdump(csd, csd_size);
1617#endif
1618
Andreas Huber08c94b22010-08-18 09:58:30 -07001619 if (csd_size == 0) {
1620 // There's no further information, i.e. no codec specific data
1621 // Let's assume that the information provided in the mpeg4 headers
1622 // is accurate and hope for the best.
1623
1624 return OK;
1625 }
1626
Andreas Huberd2315962010-01-29 14:46:59 -08001627 if (csd_size < 2) {
1628 return ERROR_MALFORMED;
1629 }
1630
1631 uint32_t objectType = csd[0] >> 3;
1632
1633 if (objectType == 31) {
1634 return ERROR_UNSUPPORTED;
1635 }
1636
1637 uint32_t freqIndex = (csd[0] & 7) << 1 | (csd[1] >> 7);
1638 int32_t sampleRate = 0;
1639 int32_t numChannels = 0;
1640 if (freqIndex == 15) {
1641 if (csd_size < 5) {
1642 return ERROR_MALFORMED;
1643 }
1644
1645 sampleRate = (csd[1] & 0x7f) << 17
1646 | csd[2] << 9
1647 | csd[3] << 1
1648 | (csd[4] >> 7);
1649
1650 numChannels = (csd[4] >> 3) & 15;
1651 } else {
Andreas Hubercc14a832010-07-20 09:21:17 -07001652 static uint32_t kSamplingRate[] = {
1653 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
1654 16000, 12000, 11025, 8000, 7350
1655 };
Andreas Huberd2315962010-01-29 14:46:59 -08001656
1657 if (freqIndex == 13 || freqIndex == 14) {
1658 return ERROR_MALFORMED;
1659 }
1660
1661 sampleRate = kSamplingRate[freqIndex];
1662 numChannels = (csd[1] >> 3) & 15;
1663 }
1664
1665 if (numChannels == 0) {
1666 return ERROR_UNSUPPORTED;
1667 }
1668
1669 int32_t prevSampleRate;
1670 CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));
1671
1672 if (prevSampleRate != sampleRate) {
Andreas Huber4a9375e2010-02-09 11:54:33 -08001673 LOGV("mpeg4 audio sample rate different from previous setting. "
Andreas Huberd2315962010-01-29 14:46:59 -08001674 "was: %d, now: %d", prevSampleRate, sampleRate);
1675 }
1676
1677 mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
1678
1679 int32_t prevChannelCount;
1680 CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount));
1681
1682 if (prevChannelCount != numChannels) {
Andreas Huber4a9375e2010-02-09 11:54:33 -08001683 LOGV("mpeg4 audio channel count different from previous setting. "
Andreas Huberd2315962010-01-29 14:46:59 -08001684 "was: %d, now: %d", prevChannelCount, numChannels);
1685 }
1686
1687 mLastTrack->meta->setInt32(kKeyChannelCount, numChannels);
1688
1689 return OK;
1690}
1691
Andreas Hubere46b7be2009-07-14 16:56:47 -07001692////////////////////////////////////////////////////////////////////////////////
1693
1694MPEG4Source::MPEG4Source(
1695 const sp<MetaData> &format,
Andreas Huberbe06d262009-08-14 14:37:10 -07001696 const sp<DataSource> &dataSource,
Andreas Huberfa8de752009-10-08 10:07:49 -07001697 int32_t timeScale,
Andreas Huberbe06d262009-08-14 14:37:10 -07001698 const sp<SampleTable> &sampleTable)
Andreas Hubere46b7be2009-07-14 16:56:47 -07001699 : mFormat(format),
1700 mDataSource(dataSource),
Andreas Huberfa8de752009-10-08 10:07:49 -07001701 mTimescale(timeScale),
Andreas Hubere46b7be2009-07-14 16:56:47 -07001702 mSampleTable(sampleTable),
1703 mCurrentSampleIndex(0),
1704 mIsAVC(false),
Andreas Huberdb5d6622010-01-12 16:30:44 -08001705 mNALLengthSize(0),
Andreas Hubere46b7be2009-07-14 16:56:47 -07001706 mStarted(false),
1707 mGroup(NULL),
1708 mBuffer(NULL),
Andreas Huber4f5e6022009-08-19 09:29:34 -07001709 mWantsNALFragments(false),
Andreas Huber8a432772009-07-28 10:03:13 -07001710 mSrcBuffer(NULL) {
Andreas Hubere46b7be2009-07-14 16:56:47 -07001711 const char *mime;
1712 bool success = mFormat->findCString(kKeyMIMEType, &mime);
Andreas Huber4f5e6022009-08-19 09:29:34 -07001713 CHECK(success);
Andreas Hubere46b7be2009-07-14 16:56:47 -07001714
Andreas Hubere6c40962009-09-10 14:13:30 -07001715 mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
Andreas Huberdb5d6622010-01-12 16:30:44 -08001716
1717 if (mIsAVC) {
1718 uint32_t type;
1719 const void *data;
1720 size_t size;
1721 CHECK(format->findData(kKeyAVCC, &type, &data, &size));
1722
1723 const uint8_t *ptr = (const uint8_t *)data;
1724
1725 CHECK(size >= 7);
Andreas Huber940c8662010-11-16 15:26:30 -08001726 CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1
Andreas Huberdb5d6622010-01-12 16:30:44 -08001727
1728 // The number of bytes used to encode the length of a NAL unit.
1729 mNALLengthSize = 1 + (ptr[4] & 3);
1730 }
Andreas Hubere46b7be2009-07-14 16:56:47 -07001731}
1732
1733MPEG4Source::~MPEG4Source() {
1734 if (mStarted) {
1735 stop();
1736 }
1737}
1738
1739status_t MPEG4Source::start(MetaData *params) {
Andreas Huberba7ec912010-02-12 10:42:02 -08001740 Mutex::Autolock autoLock(mLock);
1741
Andreas Huber4f5e6022009-08-19 09:29:34 -07001742 CHECK(!mStarted);
Andreas Hubere46b7be2009-07-14 16:56:47 -07001743
1744 int32_t val;
Andreas Huber4f5e6022009-08-19 09:29:34 -07001745 if (params && params->findInt32(kKeyWantsNALFragments, &val)
Andreas Hubere46b7be2009-07-14 16:56:47 -07001746 && val != 0) {
Andreas Huber4f5e6022009-08-19 09:29:34 -07001747 mWantsNALFragments = true;
Andreas Hubere46b7be2009-07-14 16:56:47 -07001748 } else {
Andreas Huber4f5e6022009-08-19 09:29:34 -07001749 mWantsNALFragments = false;
Andreas Hubere46b7be2009-07-14 16:56:47 -07001750 }
1751
1752 mGroup = new MediaBufferGroup;
1753
Andreas Huber1bceff92009-11-23 14:03:32 -08001754 int32_t max_size;
1755 CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size));
Andreas Hubere46b7be2009-07-14 16:56:47 -07001756
Andreas Huber1bceff92009-11-23 14:03:32 -08001757 mGroup->add_buffer(new MediaBuffer(max_size));
Andreas Huber8a432772009-07-28 10:03:13 -07001758
1759 mSrcBuffer = new uint8_t[max_size];
Andreas Hubere46b7be2009-07-14 16:56:47 -07001760
1761 mStarted = true;
1762
1763 return OK;
1764}
1765
1766status_t MPEG4Source::stop() {
Andreas Huberba7ec912010-02-12 10:42:02 -08001767 Mutex::Autolock autoLock(mLock);
1768
Andreas Huber4f5e6022009-08-19 09:29:34 -07001769 CHECK(mStarted);
Andreas Hubere46b7be2009-07-14 16:56:47 -07001770
1771 if (mBuffer != NULL) {
1772 mBuffer->release();
1773 mBuffer = NULL;
1774 }
1775
Andreas Huber8a432772009-07-28 10:03:13 -07001776 delete[] mSrcBuffer;
1777 mSrcBuffer = NULL;
1778
Andreas Hubere46b7be2009-07-14 16:56:47 -07001779 delete mGroup;
1780 mGroup = NULL;
1781
1782 mStarted = false;
1783 mCurrentSampleIndex = 0;
1784
1785 return OK;
1786}
1787
1788sp<MetaData> MPEG4Source::getFormat() {
Andreas Huberba7ec912010-02-12 10:42:02 -08001789 Mutex::Autolock autoLock(mLock);
1790
Andreas Hubere46b7be2009-07-14 16:56:47 -07001791 return mFormat;
1792}
1793
Andreas Huberdb5d6622010-01-12 16:30:44 -08001794size_t MPEG4Source::parseNALSize(const uint8_t *data) const {
1795 switch (mNALLengthSize) {
1796 case 1:
1797 return *data;
1798 case 2:
1799 return U16_AT(data);
1800 case 3:
1801 return ((size_t)data[0] << 16) | U16_AT(&data[1]);
1802 case 4:
1803 return U32_AT(data);
1804 }
1805
1806 // This cannot happen, mNALLengthSize springs to life by adding 1 to
1807 // a 2-bit integer.
1808 CHECK(!"Should not be here.");
1809
1810 return 0;
1811}
1812
Andreas Hubere46b7be2009-07-14 16:56:47 -07001813status_t MPEG4Source::read(
1814 MediaBuffer **out, const ReadOptions *options) {
Andreas Huberba7ec912010-02-12 10:42:02 -08001815 Mutex::Autolock autoLock(mLock);
1816
Andreas Huber4f5e6022009-08-19 09:29:34 -07001817 CHECK(mStarted);
Andreas Hubere46b7be2009-07-14 16:56:47 -07001818
1819 *out = NULL;
1820
Andreas Huber6624c9f2010-07-20 15:04:28 -07001821 int64_t targetSampleTimeUs = -1;
1822
Andreas Hubere46b7be2009-07-14 16:56:47 -07001823 int64_t seekTimeUs;
Andreas Huber6624c9f2010-07-20 15:04:28 -07001824 ReadOptions::SeekMode mode;
1825 if (options && options->getSeekTo(&seekTimeUs, &mode)) {
1826 uint32_t findFlags = 0;
1827 switch (mode) {
1828 case ReadOptions::SEEK_PREVIOUS_SYNC:
1829 findFlags = SampleTable::kFlagBefore;
1830 break;
1831 case ReadOptions::SEEK_NEXT_SYNC:
1832 findFlags = SampleTable::kFlagAfter;
1833 break;
1834 case ReadOptions::SEEK_CLOSEST_SYNC:
1835 case ReadOptions::SEEK_CLOSEST:
1836 findFlags = SampleTable::kFlagClosest;
1837 break;
1838 default:
1839 CHECK(!"Should not be here.");
1840 break;
1841 }
1842
Andreas Hubere46b7be2009-07-14 16:56:47 -07001843 uint32_t sampleIndex;
Andreas Huber6624c9f2010-07-20 15:04:28 -07001844 status_t err = mSampleTable->findSampleAtTime(
Andreas Hubere46b7be2009-07-14 16:56:47 -07001845 seekTimeUs * mTimescale / 1000000,
Andreas Huber6624c9f2010-07-20 15:04:28 -07001846 &sampleIndex, findFlags);
1847
1848 if (mode == ReadOptions::SEEK_CLOSEST) {
1849 // We found the closest sample already, now we want the sync
1850 // sample preceding it (or the sample itself of course), even
1851 // if the subsequent sync sample is closer.
1852 findFlags = SampleTable::kFlagBefore;
1853 }
1854
1855 uint32_t syncSampleIndex;
1856 if (err == OK) {
1857 err = mSampleTable->findSyncSampleNear(
1858 sampleIndex, &syncSampleIndex, findFlags);
1859 }
Andreas Hubere46b7be2009-07-14 16:56:47 -07001860
1861 if (err != OK) {
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001862 if (err == ERROR_OUT_OF_RANGE) {
1863 // An attempt to seek past the end of the stream would
1864 // normally cause this ERROR_OUT_OF_RANGE error. Propagating
1865 // this all the way to the MediaPlayer would cause abnormal
1866 // termination. Legacy behaviour appears to be to behave as if
1867 // we had seeked to the end of stream, ending normally.
1868 err = ERROR_END_OF_STREAM;
1869 }
Andreas Hubere46b7be2009-07-14 16:56:47 -07001870 return err;
1871 }
1872
Andreas Huber6624c9f2010-07-20 15:04:28 -07001873 uint32_t sampleTime;
Andreas Huber940c8662010-11-16 15:26:30 -08001874 CHECK_EQ((status_t)OK, mSampleTable->getMetaDataForSample(
Andreas Huber6624c9f2010-07-20 15:04:28 -07001875 sampleIndex, NULL, NULL, &sampleTime));
1876
1877 if (mode == ReadOptions::SEEK_CLOSEST) {
1878 targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
1879 }
1880
1881#if 0
1882 uint32_t syncSampleTime;
1883 CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
1884 syncSampleIndex, NULL, NULL, &syncSampleTime));
1885
1886 LOGI("seek to time %lld us => sample at time %lld us, "
1887 "sync sample at time %lld us",
1888 seekTimeUs,
1889 sampleTime * 1000000ll / mTimescale,
1890 syncSampleTime * 1000000ll / mTimescale);
1891#endif
1892
1893 mCurrentSampleIndex = syncSampleIndex;
Andreas Hubere46b7be2009-07-14 16:56:47 -07001894 if (mBuffer != NULL) {
1895 mBuffer->release();
1896 mBuffer = NULL;
1897 }
1898
1899 // fall through
1900 }
1901
James Dongb1262a82010-11-16 14:04:54 -08001902 off64_t offset;
Andreas Huber8a432772009-07-28 10:03:13 -07001903 size_t size;
Andreas Huber8a432772009-07-28 10:03:13 -07001904 uint32_t dts;
Andreas Huberad98d382010-08-06 14:13:10 -07001905 bool isSyncSample;
Andreas Huber4f5e6022009-08-19 09:29:34 -07001906 bool newBuffer = false;
1907 if (mBuffer == NULL) {
1908 newBuffer = true;
Andreas Hubere46b7be2009-07-14 16:56:47 -07001909
Andreas Huber1faa92a2010-01-19 10:39:21 -08001910 status_t err =
1911 mSampleTable->getMetaDataForSample(
Andreas Huberad98d382010-08-06 14:13:10 -07001912 mCurrentSampleIndex, &offset, &size, &dts, &isSyncSample);
Andreas Huber4f5e6022009-08-19 09:29:34 -07001913
1914 if (err != OK) {
1915 return err;
1916 }
1917
1918 err = mGroup->acquire_buffer(&mBuffer);
Andreas Huber1faa92a2010-01-19 10:39:21 -08001919
Andreas Huber4f5e6022009-08-19 09:29:34 -07001920 if (err != OK) {
Andreas Huber940c8662010-11-16 15:26:30 -08001921 CHECK(mBuffer == NULL);
Andreas Huber4f5e6022009-08-19 09:29:34 -07001922 return err;
1923 }
Andreas Huber8a432772009-07-28 10:03:13 -07001924 }
Andreas Hubere46b7be2009-07-14 16:56:47 -07001925
Andreas Huber4f5e6022009-08-19 09:29:34 -07001926 if (!mIsAVC || mWantsNALFragments) {
1927 if (newBuffer) {
1928 ssize_t num_bytes_read =
Andreas Huber9a12baf2009-10-23 10:22:30 -07001929 mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
Andreas Hubere46b7be2009-07-14 16:56:47 -07001930
Andreas Huber4f5e6022009-08-19 09:29:34 -07001931 if (num_bytes_read < (ssize_t)size) {
1932 mBuffer->release();
1933 mBuffer = NULL;
1934
1935 return ERROR_IO;
1936 }
1937
Andreas Huberba7ec912010-02-12 10:42:02 -08001938 CHECK(mBuffer != NULL);
Andreas Huber4f5e6022009-08-19 09:29:34 -07001939 mBuffer->set_range(0, size);
1940 mBuffer->meta_data()->clear();
Andreas Huberfa8de752009-10-08 10:07:49 -07001941 mBuffer->meta_data()->setInt64(
1942 kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
Andreas Huber6624c9f2010-07-20 15:04:28 -07001943
1944 if (targetSampleTimeUs >= 0) {
1945 mBuffer->meta_data()->setInt64(
1946 kKeyTargetTime, targetSampleTimeUs);
1947 }
1948
Andreas Huberad98d382010-08-06 14:13:10 -07001949 if (isSyncSample) {
1950 mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
1951 }
1952
Andreas Huber4f5e6022009-08-19 09:29:34 -07001953 ++mCurrentSampleIndex;
1954 }
1955
1956 if (!mIsAVC) {
1957 *out = mBuffer;
1958 mBuffer = NULL;
1959
1960 return OK;
1961 }
1962
1963 // Each NAL unit is split up into its constituent fragments and
1964 // each one of them returned in its own buffer.
1965
Andreas Huberdb5d6622010-01-12 16:30:44 -08001966 CHECK(mBuffer->range_length() >= mNALLengthSize);
Andreas Huber4f5e6022009-08-19 09:29:34 -07001967
1968 const uint8_t *src =
1969 (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
1970
Andreas Huberdb5d6622010-01-12 16:30:44 -08001971 size_t nal_size = parseNALSize(src);
Andreas Huber909255a2010-01-14 14:13:15 -08001972 if (mBuffer->range_length() < mNALLengthSize + nal_size) {
1973 LOGE("incomplete NAL unit.");
1974
1975 mBuffer->release();
1976 mBuffer = NULL;
1977
1978 return ERROR_MALFORMED;
1979 }
Andreas Huber4f5e6022009-08-19 09:29:34 -07001980
1981 MediaBuffer *clone = mBuffer->clone();
Andreas Huberba7ec912010-02-12 10:42:02 -08001982 CHECK(clone != NULL);
Andreas Huberdb5d6622010-01-12 16:30:44 -08001983 clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
Andreas Huber4f5e6022009-08-19 09:29:34 -07001984
Andreas Huberba7ec912010-02-12 10:42:02 -08001985 CHECK(mBuffer != NULL);
Andreas Huber4f5e6022009-08-19 09:29:34 -07001986 mBuffer->set_range(
Andreas Huberdb5d6622010-01-12 16:30:44 -08001987 mBuffer->range_offset() + mNALLengthSize + nal_size,
1988 mBuffer->range_length() - mNALLengthSize - nal_size);
Andreas Huber4f5e6022009-08-19 09:29:34 -07001989
1990 if (mBuffer->range_length() == 0) {
1991 mBuffer->release();
1992 mBuffer = NULL;
1993 }
1994
1995 *out = clone;
1996
1997 return OK;
1998 } else {
1999 // Whole NAL units are returned but each fragment is prefixed by
2000 // the start code (0x00 00 00 01).
Gloria Wangd5770912010-06-22 13:55:38 -07002001 ssize_t num_bytes_read = 0;
2002 int32_t drm = 0;
2003 bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
2004 if (usesDRM) {
2005 num_bytes_read =
2006 mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
2007 } else {
2008 num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
2009 }
Andreas Hubere46b7be2009-07-14 16:56:47 -07002010
2011 if (num_bytes_read < (ssize_t)size) {
2012 mBuffer->release();
2013 mBuffer = NULL;
2014
Andreas Huber4f5e6022009-08-19 09:29:34 -07002015 return ERROR_IO;
Andreas Hubere46b7be2009-07-14 16:56:47 -07002016 }
2017
Gloria Wangd5770912010-06-22 13:55:38 -07002018 if (usesDRM) {
2019 CHECK(mBuffer != NULL);
2020 mBuffer->set_range(0, size);
Andreas Huberdb5d6622010-01-12 16:30:44 -08002021
Gloria Wangd5770912010-06-22 13:55:38 -07002022 } else {
2023 uint8_t *dstData = (uint8_t *)mBuffer->data();
2024 size_t srcOffset = 0;
2025 size_t dstOffset = 0;
Andreas Huber909255a2010-01-14 14:13:15 -08002026
Gloria Wangd5770912010-06-22 13:55:38 -07002027 while (srcOffset < size) {
2028 CHECK(srcOffset + mNALLengthSize <= size);
2029 size_t nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
2030 srcOffset += mNALLengthSize;
Andreas Huber909255a2010-01-14 14:13:15 -08002031
Gloria Wangd5770912010-06-22 13:55:38 -07002032 if (srcOffset + nalLength > size) {
2033 mBuffer->release();
2034 mBuffer = NULL;
2035
2036 return ERROR_MALFORMED;
2037 }
2038
2039 if (nalLength == 0) {
2040 continue;
2041 }
2042
2043 CHECK(dstOffset + 4 <= mBuffer->size());
2044
2045 dstData[dstOffset++] = 0;
2046 dstData[dstOffset++] = 0;
2047 dstData[dstOffset++] = 0;
2048 dstData[dstOffset++] = 1;
2049 memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
2050 srcOffset += nalLength;
2051 dstOffset += nalLength;
Andreas Huber909255a2010-01-14 14:13:15 -08002052 }
Gloria Wangd5770912010-06-22 13:55:38 -07002053 CHECK_EQ(srcOffset, size);
2054 CHECK(mBuffer != NULL);
2055 mBuffer->set_range(0, dstOffset);
Andreas Huber4f5e6022009-08-19 09:29:34 -07002056 }
2057
Andreas Hubere46b7be2009-07-14 16:56:47 -07002058 mBuffer->meta_data()->clear();
Andreas Huberfa8de752009-10-08 10:07:49 -07002059 mBuffer->meta_data()->setInt64(
2060 kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
Andreas Huber6624c9f2010-07-20 15:04:28 -07002061
2062 if (targetSampleTimeUs >= 0) {
2063 mBuffer->meta_data()->setInt64(
2064 kKeyTargetTime, targetSampleTimeUs);
2065 }
2066
Andreas Huberad98d382010-08-06 14:13:10 -07002067 if (isSyncSample) {
2068 mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
2069 }
2070
Andreas Hubere46b7be2009-07-14 16:56:47 -07002071 ++mCurrentSampleIndex;
2072
Andreas Hubere46b7be2009-07-14 16:56:47 -07002073 *out = mBuffer;
2074 mBuffer = NULL;
2075
2076 return OK;
2077 }
Andreas Hubere46b7be2009-07-14 16:56:47 -07002078}
2079
Andreas Huber261eb0c2010-05-27 09:59:54 -07002080static bool LegacySniffMPEG4(
Andreas Huberbe06d262009-08-14 14:37:10 -07002081 const sp<DataSource> &source, String8 *mimeType, float *confidence) {
Andreas Hubere46b7be2009-07-14 16:56:47 -07002082 uint8_t header[8];
2083
Andreas Huber9a12baf2009-10-23 10:22:30 -07002084 ssize_t n = source->readAt(4, header, sizeof(header));
Andreas Hubere46b7be2009-07-14 16:56:47 -07002085 if (n < (ssize_t)sizeof(header)) {
2086 return false;
2087 }
2088
2089 if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
James Donge1130662010-04-13 15:06:41 -07002090 || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8)
2091 || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8)
Andreas Huber6bce6d82009-11-03 16:00:58 -08002092 || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
Andreas Huberdfb8eee2010-02-25 15:59:24 -08002093 || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)
Andreas Hubereea1eef2010-04-01 11:42:50 -07002094 || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) {
Andreas Hubere6c40962009-09-10 14:13:30 -07002095 *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
Andreas Huberefdd0882010-08-25 11:09:41 -07002096 *confidence = 0.4;
Andreas Hubere46b7be2009-07-14 16:56:47 -07002097
2098 return true;
2099 }
2100
2101 return false;
2102}
2103
Andreas Huber261eb0c2010-05-27 09:59:54 -07002104static bool isCompatibleBrand(uint32_t fourcc) {
2105 static const uint32_t kCompatibleBrands[] = {
2106 FOURCC('i', 's', 'o', 'm'),
2107 FOURCC('i', 's', 'o', '2'),
2108 FOURCC('a', 'v', 'c', '1'),
2109 FOURCC('3', 'g', 'p', '4'),
2110 FOURCC('m', 'p', '4', '1'),
2111 FOURCC('m', 'p', '4', '2'),
2112 };
2113
2114 for (size_t i = 0;
2115 i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]);
2116 ++i) {
2117 if (kCompatibleBrands[i] == fourcc) {
2118 return true;
2119 }
2120 }
2121
2122 return false;
2123}
2124
2125// Attempt to actually parse the 'ftyp' atom and determine if a suitable
2126// compatible brand is present.
2127static bool BetterSniffMPEG4(
2128 const sp<DataSource> &source, String8 *mimeType, float *confidence) {
2129 uint8_t header[12];
2130 if (source->readAt(0, header, 12) != 12
2131 || memcmp("ftyp", &header[4], 4)) {
2132 return false;
2133 }
2134
2135 size_t atomSize = U32_AT(&header[0]);
2136 if (atomSize < 16 || (atomSize % 4) != 0) {
2137 return false;
2138 }
2139
2140 bool success = false;
2141 if (isCompatibleBrand(U32_AT(&header[8]))) {
2142 success = true;
2143 } else {
2144 size_t numCompatibleBrands = (atomSize - 16) / 4;
2145 for (size_t i = 0; i < numCompatibleBrands; ++i) {
2146 uint8_t tmp[4];
2147 if (source->readAt(16 + i * 4, tmp, 4) != 4) {
2148 return false;
2149 }
2150
2151 if (isCompatibleBrand(U32_AT(&tmp[0]))) {
2152 success = true;
2153 break;
2154 }
2155 }
2156 }
2157
2158 if (!success) {
2159 return false;
2160 }
2161
2162 *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
Andreas Huberefdd0882010-08-25 11:09:41 -07002163 *confidence = 0.4f;
Andreas Huber261eb0c2010-05-27 09:59:54 -07002164
2165 return true;
2166}
2167
2168bool SniffMPEG4(
Andreas Huberefdd0882010-08-25 11:09:41 -07002169 const sp<DataSource> &source, String8 *mimeType, float *confidence,
2170 sp<AMessage> *) {
Andreas Huber261eb0c2010-05-27 09:59:54 -07002171 if (BetterSniffMPEG4(source, mimeType, confidence)) {
2172 return true;
2173 }
2174
2175 if (LegacySniffMPEG4(source, mimeType, confidence)) {
2176 LOGW("Identified supported mpeg4 through LegacySniffMPEG4.");
2177 return true;
2178 }
2179
2180 return false;
2181}
2182
Andreas Hubere46b7be2009-07-14 16:56:47 -07002183} // namespace android
2184