blob: 34064c8c583d846e548b68d3c8694fb6f3bcfe94 [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 Huber31dc9112010-11-04 11:50:27 -070030#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;
101 virtual ssize_t readAt(off_t offset, void *data, size_t size);
102 virtual status_t getSize(off_t *size);
103 virtual uint32_t flags();
104
105 status_t setCachedRange(off_t offset, size_t size);
106
107protected:
108 virtual ~MPEG4DataSource();
109
110private:
111 Mutex mLock;
112
113 sp<DataSource> mSource;
114 off_t mCachedOffset;
115 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
149ssize_t MPEG4DataSource::readAt(off_t offset, void *data, size_t size) {
150 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
161status_t MPEG4DataSource::getSize(off_t *size) {
162 return mSource->getSize(size);
163}
164
165uint32_t MPEG4DataSource::flags() {
166 return mSource->flags();
167}
168
169status_t MPEG4DataSource::setCachedRange(off_t offset, size_t size) {
170 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'):
Andreas Hubere6c40962009-09-10 14:13:30 -0700250 return MEDIA_MIMETYPE_VIDEO_H263;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700251
252 case FOURCC('a', 'v', 'c', '1'):
Andreas Hubere6c40962009-09-10 14:13:30 -0700253 return MEDIA_MIMETYPE_VIDEO_AVC;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700254
255 default:
Andreas Huber4f5e6022009-08-19 09:29:34 -0700256 CHECK(!"should not be here.");
Andreas Hubere46b7be2009-07-14 16:56:47 -0700257 return NULL;
258 }
259}
260
Andreas Huberbe06d262009-08-14 14:37:10 -0700261MPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
Andreas Hubere46b7be2009-07-14 16:56:47 -0700262 : mDataSource(source),
263 mHaveMetadata(false),
Andreas Huber1cb02bf2010-01-13 11:25:10 -0800264 mHasVideo(false),
Andreas Hubere46b7be2009-07-14 16:56:47 -0700265 mFirstTrack(NULL),
Andreas Huberc2c9dd32010-01-19 16:43:53 -0800266 mLastTrack(NULL),
267 mFileMetaData(new MetaData) {
Andreas Hubere46b7be2009-07-14 16:56:47 -0700268}
269
270MPEG4Extractor::~MPEG4Extractor() {
271 Track *track = mFirstTrack;
272 while (track) {
273 Track *next = track->next;
274
Andreas Hubere46b7be2009-07-14 16:56:47 -0700275 delete track;
276 track = next;
277 }
278 mFirstTrack = mLastTrack = NULL;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700279}
280
Andreas Huber1cb02bf2010-01-13 11:25:10 -0800281sp<MetaData> MPEG4Extractor::getMetaData() {
Andreas Huber1cb02bf2010-01-13 11:25:10 -0800282 status_t err;
283 if ((err = readMetaData()) != OK) {
Andreas Huberc2c9dd32010-01-19 16:43:53 -0800284 return new MetaData;
Andreas Huber1cb02bf2010-01-13 11:25:10 -0800285 }
286
Andreas Huberc2c9dd32010-01-19 16:43:53 -0800287 return mFileMetaData;
Andreas Huber1cb02bf2010-01-13 11:25:10 -0800288}
289
Andreas Huberbe06d262009-08-14 14:37:10 -0700290size_t MPEG4Extractor::countTracks() {
Andreas Hubere46b7be2009-07-14 16:56:47 -0700291 status_t err;
292 if ((err = readMetaData()) != OK) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700293 return 0;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700294 }
295
Andreas Huberbe06d262009-08-14 14:37:10 -0700296 size_t n = 0;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700297 Track *track = mFirstTrack;
298 while (track) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700299 ++n;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700300 track = track->next;
301 }
302
Andreas Huberbe06d262009-08-14 14:37:10 -0700303 return n;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700304}
305
Andreas Hubere981c332009-10-22 13:49:30 -0700306sp<MetaData> MPEG4Extractor::getTrackMetaData(
307 size_t index, uint32_t flags) {
Andreas Hubere46b7be2009-07-14 16:56:47 -0700308 status_t err;
309 if ((err = readMetaData()) != OK) {
310 return NULL;
311 }
312
313 Track *track = mFirstTrack;
314 while (index > 0) {
315 if (track == NULL) {
316 return NULL;
317 }
318
319 track = track->next;
320 --index;
321 }
322
Andreas Huber2a651172009-09-09 16:32:59 -0700323 if (track == NULL) {
324 return NULL;
325 }
326
Andreas Hubere981c332009-10-22 13:49:30 -0700327 if ((flags & kIncludeExtensiveMetaData)
328 && !track->includes_expensive_metadata) {
329 track->includes_expensive_metadata = true;
330
331 const char *mime;
332 CHECK(track->meta->findCString(kKeyMIMEType, &mime));
333 if (!strncasecmp("video/", mime, 6)) {
334 uint32_t sampleIndex;
335 uint32_t sampleTime;
336 if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK
Andreas Huber1faa92a2010-01-19 10:39:21 -0800337 && track->sampleTable->getMetaDataForSample(
338 sampleIndex, NULL /* offset */, NULL /* size */,
339 &sampleTime) == OK) {
Andreas Hubere981c332009-10-22 13:49:30 -0700340 track->meta->setInt64(
341 kKeyThumbnailTime,
342 ((int64_t)sampleTime * 1000000) / track->timescale);
343 }
344 }
345 }
346
Andreas Hubere46b7be2009-07-14 16:56:47 -0700347 return track->meta;
348}
349
350status_t MPEG4Extractor::readMetaData() {
351 if (mHaveMetadata) {
352 return OK;
353 }
354
355 off_t offset = 0;
356 status_t err;
357 while ((err = parseChunk(&offset, 0)) == OK) {
358 }
Andreas Huber1cb02bf2010-01-13 11:25:10 -0800359
Andreas Hubere46b7be2009-07-14 16:56:47 -0700360 if (mHaveMetadata) {
Andreas Huberc2c9dd32010-01-19 16:43:53 -0800361 if (mHasVideo) {
362 mFileMetaData->setCString(kKeyMIMEType, "video/mp4");
363 } else {
364 mFileMetaData->setCString(kKeyMIMEType, "audio/mp4");
365 }
366
Andreas Hubere46b7be2009-07-14 16:56:47 -0700367 return OK;
368 }
369
370 return err;
371}
372
373static void MakeFourCCString(uint32_t x, char *s) {
374 s[0] = x >> 24;
375 s[1] = (x >> 16) & 0xff;
376 s[2] = (x >> 8) & 0xff;
377 s[3] = x & 0xff;
378 s[4] = '\0';
379}
380
Andreas Huberc2c9dd32010-01-19 16:43:53 -0800381struct PathAdder {
382 PathAdder(Vector<uint32_t> *path, uint32_t chunkType)
383 : mPath(path) {
384 mPath->push(chunkType);
385 }
386
387 ~PathAdder() {
388 mPath->pop();
389 }
390
391private:
392 Vector<uint32_t> *mPath;
393
394 PathAdder(const PathAdder &);
395 PathAdder &operator=(const PathAdder &);
396};
397
398static bool underMetaDataPath(const Vector<uint32_t> &path) {
399 return path.size() >= 5
400 && path[0] == FOURCC('m', 'o', 'o', 'v')
401 && path[1] == FOURCC('u', 'd', 't', 'a')
402 && path[2] == FOURCC('m', 'e', 't', 'a')
403 && path[3] == FOURCC('i', 'l', 's', 't');
404}
405
406// Given a time in seconds since Jan 1 1904, produce a human-readable string.
407static void convertTimeToDate(int64_t time_1904, String8 *s) {
408 time_t time_1970 = time_1904 - (((66 * 365 + 17) * 24) * 3600);
409
410 char tmp[32];
411 strftime(tmp, sizeof(tmp), "%Y%m%dT%H%M%S.000Z", gmtime(&time_1970));
412
413 s->setTo(tmp);
414}
415
Andreas Hubere46b7be2009-07-14 16:56:47 -0700416status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
417 uint32_t hdr[2];
Andreas Huber9a12baf2009-10-23 10:22:30 -0700418 if (mDataSource->readAt(*offset, hdr, 8) < 8) {
Andreas Hubere46b7be2009-07-14 16:56:47 -0700419 return ERROR_IO;
420 }
421 uint64_t chunk_size = ntohl(hdr[0]);
422 uint32_t chunk_type = ntohl(hdr[1]);
423 off_t data_offset = *offset + 8;
424
425 if (chunk_size == 1) {
Andreas Huber9a12baf2009-10-23 10:22:30 -0700426 if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
Andreas Hubere46b7be2009-07-14 16:56:47 -0700427 return ERROR_IO;
428 }
429 chunk_size = ntoh64(chunk_size);
430 data_offset += 8;
Andreas Huber736c22d2010-06-24 12:16:25 -0700431
432 if (chunk_size < 16) {
433 // The smallest valid chunk is 16 bytes long in this case.
434 return ERROR_MALFORMED;
435 }
436 } else if (chunk_size < 8) {
437 // The smallest valid chunk is 8 bytes long.
438 return ERROR_MALFORMED;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700439 }
440
441 char chunk[5];
442 MakeFourCCString(chunk_type, chunk);
443
444#if 0
445 static const char kWhitespace[] = " ";
446 const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth];
447 printf("%sfound chunk '%s' of size %lld\n", indent, chunk, chunk_size);
448
449 char buffer[256];
Andreas Huberdfb8eee2010-02-25 15:59:24 -0800450 size_t n = chunk_size;
451 if (n > sizeof(buffer)) {
452 n = sizeof(buffer);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700453 }
Andreas Huberdfb8eee2010-02-25 15:59:24 -0800454 if (mDataSource->readAt(*offset, buffer, n)
455 < (ssize_t)n) {
456 return ERROR_IO;
457 }
458
459 hexdump(buffer, n);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700460#endif
461
Andreas Huberc2c9dd32010-01-19 16:43:53 -0800462 PathAdder autoAdder(&mPath, chunk_type);
463
Andreas Hubere46b7be2009-07-14 16:56:47 -0700464 off_t chunk_data_size = *offset + chunk_size - data_offset;
465
Andreas Huberc2c9dd32010-01-19 16:43:53 -0800466 if (chunk_type != FOURCC('c', 'p', 'r', 't')
467 && mPath.size() == 5 && underMetaDataPath(mPath)) {
468 off_t stop_offset = *offset + chunk_size;
469 *offset = data_offset;
470 while (*offset < stop_offset) {
471 status_t err = parseChunk(offset, depth + 1);
472 if (err != OK) {
473 return err;
474 }
475 }
Andreas Huber5ee0bce2010-02-23 10:12:02 -0800476
477 if (*offset != stop_offset) {
478 return ERROR_MALFORMED;
479 }
Andreas Huberc2c9dd32010-01-19 16:43:53 -0800480
481 return OK;
482 }
483
Andreas Hubere46b7be2009-07-14 16:56:47 -0700484 switch(chunk_type) {
485 case FOURCC('m', 'o', 'o', 'v'):
486 case FOURCC('t', 'r', 'a', 'k'):
487 case FOURCC('m', 'd', 'i', 'a'):
488 case FOURCC('m', 'i', 'n', 'f'):
489 case FOURCC('d', 'i', 'n', 'f'):
490 case FOURCC('s', 't', 'b', 'l'):
491 case FOURCC('m', 'v', 'e', 'x'):
492 case FOURCC('m', 'o', 'o', 'f'):
493 case FOURCC('t', 'r', 'a', 'f'):
494 case FOURCC('m', 'f', 'r', 'a'):
Andreas Huberc2c9dd32010-01-19 16:43:53 -0800495 case FOURCC('u', 'd', 't', 'a'):
496 case FOURCC('i', 'l', 's', 't'):
Andreas Hubere46b7be2009-07-14 16:56:47 -0700497 {
Andreas Huberaffa99c2010-01-28 14:27:37 -0800498 if (chunk_type == FOURCC('s', 't', 'b', 'l')) {
499 LOGV("sampleTable chunk is %d bytes long.", (size_t)chunk_size);
500
Andreas Huber6da2ae12010-10-15 08:38:49 -0700501 if (mDataSource->flags()
502 & (DataSource::kWantsPrefetching
503 | DataSource::kIsCachingDataSource)) {
Andreas Huberaffa99c2010-01-28 14:27:37 -0800504 sp<MPEG4DataSource> cachedSource =
505 new MPEG4DataSource(mDataSource);
506
507 if (cachedSource->setCachedRange(*offset, chunk_size) == OK) {
508 mDataSource = cachedSource;
509 }
510 }
Andreas Hubereb9128f2010-05-14 15:28:51 -0700511
512 mLastTrack->sampleTable = new SampleTable(mDataSource);
Andreas Huberaffa99c2010-01-28 14:27:37 -0800513 }
514
Andreas Huber4d60fc52010-03-12 16:15:53 -0800515 bool isTrack = false;
Andreas Huber5ee0bce2010-02-23 10:12:02 -0800516 if (chunk_type == FOURCC('t', 'r', 'a', 'k')) {
Andreas Huber4d60fc52010-03-12 16:15:53 -0800517 isTrack = true;
518
Andreas Huber5ee0bce2010-02-23 10:12:02 -0800519 Track *track = new Track;
520 track->next = NULL;
521 if (mLastTrack) {
522 mLastTrack->next = track;
523 } else {
524 mFirstTrack = track;
525 }
526 mLastTrack = track;
527
528 track->meta = new MetaData;
529 track->includes_expensive_metadata = false;
Andreas Huber4d60fc52010-03-12 16:15:53 -0800530 track->skipTrack = false;
Andreas Huber5ee0bce2010-02-23 10:12:02 -0800531 track->timescale = 0;
Andreas Huber5ee0bce2010-02-23 10:12:02 -0800532 track->meta->setCString(kKeyMIMEType, "application/octet-stream");
533 }
534
Andreas Hubere46b7be2009-07-14 16:56:47 -0700535 off_t stop_offset = *offset + chunk_size;
536 *offset = data_offset;
537 while (*offset < stop_offset) {
538 status_t err = parseChunk(offset, depth + 1);
539 if (err != OK) {
540 return err;
541 }
542 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700543
Andreas Huber5ee0bce2010-02-23 10:12:02 -0800544 if (*offset != stop_offset) {
545 return ERROR_MALFORMED;
546 }
547
Andreas Huber4d60fc52010-03-12 16:15:53 -0800548 if (isTrack) {
549 if (mLastTrack->skipTrack) {
550 Track *cur = mFirstTrack;
551
552 if (cur == mLastTrack) {
553 delete cur;
554 mFirstTrack = mLastTrack = NULL;
555 } else {
556 while (cur && cur->next != mLastTrack) {
557 cur = cur->next;
558 }
559 cur->next = NULL;
560 delete mLastTrack;
561 mLastTrack = cur;
562 }
563
564 return OK;
565 }
566
Andreas Huber5ee0bce2010-02-23 10:12:02 -0800567 status_t err = verifyTrack(mLastTrack);
568
569 if (err != OK) {
570 return err;
571 }
572 } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
Andreas Hubere46b7be2009-07-14 16:56:47 -0700573 mHaveMetadata = true;
574
575 return UNKNOWN_ERROR; // Return a dummy error.
576 }
577 break;
578 }
579
580 case FOURCC('t', 'k', 'h', 'd'):
581 {
Andreas Huber31dc9112010-11-04 11:50:27 -0700582 status_t err;
583 if ((err = parseTrackHeader(data_offset, chunk_data_size)) != OK) {
584 return err;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700585 }
586
Andreas Hubere46b7be2009-07-14 16:56:47 -0700587 *offset += chunk_size;
588 break;
589 }
590
591 case FOURCC('m', 'd', 'h', 'd'):
592 {
593 if (chunk_data_size < 4) {
594 return ERROR_MALFORMED;
595 }
596
597 uint8_t version;
Andreas Huber9a12baf2009-10-23 10:22:30 -0700598 if (mDataSource->readAt(
Andreas Hubere46b7be2009-07-14 16:56:47 -0700599 data_offset, &version, sizeof(version))
600 < (ssize_t)sizeof(version)) {
601 return ERROR_IO;
602 }
603
604 off_t timescale_offset;
605
606 if (version == 1) {
607 timescale_offset = data_offset + 4 + 16;
608 } else if (version == 0) {
609 timescale_offset = data_offset + 4 + 8;
610 } else {
611 return ERROR_IO;
612 }
613
614 uint32_t timescale;
Andreas Huber9a12baf2009-10-23 10:22:30 -0700615 if (mDataSource->readAt(
Andreas Hubere46b7be2009-07-14 16:56:47 -0700616 timescale_offset, &timescale, sizeof(timescale))
617 < (ssize_t)sizeof(timescale)) {
618 return ERROR_IO;
619 }
620
621 mLastTrack->timescale = ntohl(timescale);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700622
623 int64_t duration;
624 if (version == 1) {
Andreas Huber9a12baf2009-10-23 10:22:30 -0700625 if (mDataSource->readAt(
Andreas Hubere46b7be2009-07-14 16:56:47 -0700626 timescale_offset + 4, &duration, sizeof(duration))
627 < (ssize_t)sizeof(duration)) {
628 return ERROR_IO;
629 }
630 duration = ntoh64(duration);
631 } else {
632 int32_t duration32;
Andreas Huber9a12baf2009-10-23 10:22:30 -0700633 if (mDataSource->readAt(
Andreas Hubere46b7be2009-07-14 16:56:47 -0700634 timescale_offset + 4, &duration32, sizeof(duration32))
635 < (ssize_t)sizeof(duration32)) {
636 return ERROR_IO;
637 }
638 duration = ntohl(duration32);
639 }
Andreas Huberfa8de752009-10-08 10:07:49 -0700640 mLastTrack->meta->setInt64(
641 kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700642
643 *offset += chunk_size;
644 break;
645 }
646
Andreas Hubere46b7be2009-07-14 16:56:47 -0700647 case FOURCC('s', 't', 's', 'd'):
648 {
649 if (chunk_data_size < 8) {
650 return ERROR_MALFORMED;
651 }
652
653 uint8_t buffer[8];
Andreas Huber5ee0bce2010-02-23 10:12:02 -0800654 if (chunk_data_size < (off_t)sizeof(buffer)) {
655 return ERROR_MALFORMED;
656 }
657
Andreas Huber9a12baf2009-10-23 10:22:30 -0700658 if (mDataSource->readAt(
Andreas Hubere46b7be2009-07-14 16:56:47 -0700659 data_offset, buffer, 8) < 8) {
660 return ERROR_IO;
661 }
662
663 if (U32_AT(buffer) != 0) {
664 // Should be version 0, flags 0.
665 return ERROR_MALFORMED;
666 }
667
668 uint32_t entry_count = U32_AT(&buffer[4]);
669
670 if (entry_count > 1) {
671 // For now we only support a single type of media per track.
Andreas Huber4d60fc52010-03-12 16:15:53 -0800672
673 mLastTrack->skipTrack = true;
674 *offset += chunk_size;
675 break;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700676 }
677
678 off_t stop_offset = *offset + chunk_size;
679 *offset = data_offset + 8;
680 for (uint32_t i = 0; i < entry_count; ++i) {
681 status_t err = parseChunk(offset, depth + 1);
682 if (err != OK) {
683 return err;
684 }
685 }
Andreas Huber5ee0bce2010-02-23 10:12:02 -0800686
687 if (*offset != stop_offset) {
688 return ERROR_MALFORMED;
689 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700690 break;
691 }
692
693 case FOURCC('m', 'p', '4', 'a'):
694 case FOURCC('s', 'a', 'm', 'r'):
Andreas Huber2a651172009-09-09 16:32:59 -0700695 case FOURCC('s', 'a', 'w', 'b'):
Andreas Hubere46b7be2009-07-14 16:56:47 -0700696 {
Andreas Hubere46b7be2009-07-14 16:56:47 -0700697 uint8_t buffer[8 + 20];
698 if (chunk_data_size < (ssize_t)sizeof(buffer)) {
699 // Basic AudioSampleEntry size.
700 return ERROR_MALFORMED;
701 }
702
Andreas Huber9a12baf2009-10-23 10:22:30 -0700703 if (mDataSource->readAt(
Andreas Hubere46b7be2009-07-14 16:56:47 -0700704 data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
705 return ERROR_IO;
706 }
707
708 uint16_t data_ref_index = U16_AT(&buffer[6]);
709 uint16_t num_channels = U16_AT(&buffer[16]);
710
Andreas Hubere46b7be2009-07-14 16:56:47 -0700711 uint16_t sample_size = U16_AT(&buffer[18]);
712 uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
713
Andreas Huberd0332ad2010-04-12 16:05:57 -0700714 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB,
715 FourCC2MIME(chunk_type))) {
716 // AMR NB audio is always mono, 8kHz
717 num_channels = 1;
718 sample_rate = 8000;
719 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB,
720 FourCC2MIME(chunk_type))) {
721 // AMR WB audio is always mono, 16kHz
722 num_channels = 1;
723 sample_rate = 16000;
724 }
725
726#if 0
727 printf("*** coding='%s' %d channels, size %d, rate %d\n",
728 chunk, num_channels, sample_size, sample_rate);
729#endif
Andreas Hubere46b7be2009-07-14 16:56:47 -0700730
731 mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
732 mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
733 mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
734
735 off_t stop_offset = *offset + chunk_size;
736 *offset = data_offset + sizeof(buffer);
737 while (*offset < stop_offset) {
738 status_t err = parseChunk(offset, depth + 1);
739 if (err != OK) {
740 return err;
741 }
742 }
Andreas Huber5ee0bce2010-02-23 10:12:02 -0800743
744 if (*offset != stop_offset) {
745 return ERROR_MALFORMED;
746 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700747 break;
748 }
749
750 case FOURCC('m', 'p', '4', 'v'):
751 case FOURCC('s', '2', '6', '3'):
752 case FOURCC('a', 'v', 'c', '1'):
753 {
Andreas Huber1cb02bf2010-01-13 11:25:10 -0800754 mHasVideo = true;
755
Andreas Hubere46b7be2009-07-14 16:56:47 -0700756 uint8_t buffer[78];
757 if (chunk_data_size < (ssize_t)sizeof(buffer)) {
758 // Basic VideoSampleEntry size.
759 return ERROR_MALFORMED;
760 }
761
Andreas Huber9a12baf2009-10-23 10:22:30 -0700762 if (mDataSource->readAt(
Andreas Hubere46b7be2009-07-14 16:56:47 -0700763 data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
764 return ERROR_IO;
765 }
766
767 uint16_t data_ref_index = U16_AT(&buffer[6]);
768 uint16_t width = U16_AT(&buffer[6 + 18]);
769 uint16_t height = U16_AT(&buffer[6 + 20]);
770
Andreas Huber2ea14e22009-12-16 09:30:55 -0800771 // printf("*** coding='%s' width=%d height=%d\n",
772 // chunk, width, height);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700773
774 mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
775 mLastTrack->meta->setInt32(kKeyWidth, width);
776 mLastTrack->meta->setInt32(kKeyHeight, height);
777
778 off_t stop_offset = *offset + chunk_size;
779 *offset = data_offset + sizeof(buffer);
780 while (*offset < stop_offset) {
781 status_t err = parseChunk(offset, depth + 1);
782 if (err != OK) {
783 return err;
784 }
785 }
Andreas Huber5ee0bce2010-02-23 10:12:02 -0800786
787 if (*offset != stop_offset) {
788 return ERROR_MALFORMED;
789 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700790 break;
791 }
792
793 case FOURCC('s', 't', 'c', 'o'):
794 case FOURCC('c', 'o', '6', '4'):
795 {
796 status_t err =
797 mLastTrack->sampleTable->setChunkOffsetParams(
798 chunk_type, data_offset, chunk_data_size);
799
800 if (err != OK) {
801 return err;
802 }
803
804 *offset += chunk_size;
805 break;
806 }
807
808 case FOURCC('s', 't', 's', 'c'):
809 {
810 status_t err =
811 mLastTrack->sampleTable->setSampleToChunkParams(
812 data_offset, chunk_data_size);
813
814 if (err != OK) {
815 return err;
816 }
817
818 *offset += chunk_size;
819 break;
820 }
821
822 case FOURCC('s', 't', 's', 'z'):
823 case FOURCC('s', 't', 'z', '2'):
824 {
825 status_t err =
826 mLastTrack->sampleTable->setSampleSizeParams(
827 chunk_type, data_offset, chunk_data_size);
828
829 if (err != OK) {
830 return err;
831 }
832
Andreas Huber1bceff92009-11-23 14:03:32 -0800833 size_t max_size;
Andreas Huberd7f22252010-09-09 10:10:15 -0700834 err = mLastTrack->sampleTable->getMaxSampleSize(&max_size);
835
836 if (err != OK) {
837 return err;
838 }
Andreas Huber1bceff92009-11-23 14:03:32 -0800839
840 // Assume that a given buffer only contains at most 10 fragments,
841 // each fragment originally prefixed with a 2 byte length will
842 // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
843 // and thus will grow by 2 bytes per fragment.
844 mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
845
Andreas Hubere46b7be2009-07-14 16:56:47 -0700846 *offset += chunk_size;
847 break;
848 }
849
850 case FOURCC('s', 't', 't', 's'):
851 {
852 status_t err =
853 mLastTrack->sampleTable->setTimeToSampleParams(
854 data_offset, chunk_data_size);
855
856 if (err != OK) {
857 return err;
858 }
859
860 *offset += chunk_size;
861 break;
862 }
863
864 case FOURCC('s', 't', 's', 's'):
865 {
866 status_t err =
867 mLastTrack->sampleTable->setSyncSampleParams(
868 data_offset, chunk_data_size);
869
870 if (err != OK) {
871 return err;
872 }
873
874 *offset += chunk_size;
875 break;
876 }
877
878 case FOURCC('e', 's', 'd', 's'):
879 {
880 if (chunk_data_size < 4) {
881 return ERROR_MALFORMED;
882 }
883
884 uint8_t buffer[256];
885 if (chunk_data_size > (off_t)sizeof(buffer)) {
886 return ERROR_BUFFER_TOO_SMALL;
887 }
888
Andreas Huber9a12baf2009-10-23 10:22:30 -0700889 if (mDataSource->readAt(
Andreas Hubere46b7be2009-07-14 16:56:47 -0700890 data_offset, buffer, chunk_data_size) < chunk_data_size) {
891 return ERROR_IO;
892 }
893
894 if (U32_AT(buffer) != 0) {
895 // Should be version 0, flags 0.
896 return ERROR_MALFORMED;
897 }
898
899 mLastTrack->meta->setData(
900 kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
901
Andreas Huberd2315962010-01-29 14:46:59 -0800902 if (mPath.size() >= 2
903 && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) {
904 // Information from the ESDS must be relied on for proper
905 // setup of sample rate and channel count for MPEG4 Audio.
906 // The generic header appears to only contain generic
907 // information...
908
909 status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio(
910 &buffer[4], chunk_data_size - 4);
911
912 if (err != OK) {
913 return err;
914 }
915 }
916
Andreas Hubere46b7be2009-07-14 16:56:47 -0700917 *offset += chunk_size;
918 break;
919 }
920
921 case FOURCC('a', 'v', 'c', 'C'):
922 {
923 char buffer[256];
924 if (chunk_data_size > (off_t)sizeof(buffer)) {
925 return ERROR_BUFFER_TOO_SMALL;
926 }
927
Andreas Huber9a12baf2009-10-23 10:22:30 -0700928 if (mDataSource->readAt(
Andreas Hubere46b7be2009-07-14 16:56:47 -0700929 data_offset, buffer, chunk_data_size) < chunk_data_size) {
930 return ERROR_IO;
931 }
932
933 mLastTrack->meta->setData(
934 kKeyAVCC, kTypeAVCC, buffer, chunk_data_size);
935
936 *offset += chunk_size;
937 break;
938 }
939
Andreas Huberc2c9dd32010-01-19 16:43:53 -0800940 case FOURCC('m', 'e', 't', 'a'):
941 {
942 uint8_t buffer[4];
Andreas Huber5ee0bce2010-02-23 10:12:02 -0800943 if (chunk_data_size < (off_t)sizeof(buffer)) {
944 return ERROR_MALFORMED;
945 }
946
Andreas Huberc2c9dd32010-01-19 16:43:53 -0800947 if (mDataSource->readAt(
948 data_offset, buffer, 4) < 4) {
949 return ERROR_IO;
950 }
951
952 if (U32_AT(buffer) != 0) {
953 // Should be version 0, flags 0.
Andreas Huberdfb8eee2010-02-25 15:59:24 -0800954
955 // If it's not, let's assume this is one of those
956 // apparently malformed chunks that don't have flags
957 // and completely different semantics than what's
958 // in the MPEG4 specs and skip it.
959 *offset += chunk_size;
960 return OK;
Andreas Huberc2c9dd32010-01-19 16:43:53 -0800961 }
962
963 off_t stop_offset = *offset + chunk_size;
964 *offset = data_offset + sizeof(buffer);
965 while (*offset < stop_offset) {
966 status_t err = parseChunk(offset, depth + 1);
967 if (err != OK) {
968 return err;
969 }
970 }
Andreas Huber5ee0bce2010-02-23 10:12:02 -0800971
972 if (*offset != stop_offset) {
973 return ERROR_MALFORMED;
974 }
Andreas Huberc2c9dd32010-01-19 16:43:53 -0800975 break;
976 }
977
978 case FOURCC('d', 'a', 't', 'a'):
979 {
980 if (mPath.size() == 6 && underMetaDataPath(mPath)) {
981 status_t err = parseMetaData(data_offset, chunk_data_size);
982
983 if (err != OK) {
984 return err;
985 }
986 }
987
988 *offset += chunk_size;
989 break;
990 }
991
992 case FOURCC('m', 'v', 'h', 'd'):
993 {
994 if (chunk_data_size < 12) {
995 return ERROR_MALFORMED;
996 }
997
998 uint8_t header[12];
999 if (mDataSource->readAt(
1000 data_offset, header, sizeof(header))
1001 < (ssize_t)sizeof(header)) {
1002 return ERROR_IO;
1003 }
1004
1005 int64_t creationTime;
1006 if (header[0] == 1) {
1007 creationTime = U64_AT(&header[4]);
Andreas Huber5ee0bce2010-02-23 10:12:02 -08001008 } else if (header[0] != 0) {
1009 return ERROR_MALFORMED;
Andreas Huberc2c9dd32010-01-19 16:43:53 -08001010 } else {
Andreas Huberc2c9dd32010-01-19 16:43:53 -08001011 creationTime = U32_AT(&header[4]);
1012 }
1013
1014 String8 s;
1015 convertTimeToDate(creationTime, &s);
1016
1017 mFileMetaData->setCString(kKeyDate, s.string());
1018
1019 *offset += chunk_size;
1020 break;
1021 }
1022
Andreas Hubere46b7be2009-07-14 16:56:47 -07001023 default:
1024 {
1025 *offset += chunk_size;
1026 break;
1027 }
1028 }
1029
1030 return OK;
1031}
1032
Andreas Huber31dc9112010-11-04 11:50:27 -07001033status_t MPEG4Extractor::parseTrackHeader(
1034 off_t data_offset, off_t data_size) {
1035 if (data_size < 4) {
1036 return ERROR_MALFORMED;
1037 }
1038
1039 uint8_t version;
1040 if (mDataSource->readAt(data_offset, &version, 1) < 1) {
1041 return ERROR_IO;
1042 }
1043
1044 size_t dynSize = (version == 1) ? 36 : 24;
1045
1046 uint8_t buffer[36 + 60];
1047
1048 if (data_size != (off_t)dynSize + 60) {
1049 return ERROR_MALFORMED;
1050 }
1051
1052 if (mDataSource->readAt(
1053 data_offset, buffer, data_size) < (ssize_t)data_size) {
1054 return ERROR_IO;
1055 }
1056
1057 uint64_t ctime, mtime, duration;
1058 int32_t id;
1059
1060 if (version == 1) {
1061 ctime = U64_AT(&buffer[4]);
1062 mtime = U64_AT(&buffer[12]);
1063 id = U32_AT(&buffer[20]);
1064 duration = U64_AT(&buffer[28]);
1065 } else if (version == 0) {
1066 ctime = U32_AT(&buffer[4]);
1067 mtime = U32_AT(&buffer[8]);
1068 id = U32_AT(&buffer[12]);
1069 duration = U32_AT(&buffer[20]);
1070 }
1071
1072 size_t matrixOffset = dynSize + 16;
1073 int32_t a00 = U32_AT(&buffer[matrixOffset]);
1074 int32_t a01 = U32_AT(&buffer[matrixOffset + 4]);
1075 int32_t dx = U32_AT(&buffer[matrixOffset + 8]);
1076 int32_t a10 = U32_AT(&buffer[matrixOffset + 12]);
1077 int32_t a11 = U32_AT(&buffer[matrixOffset + 16]);
1078 int32_t dy = U32_AT(&buffer[matrixOffset + 20]);
1079
1080#if 0
1081 LOGI("x' = %.2f * x + %.2f * y + %.2f",
1082 a00 / 65536.0f, a01 / 65536.0f, dx / 65536.0f);
1083 LOGI("y' = %.2f * x + %.2f * y + %.2f",
1084 a10 / 65536.0f, a11 / 65536.0f, dy / 65536.0f);
1085#endif
1086
1087 uint32_t rotationDegrees;
1088
1089 static const int32_t kFixedOne = 0x10000;
1090 if (a00 == kFixedOne && a01 == 0 && a10 == 0 && a11 == kFixedOne) {
1091 // Identity, no rotation
1092 rotationDegrees = 0;
1093 } else if (a00 == 0 && a01 == kFixedOne && a10 == -kFixedOne && a11 == 0) {
1094 rotationDegrees = 90;
1095 } else if (a00 == 0 && a01 == -kFixedOne && a10 == kFixedOne && a11 == 0) {
1096 rotationDegrees = 270;
1097 } else if (a00 == -kFixedOne && a01 == 0 && a10 == 0 && a11 == -kFixedOne) {
1098 rotationDegrees = 180;
1099 } else {
1100 LOGW("We only support 0,90,180,270 degree rotation matrices");
1101 rotationDegrees = 0;
1102 }
1103
1104 if (rotationDegrees != 0) {
1105 mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees);
1106 }
1107
1108#if 0
1109 uint32_t width = U32_AT(&buffer[dynSize + 52]);
1110 uint32_t height = U32_AT(&buffer[dynSize + 56]);
1111#endif
1112
1113 return OK;
1114}
1115
Andreas Huberc2c9dd32010-01-19 16:43:53 -08001116status_t MPEG4Extractor::parseMetaData(off_t offset, size_t size) {
1117 if (size < 4) {
1118 return ERROR_MALFORMED;
1119 }
1120
1121 uint8_t *buffer = new uint8_t[size + 1];
1122 if (mDataSource->readAt(
1123 offset, buffer, size) != (ssize_t)size) {
1124 delete[] buffer;
1125 buffer = NULL;
1126
1127 return ERROR_IO;
1128 }
1129
1130 uint32_t flags = U32_AT(buffer);
1131
1132 uint32_t metadataKey = 0;
1133 switch (mPath[4]) {
1134 case FOURCC(0xa9, 'a', 'l', 'b'):
1135 {
1136 metadataKey = kKeyAlbum;
1137 break;
1138 }
1139 case FOURCC(0xa9, 'A', 'R', 'T'):
1140 {
1141 metadataKey = kKeyArtist;
1142 break;
1143 }
Marco Nelissenc5d5ee32010-02-11 13:31:44 -08001144 case FOURCC('a', 'A', 'R', 'T'):
1145 {
1146 metadataKey = kKeyAlbumArtist;
1147 break;
1148 }
Andreas Huberc2c9dd32010-01-19 16:43:53 -08001149 case FOURCC(0xa9, 'd', 'a', 'y'):
1150 {
1151 metadataKey = kKeyYear;
1152 break;
1153 }
1154 case FOURCC(0xa9, 'n', 'a', 'm'):
1155 {
1156 metadataKey = kKeyTitle;
1157 break;
1158 }
1159 case FOURCC(0xa9, 'w', 'r', 't'):
1160 {
1161 metadataKey = kKeyWriter;
1162 break;
1163 }
1164 case FOURCC('c', 'o', 'v', 'r'):
1165 {
1166 metadataKey = kKeyAlbumArt;
1167 break;
1168 }
1169 case FOURCC('g', 'n', 'r', 'e'):
1170 {
1171 metadataKey = kKeyGenre;
1172 break;
1173 }
Marco Nelissenfe3b8e92010-02-09 14:02:16 -08001174 case FOURCC(0xa9, 'g', 'e', 'n'):
1175 {
1176 metadataKey = kKeyGenre;
1177 break;
1178 }
Marco Nelissenba77a3f2011-01-06 11:12:17 -08001179 case FOURCC('c', 'p', 'i', 'l'):
1180 {
1181 if (size == 9 && flags == 21) {
1182 char tmp[16];
1183 sprintf(tmp, "%d",
1184 (int)buffer[size - 1]);
1185
1186 mFileMetaData->setCString(kKeyCompilation, tmp);
1187 }
1188 break;
1189 }
Andreas Huberc2c9dd32010-01-19 16:43:53 -08001190 case FOURCC('t', 'r', 'k', 'n'):
1191 {
1192 if (size == 16 && flags == 0) {
1193 char tmp[16];
1194 sprintf(tmp, "%d/%d",
1195 (int)buffer[size - 5], (int)buffer[size - 3]);
1196
Andreas Huberc2c9dd32010-01-19 16:43:53 -08001197 mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
1198 }
1199 break;
1200 }
Marco Nelissenfe3b8e92010-02-09 14:02:16 -08001201 case FOURCC('d', 'i', 's', 'k'):
1202 {
1203 if (size == 14 && flags == 0) {
1204 char tmp[16];
1205 sprintf(tmp, "%d/%d",
1206 (int)buffer[size - 3], (int)buffer[size - 1]);
1207
1208 mFileMetaData->setCString(kKeyDiscNumber, tmp);
1209 }
1210 break;
1211 }
1212
Andreas Huberc2c9dd32010-01-19 16:43:53 -08001213 default:
1214 break;
1215 }
1216
1217 if (size >= 8 && metadataKey) {
1218 if (metadataKey == kKeyAlbumArt) {
1219 mFileMetaData->setData(
1220 kKeyAlbumArt, MetaData::TYPE_NONE,
1221 buffer + 8, size - 8);
1222 } else if (metadataKey == kKeyGenre) {
1223 if (flags == 0) {
Marco Nelissenfe3b8e92010-02-09 14:02:16 -08001224 // uint8_t genre code, iTunes genre codes are
1225 // the standard id3 codes, except they start
1226 // at 1 instead of 0 (e.g. Pop is 14, not 13)
1227 // We use standard id3 numbering, so subtract 1.
1228 int genrecode = (int)buffer[size - 1];
1229 genrecode--;
1230 if (genrecode < 0) {
1231 genrecode = 255; // reserved for 'unknown genre'
1232 }
Andreas Huberc2c9dd32010-01-19 16:43:53 -08001233 char genre[10];
Marco Nelissenfe3b8e92010-02-09 14:02:16 -08001234 sprintf(genre, "%d", genrecode);
Andreas Huberc2c9dd32010-01-19 16:43:53 -08001235
1236 mFileMetaData->setCString(metadataKey, genre);
Marco Nelissenfe3b8e92010-02-09 14:02:16 -08001237 } else if (flags == 1) {
1238 // custom genre string
1239 buffer[size] = '\0';
1240
1241 mFileMetaData->setCString(
1242 metadataKey, (const char *)buffer + 8);
Andreas Huberc2c9dd32010-01-19 16:43:53 -08001243 }
1244 } else {
1245 buffer[size] = '\0';
1246
1247 mFileMetaData->setCString(
1248 metadataKey, (const char *)buffer + 8);
1249 }
1250 }
1251
1252 delete[] buffer;
1253 buffer = NULL;
1254
1255 return OK;
1256}
1257
Andreas Huberbe06d262009-08-14 14:37:10 -07001258sp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
Andreas Hubere46b7be2009-07-14 16:56:47 -07001259 status_t err;
1260 if ((err = readMetaData()) != OK) {
Andreas Huberbe06d262009-08-14 14:37:10 -07001261 return NULL;
Andreas Hubere46b7be2009-07-14 16:56:47 -07001262 }
1263
1264 Track *track = mFirstTrack;
1265 while (index > 0) {
1266 if (track == NULL) {
Andreas Huberbe06d262009-08-14 14:37:10 -07001267 return NULL;
Andreas Hubere46b7be2009-07-14 16:56:47 -07001268 }
1269
1270 track = track->next;
1271 --index;
1272 }
1273
Andreas Huber2a651172009-09-09 16:32:59 -07001274 if (track == NULL) {
1275 return NULL;
1276 }
1277
Andreas Huberbe06d262009-08-14 14:37:10 -07001278 return new MPEG4Source(
Andreas Huberfa8de752009-10-08 10:07:49 -07001279 track->meta, mDataSource, track->timescale, track->sampleTable);
Andreas Hubere46b7be2009-07-14 16:56:47 -07001280}
1281
Andreas Huber5ee0bce2010-02-23 10:12:02 -08001282// static
1283status_t MPEG4Extractor::verifyTrack(Track *track) {
1284 const char *mime;
1285 CHECK(track->meta->findCString(kKeyMIMEType, &mime));
1286
1287 uint32_t type;
1288 const void *data;
1289 size_t size;
1290 if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
1291 if (!track->meta->findData(kKeyAVCC, &type, &data, &size)
1292 || type != kTypeAVCC) {
1293 return ERROR_MALFORMED;
1294 }
1295 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
1296 || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
1297 if (!track->meta->findData(kKeyESDS, &type, &data, &size)
1298 || type != kTypeESDS) {
1299 return ERROR_MALFORMED;
1300 }
1301 }
1302
1303 return OK;
1304}
1305
Andreas Huberd2315962010-01-29 14:46:59 -08001306status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(
1307 const void *esds_data, size_t esds_size) {
1308 ESDS esds(esds_data, esds_size);
Andreas Huberd0332ad2010-04-12 16:05:57 -07001309
1310 uint8_t objectTypeIndication;
1311 if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) {
1312 return ERROR_MALFORMED;
1313 }
1314
1315 if (objectTypeIndication == 0xe1) {
1316 // This isn't MPEG4 audio at all, it's QCELP 14k...
1317 mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
1318 return OK;
1319 }
1320
Andreas Huberd2315962010-01-29 14:46:59 -08001321 const uint8_t *csd;
1322 size_t csd_size;
1323 if (esds.getCodecSpecificInfo(
1324 (const void **)&csd, &csd_size) != OK) {
1325 return ERROR_MALFORMED;
1326 }
1327
1328#if 0
1329 printf("ESD of size %d\n", csd_size);
1330 hexdump(csd, csd_size);
1331#endif
1332
Andreas Huber08c94b22010-08-18 09:58:30 -07001333 if (csd_size == 0) {
1334 // There's no further information, i.e. no codec specific data
1335 // Let's assume that the information provided in the mpeg4 headers
1336 // is accurate and hope for the best.
1337
1338 return OK;
1339 }
1340
Andreas Huberd2315962010-01-29 14:46:59 -08001341 if (csd_size < 2) {
1342 return ERROR_MALFORMED;
1343 }
1344
1345 uint32_t objectType = csd[0] >> 3;
1346
1347 if (objectType == 31) {
1348 return ERROR_UNSUPPORTED;
1349 }
1350
1351 uint32_t freqIndex = (csd[0] & 7) << 1 | (csd[1] >> 7);
1352 int32_t sampleRate = 0;
1353 int32_t numChannels = 0;
1354 if (freqIndex == 15) {
1355 if (csd_size < 5) {
1356 return ERROR_MALFORMED;
1357 }
1358
1359 sampleRate = (csd[1] & 0x7f) << 17
1360 | csd[2] << 9
1361 | csd[3] << 1
1362 | (csd[4] >> 7);
1363
1364 numChannels = (csd[4] >> 3) & 15;
1365 } else {
Andreas Hubercc14a832010-07-20 09:21:17 -07001366 static uint32_t kSamplingRate[] = {
1367 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
1368 16000, 12000, 11025, 8000, 7350
1369 };
Andreas Huberd2315962010-01-29 14:46:59 -08001370
1371 if (freqIndex == 13 || freqIndex == 14) {
1372 return ERROR_MALFORMED;
1373 }
1374
1375 sampleRate = kSamplingRate[freqIndex];
1376 numChannels = (csd[1] >> 3) & 15;
1377 }
1378
1379 if (numChannels == 0) {
1380 return ERROR_UNSUPPORTED;
1381 }
1382
1383 int32_t prevSampleRate;
1384 CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));
1385
1386 if (prevSampleRate != sampleRate) {
Andreas Huber4a9375e2010-02-09 11:54:33 -08001387 LOGV("mpeg4 audio sample rate different from previous setting. "
Andreas Huberd2315962010-01-29 14:46:59 -08001388 "was: %d, now: %d", prevSampleRate, sampleRate);
1389 }
1390
1391 mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
1392
1393 int32_t prevChannelCount;
1394 CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount));
1395
1396 if (prevChannelCount != numChannels) {
Andreas Huber4a9375e2010-02-09 11:54:33 -08001397 LOGV("mpeg4 audio channel count different from previous setting. "
Andreas Huberd2315962010-01-29 14:46:59 -08001398 "was: %d, now: %d", prevChannelCount, numChannels);
1399 }
1400
1401 mLastTrack->meta->setInt32(kKeyChannelCount, numChannels);
1402
1403 return OK;
1404}
1405
Andreas Hubere46b7be2009-07-14 16:56:47 -07001406////////////////////////////////////////////////////////////////////////////////
1407
1408MPEG4Source::MPEG4Source(
1409 const sp<MetaData> &format,
Andreas Huberbe06d262009-08-14 14:37:10 -07001410 const sp<DataSource> &dataSource,
Andreas Huberfa8de752009-10-08 10:07:49 -07001411 int32_t timeScale,
Andreas Huberbe06d262009-08-14 14:37:10 -07001412 const sp<SampleTable> &sampleTable)
Andreas Hubere46b7be2009-07-14 16:56:47 -07001413 : mFormat(format),
1414 mDataSource(dataSource),
Andreas Huberfa8de752009-10-08 10:07:49 -07001415 mTimescale(timeScale),
Andreas Hubere46b7be2009-07-14 16:56:47 -07001416 mSampleTable(sampleTable),
1417 mCurrentSampleIndex(0),
1418 mIsAVC(false),
Andreas Huberdb5d6622010-01-12 16:30:44 -08001419 mNALLengthSize(0),
Andreas Hubere46b7be2009-07-14 16:56:47 -07001420 mStarted(false),
1421 mGroup(NULL),
1422 mBuffer(NULL),
Andreas Huber4f5e6022009-08-19 09:29:34 -07001423 mWantsNALFragments(false),
Andreas Huber8a432772009-07-28 10:03:13 -07001424 mSrcBuffer(NULL) {
Andreas Hubere46b7be2009-07-14 16:56:47 -07001425 const char *mime;
1426 bool success = mFormat->findCString(kKeyMIMEType, &mime);
Andreas Huber4f5e6022009-08-19 09:29:34 -07001427 CHECK(success);
Andreas Hubere46b7be2009-07-14 16:56:47 -07001428
Andreas Hubere6c40962009-09-10 14:13:30 -07001429 mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
Andreas Huberdb5d6622010-01-12 16:30:44 -08001430
1431 if (mIsAVC) {
1432 uint32_t type;
1433 const void *data;
1434 size_t size;
1435 CHECK(format->findData(kKeyAVCC, &type, &data, &size));
1436
1437 const uint8_t *ptr = (const uint8_t *)data;
1438
1439 CHECK(size >= 7);
Andreas Huber31dc9112010-11-04 11:50:27 -07001440 CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1
Andreas Huberdb5d6622010-01-12 16:30:44 -08001441
1442 // The number of bytes used to encode the length of a NAL unit.
1443 mNALLengthSize = 1 + (ptr[4] & 3);
1444 }
Andreas Hubere46b7be2009-07-14 16:56:47 -07001445}
1446
1447MPEG4Source::~MPEG4Source() {
1448 if (mStarted) {
1449 stop();
1450 }
1451}
1452
1453status_t MPEG4Source::start(MetaData *params) {
Andreas Huberba7ec912010-02-12 10:42:02 -08001454 Mutex::Autolock autoLock(mLock);
1455
Andreas Huber4f5e6022009-08-19 09:29:34 -07001456 CHECK(!mStarted);
Andreas Hubere46b7be2009-07-14 16:56:47 -07001457
1458 int32_t val;
Andreas Huber4f5e6022009-08-19 09:29:34 -07001459 if (params && params->findInt32(kKeyWantsNALFragments, &val)
Andreas Hubere46b7be2009-07-14 16:56:47 -07001460 && val != 0) {
Andreas Huber4f5e6022009-08-19 09:29:34 -07001461 mWantsNALFragments = true;
Andreas Hubere46b7be2009-07-14 16:56:47 -07001462 } else {
Andreas Huber4f5e6022009-08-19 09:29:34 -07001463 mWantsNALFragments = false;
Andreas Hubere46b7be2009-07-14 16:56:47 -07001464 }
1465
1466 mGroup = new MediaBufferGroup;
1467
Andreas Huber1bceff92009-11-23 14:03:32 -08001468 int32_t max_size;
1469 CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size));
Andreas Hubere46b7be2009-07-14 16:56:47 -07001470
Andreas Huber1bceff92009-11-23 14:03:32 -08001471 mGroup->add_buffer(new MediaBuffer(max_size));
Andreas Huber8a432772009-07-28 10:03:13 -07001472
1473 mSrcBuffer = new uint8_t[max_size];
Andreas Hubere46b7be2009-07-14 16:56:47 -07001474
1475 mStarted = true;
1476
1477 return OK;
1478}
1479
1480status_t MPEG4Source::stop() {
Andreas Huberba7ec912010-02-12 10:42:02 -08001481 Mutex::Autolock autoLock(mLock);
1482
Andreas Huber4f5e6022009-08-19 09:29:34 -07001483 CHECK(mStarted);
Andreas Hubere46b7be2009-07-14 16:56:47 -07001484
1485 if (mBuffer != NULL) {
1486 mBuffer->release();
1487 mBuffer = NULL;
1488 }
1489
Andreas Huber8a432772009-07-28 10:03:13 -07001490 delete[] mSrcBuffer;
1491 mSrcBuffer = NULL;
1492
Andreas Hubere46b7be2009-07-14 16:56:47 -07001493 delete mGroup;
1494 mGroup = NULL;
1495
1496 mStarted = false;
1497 mCurrentSampleIndex = 0;
1498
1499 return OK;
1500}
1501
1502sp<MetaData> MPEG4Source::getFormat() {
Andreas Huberba7ec912010-02-12 10:42:02 -08001503 Mutex::Autolock autoLock(mLock);
1504
Andreas Hubere46b7be2009-07-14 16:56:47 -07001505 return mFormat;
1506}
1507
Andreas Huberdb5d6622010-01-12 16:30:44 -08001508size_t MPEG4Source::parseNALSize(const uint8_t *data) const {
1509 switch (mNALLengthSize) {
1510 case 1:
1511 return *data;
1512 case 2:
1513 return U16_AT(data);
1514 case 3:
1515 return ((size_t)data[0] << 16) | U16_AT(&data[1]);
1516 case 4:
1517 return U32_AT(data);
1518 }
1519
1520 // This cannot happen, mNALLengthSize springs to life by adding 1 to
1521 // a 2-bit integer.
1522 CHECK(!"Should not be here.");
1523
1524 return 0;
1525}
1526
Andreas Hubere46b7be2009-07-14 16:56:47 -07001527status_t MPEG4Source::read(
1528 MediaBuffer **out, const ReadOptions *options) {
Andreas Huberba7ec912010-02-12 10:42:02 -08001529 Mutex::Autolock autoLock(mLock);
1530
Andreas Huber4f5e6022009-08-19 09:29:34 -07001531 CHECK(mStarted);
Andreas Hubere46b7be2009-07-14 16:56:47 -07001532
1533 *out = NULL;
1534
Andreas Huber6624c9f2010-07-20 15:04:28 -07001535 int64_t targetSampleTimeUs = -1;
1536
Andreas Hubere46b7be2009-07-14 16:56:47 -07001537 int64_t seekTimeUs;
Andreas Huber6624c9f2010-07-20 15:04:28 -07001538 ReadOptions::SeekMode mode;
1539 if (options && options->getSeekTo(&seekTimeUs, &mode)) {
1540 uint32_t findFlags = 0;
1541 switch (mode) {
1542 case ReadOptions::SEEK_PREVIOUS_SYNC:
1543 findFlags = SampleTable::kFlagBefore;
1544 break;
1545 case ReadOptions::SEEK_NEXT_SYNC:
1546 findFlags = SampleTable::kFlagAfter;
1547 break;
1548 case ReadOptions::SEEK_CLOSEST_SYNC:
1549 case ReadOptions::SEEK_CLOSEST:
1550 findFlags = SampleTable::kFlagClosest;
1551 break;
1552 default:
1553 CHECK(!"Should not be here.");
1554 break;
1555 }
1556
Andreas Hubere46b7be2009-07-14 16:56:47 -07001557 uint32_t sampleIndex;
Andreas Huber6624c9f2010-07-20 15:04:28 -07001558 status_t err = mSampleTable->findSampleAtTime(
Andreas Hubere46b7be2009-07-14 16:56:47 -07001559 seekTimeUs * mTimescale / 1000000,
Andreas Huber6624c9f2010-07-20 15:04:28 -07001560 &sampleIndex, findFlags);
1561
1562 if (mode == ReadOptions::SEEK_CLOSEST) {
1563 // We found the closest sample already, now we want the sync
1564 // sample preceding it (or the sample itself of course), even
1565 // if the subsequent sync sample is closer.
1566 findFlags = SampleTable::kFlagBefore;
1567 }
1568
1569 uint32_t syncSampleIndex;
1570 if (err == OK) {
1571 err = mSampleTable->findSyncSampleNear(
1572 sampleIndex, &syncSampleIndex, findFlags);
1573 }
Andreas Hubere46b7be2009-07-14 16:56:47 -07001574
1575 if (err != OK) {
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001576 if (err == ERROR_OUT_OF_RANGE) {
1577 // An attempt to seek past the end of the stream would
1578 // normally cause this ERROR_OUT_OF_RANGE error. Propagating
1579 // this all the way to the MediaPlayer would cause abnormal
1580 // termination. Legacy behaviour appears to be to behave as if
1581 // we had seeked to the end of stream, ending normally.
1582 err = ERROR_END_OF_STREAM;
1583 }
Andreas Hubere46b7be2009-07-14 16:56:47 -07001584 return err;
1585 }
1586
Andreas Huber6624c9f2010-07-20 15:04:28 -07001587 uint32_t sampleTime;
Andreas Huber31dc9112010-11-04 11:50:27 -07001588 CHECK_EQ((status_t)OK, mSampleTable->getMetaDataForSample(
Andreas Huber6624c9f2010-07-20 15:04:28 -07001589 sampleIndex, NULL, NULL, &sampleTime));
1590
1591 if (mode == ReadOptions::SEEK_CLOSEST) {
1592 targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
1593 }
1594
1595#if 0
1596 uint32_t syncSampleTime;
1597 CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
1598 syncSampleIndex, NULL, NULL, &syncSampleTime));
1599
1600 LOGI("seek to time %lld us => sample at time %lld us, "
1601 "sync sample at time %lld us",
1602 seekTimeUs,
1603 sampleTime * 1000000ll / mTimescale,
1604 syncSampleTime * 1000000ll / mTimescale);
1605#endif
1606
1607 mCurrentSampleIndex = syncSampleIndex;
Andreas Hubere46b7be2009-07-14 16:56:47 -07001608 if (mBuffer != NULL) {
1609 mBuffer->release();
1610 mBuffer = NULL;
1611 }
1612
1613 // fall through
1614 }
1615
Andreas Huber8a432772009-07-28 10:03:13 -07001616 off_t offset;
1617 size_t size;
Andreas Huber8a432772009-07-28 10:03:13 -07001618 uint32_t dts;
Andreas Huberad98d382010-08-06 14:13:10 -07001619 bool isSyncSample;
Andreas Huber4f5e6022009-08-19 09:29:34 -07001620 bool newBuffer = false;
1621 if (mBuffer == NULL) {
1622 newBuffer = true;
Andreas Hubere46b7be2009-07-14 16:56:47 -07001623
Andreas Huber1faa92a2010-01-19 10:39:21 -08001624 status_t err =
1625 mSampleTable->getMetaDataForSample(
Andreas Huberad98d382010-08-06 14:13:10 -07001626 mCurrentSampleIndex, &offset, &size, &dts, &isSyncSample);
Andreas Huber4f5e6022009-08-19 09:29:34 -07001627
1628 if (err != OK) {
1629 return err;
1630 }
1631
1632 err = mGroup->acquire_buffer(&mBuffer);
Andreas Huber1faa92a2010-01-19 10:39:21 -08001633
Andreas Huber4f5e6022009-08-19 09:29:34 -07001634 if (err != OK) {
Andreas Huber31dc9112010-11-04 11:50:27 -07001635 CHECK(mBuffer == NULL);
Andreas Huber4f5e6022009-08-19 09:29:34 -07001636 return err;
1637 }
Andreas Huber8a432772009-07-28 10:03:13 -07001638 }
Andreas Hubere46b7be2009-07-14 16:56:47 -07001639
Andreas Huber4f5e6022009-08-19 09:29:34 -07001640 if (!mIsAVC || mWantsNALFragments) {
1641 if (newBuffer) {
1642 ssize_t num_bytes_read =
Andreas Huber9a12baf2009-10-23 10:22:30 -07001643 mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
Andreas Hubere46b7be2009-07-14 16:56:47 -07001644
Andreas Huber4f5e6022009-08-19 09:29:34 -07001645 if (num_bytes_read < (ssize_t)size) {
1646 mBuffer->release();
1647 mBuffer = NULL;
1648
1649 return ERROR_IO;
1650 }
1651
Andreas Huberba7ec912010-02-12 10:42:02 -08001652 CHECK(mBuffer != NULL);
Andreas Huber4f5e6022009-08-19 09:29:34 -07001653 mBuffer->set_range(0, size);
1654 mBuffer->meta_data()->clear();
Andreas Huberfa8de752009-10-08 10:07:49 -07001655 mBuffer->meta_data()->setInt64(
1656 kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
Andreas Huber6624c9f2010-07-20 15:04:28 -07001657
1658 if (targetSampleTimeUs >= 0) {
1659 mBuffer->meta_data()->setInt64(
1660 kKeyTargetTime, targetSampleTimeUs);
1661 }
1662
Andreas Huberad98d382010-08-06 14:13:10 -07001663 if (isSyncSample) {
1664 mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
1665 }
1666
Andreas Huber4f5e6022009-08-19 09:29:34 -07001667 ++mCurrentSampleIndex;
1668 }
1669
1670 if (!mIsAVC) {
1671 *out = mBuffer;
1672 mBuffer = NULL;
1673
1674 return OK;
1675 }
1676
1677 // Each NAL unit is split up into its constituent fragments and
1678 // each one of them returned in its own buffer.
1679
Andreas Huberdb5d6622010-01-12 16:30:44 -08001680 CHECK(mBuffer->range_length() >= mNALLengthSize);
Andreas Huber4f5e6022009-08-19 09:29:34 -07001681
1682 const uint8_t *src =
1683 (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
1684
Andreas Huberdb5d6622010-01-12 16:30:44 -08001685 size_t nal_size = parseNALSize(src);
Andreas Huber909255a2010-01-14 14:13:15 -08001686 if (mBuffer->range_length() < mNALLengthSize + nal_size) {
1687 LOGE("incomplete NAL unit.");
1688
1689 mBuffer->release();
1690 mBuffer = NULL;
1691
1692 return ERROR_MALFORMED;
1693 }
Andreas Huber4f5e6022009-08-19 09:29:34 -07001694
1695 MediaBuffer *clone = mBuffer->clone();
Andreas Huberba7ec912010-02-12 10:42:02 -08001696 CHECK(clone != NULL);
Andreas Huberdb5d6622010-01-12 16:30:44 -08001697 clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
Andreas Huber4f5e6022009-08-19 09:29:34 -07001698
Andreas Huberba7ec912010-02-12 10:42:02 -08001699 CHECK(mBuffer != NULL);
Andreas Huber4f5e6022009-08-19 09:29:34 -07001700 mBuffer->set_range(
Andreas Huberdb5d6622010-01-12 16:30:44 -08001701 mBuffer->range_offset() + mNALLengthSize + nal_size,
1702 mBuffer->range_length() - mNALLengthSize - nal_size);
Andreas Huber4f5e6022009-08-19 09:29:34 -07001703
1704 if (mBuffer->range_length() == 0) {
1705 mBuffer->release();
1706 mBuffer = NULL;
1707 }
1708
1709 *out = clone;
1710
1711 return OK;
1712 } else {
1713 // Whole NAL units are returned but each fragment is prefixed by
1714 // the start code (0x00 00 00 01).
1715
Andreas Hubere46b7be2009-07-14 16:56:47 -07001716 ssize_t num_bytes_read =
Andreas Huber9a12baf2009-10-23 10:22:30 -07001717 mDataSource->readAt(offset, mSrcBuffer, size);
Andreas Hubere46b7be2009-07-14 16:56:47 -07001718
1719 if (num_bytes_read < (ssize_t)size) {
1720 mBuffer->release();
1721 mBuffer = NULL;
1722
Andreas Huber4f5e6022009-08-19 09:29:34 -07001723 return ERROR_IO;
Andreas Hubere46b7be2009-07-14 16:56:47 -07001724 }
1725
Andreas Huber4f5e6022009-08-19 09:29:34 -07001726 uint8_t *dstData = (uint8_t *)mBuffer->data();
1727 size_t srcOffset = 0;
1728 size_t dstOffset = 0;
Andreas Huberdb5d6622010-01-12 16:30:44 -08001729
Andreas Huber4f5e6022009-08-19 09:29:34 -07001730 while (srcOffset < size) {
Andreas Huberdb5d6622010-01-12 16:30:44 -08001731 CHECK(srcOffset + mNALLengthSize <= size);
1732 size_t nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
1733 srcOffset += mNALLengthSize;
Andreas Huber909255a2010-01-14 14:13:15 -08001734
1735 if (srcOffset + nalLength > size) {
1736 mBuffer->release();
1737 mBuffer = NULL;
1738
1739 return ERROR_MALFORMED;
1740 }
Andreas Huber4f5e6022009-08-19 09:29:34 -07001741
1742 if (nalLength == 0) {
1743 continue;
1744 }
1745
1746 CHECK(dstOffset + 4 <= mBuffer->size());
1747
1748 dstData[dstOffset++] = 0;
1749 dstData[dstOffset++] = 0;
1750 dstData[dstOffset++] = 0;
1751 dstData[dstOffset++] = 1;
1752 memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
1753 srcOffset += nalLength;
1754 dstOffset += nalLength;
1755 }
Andreas Huberdb5d6622010-01-12 16:30:44 -08001756 CHECK_EQ(srcOffset, size);
Andreas Huber4f5e6022009-08-19 09:29:34 -07001757
Andreas Huberba7ec912010-02-12 10:42:02 -08001758 CHECK(mBuffer != NULL);
Andreas Huber4f5e6022009-08-19 09:29:34 -07001759 mBuffer->set_range(0, dstOffset);
Andreas Hubere46b7be2009-07-14 16:56:47 -07001760 mBuffer->meta_data()->clear();
Andreas Huberfa8de752009-10-08 10:07:49 -07001761 mBuffer->meta_data()->setInt64(
1762 kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
Andreas Huber6624c9f2010-07-20 15:04:28 -07001763
1764 if (targetSampleTimeUs >= 0) {
1765 mBuffer->meta_data()->setInt64(
1766 kKeyTargetTime, targetSampleTimeUs);
1767 }
1768
Andreas Huberad98d382010-08-06 14:13:10 -07001769 if (isSyncSample) {
1770 mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
1771 }
1772
Andreas Hubere46b7be2009-07-14 16:56:47 -07001773 ++mCurrentSampleIndex;
1774
Andreas Hubere46b7be2009-07-14 16:56:47 -07001775 *out = mBuffer;
1776 mBuffer = NULL;
1777
1778 return OK;
1779 }
Andreas Hubere46b7be2009-07-14 16:56:47 -07001780}
1781
Andreas Huber261eb0c2010-05-27 09:59:54 -07001782static bool LegacySniffMPEG4(
Andreas Huberbe06d262009-08-14 14:37:10 -07001783 const sp<DataSource> &source, String8 *mimeType, float *confidence) {
Andreas Hubere46b7be2009-07-14 16:56:47 -07001784 uint8_t header[8];
1785
Andreas Huber9a12baf2009-10-23 10:22:30 -07001786 ssize_t n = source->readAt(4, header, sizeof(header));
Andreas Hubere46b7be2009-07-14 16:56:47 -07001787 if (n < (ssize_t)sizeof(header)) {
1788 return false;
1789 }
1790
1791 if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
James Donge1130662010-04-13 15:06:41 -07001792 || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8)
1793 || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8)
Andreas Huber6bce6d82009-11-03 16:00:58 -08001794 || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
Andreas Huberdfb8eee2010-02-25 15:59:24 -08001795 || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)
Andreas Hubereea1eef2010-04-01 11:42:50 -07001796 || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) {
Andreas Hubere6c40962009-09-10 14:13:30 -07001797 *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
Andreas Huberefdd0882010-08-25 11:09:41 -07001798 *confidence = 0.4;
Andreas Hubere46b7be2009-07-14 16:56:47 -07001799
1800 return true;
1801 }
1802
1803 return false;
1804}
1805
Andreas Huber261eb0c2010-05-27 09:59:54 -07001806static bool isCompatibleBrand(uint32_t fourcc) {
1807 static const uint32_t kCompatibleBrands[] = {
1808 FOURCC('i', 's', 'o', 'm'),
1809 FOURCC('i', 's', 'o', '2'),
1810 FOURCC('a', 'v', 'c', '1'),
1811 FOURCC('3', 'g', 'p', '4'),
1812 FOURCC('m', 'p', '4', '1'),
1813 FOURCC('m', 'p', '4', '2'),
1814 };
1815
1816 for (size_t i = 0;
1817 i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]);
1818 ++i) {
1819 if (kCompatibleBrands[i] == fourcc) {
1820 return true;
1821 }
1822 }
1823
1824 return false;
1825}
1826
1827// Attempt to actually parse the 'ftyp' atom and determine if a suitable
1828// compatible brand is present.
1829static bool BetterSniffMPEG4(
1830 const sp<DataSource> &source, String8 *mimeType, float *confidence) {
1831 uint8_t header[12];
1832 if (source->readAt(0, header, 12) != 12
1833 || memcmp("ftyp", &header[4], 4)) {
1834 return false;
1835 }
1836
1837 size_t atomSize = U32_AT(&header[0]);
1838 if (atomSize < 16 || (atomSize % 4) != 0) {
1839 return false;
1840 }
1841
1842 bool success = false;
1843 if (isCompatibleBrand(U32_AT(&header[8]))) {
1844 success = true;
1845 } else {
1846 size_t numCompatibleBrands = (atomSize - 16) / 4;
1847 for (size_t i = 0; i < numCompatibleBrands; ++i) {
1848 uint8_t tmp[4];
1849 if (source->readAt(16 + i * 4, tmp, 4) != 4) {
1850 return false;
1851 }
1852
1853 if (isCompatibleBrand(U32_AT(&tmp[0]))) {
1854 success = true;
1855 break;
1856 }
1857 }
1858 }
1859
1860 if (!success) {
1861 return false;
1862 }
1863
1864 *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
Andreas Huberefdd0882010-08-25 11:09:41 -07001865 *confidence = 0.4f;
Andreas Huber261eb0c2010-05-27 09:59:54 -07001866
1867 return true;
1868}
1869
1870bool SniffMPEG4(
Andreas Huberefdd0882010-08-25 11:09:41 -07001871 const sp<DataSource> &source, String8 *mimeType, float *confidence,
1872 sp<AMessage> *) {
Andreas Huber261eb0c2010-05-27 09:59:54 -07001873 if (BetterSniffMPEG4(source, mimeType, confidence)) {
1874 return true;
1875 }
1876
1877 if (LegacySniffMPEG4(source, mimeType, confidence)) {
1878 LOGW("Identified supported mpeg4 through LegacySniffMPEG4.");
1879 return true;
1880 }
1881
1882 return false;
1883}
1884
Andreas Hubere46b7be2009-07-14 16:56:47 -07001885} // namespace android
1886