summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/MPEG4Extractor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libstagefright/MPEG4Extractor.cpp')
-rw-r--r--media/libstagefright/MPEG4Extractor.cpp90
1 files changed, 56 insertions, 34 deletions
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 9174d19..9d17064 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -17,6 +17,9 @@
#define LOG_TAG "MPEG4Extractor"
#include <utils/Log.h>
+#include "include/MPEG4Extractor.h"
+#include "include/SampleTable.h"
+
#include <arpa/inet.h>
#include <ctype.h>
@@ -25,14 +28,12 @@
#include <string.h>
#include <media/stagefright/DataSource.h>
-#include <media/stagefright/MPEG4Extractor.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/MetaData.h>
-#include <media/stagefright/SampleTable.h>
#include <media/stagefright/Utils.h>
#include <utils/String8.h>
@@ -43,6 +44,7 @@ public:
// Caller retains ownership of both "dataSource" and "sampleTable".
MPEG4Source(const sp<MetaData> &format,
const sp<DataSource> &dataSource,
+ int32_t timeScale,
const sp<SampleTable> &sampleTable);
virtual status_t start(MetaData *params = NULL);
@@ -177,7 +179,8 @@ size_t MPEG4Extractor::countTracks() {
return n;
}
-sp<MetaData> MPEG4Extractor::getTrackMetaData(size_t index) {
+sp<MetaData> MPEG4Extractor::getTrackMetaData(
+ size_t index, uint32_t flags) {
status_t err;
if ((err = readMetaData()) != OK) {
return NULL;
@@ -197,6 +200,25 @@ sp<MetaData> MPEG4Extractor::getTrackMetaData(size_t index) {
return NULL;
}
+ if ((flags & kIncludeExtensiveMetaData)
+ && !track->includes_expensive_metadata) {
+ track->includes_expensive_metadata = true;
+
+ const char *mime;
+ CHECK(track->meta->findCString(kKeyMIMEType, &mime));
+ if (!strncasecmp("video/", mime, 6)) {
+ uint32_t sampleIndex;
+ uint32_t sampleTime;
+ if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK
+ && track->sampleTable->getDecodingTime(
+ sampleIndex, &sampleTime) == OK) {
+ track->meta->setInt64(
+ kKeyThumbnailTime,
+ ((int64_t)sampleTime * 1000000) / track->timescale);
+ }
+ }
+ }
+
return track->meta;
}
@@ -227,7 +249,7 @@ static void MakeFourCCString(uint32_t x, char *s) {
status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
uint32_t hdr[2];
- if (mDataSource->read_at(*offset, hdr, 8) < 8) {
+ if (mDataSource->readAt(*offset, hdr, 8) < 8) {
return ERROR_IO;
}
uint64_t chunk_size = ntohl(hdr[0]);
@@ -235,7 +257,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
off_t data_offset = *offset + 8;
if (chunk_size == 1) {
- if (mDataSource->read_at(*offset + 8, &chunk_size, 8) < 8) {
+ if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
return ERROR_IO;
}
chunk_size = ntoh64(chunk_size);
@@ -252,7 +274,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
char buffer[256];
if (chunk_size <= sizeof(buffer)) {
- if (mDataSource->read_at(*offset, buffer, chunk_size) < chunk_size) {
+ if (mDataSource->readAt(*offset, buffer, chunk_size) < chunk_size) {
return ERROR_IO;
}
@@ -298,7 +320,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
CHECK(chunk_data_size >= 4);
uint8_t version;
- if (mDataSource->read_at(data_offset, &version, 1) < 1) {
+ if (mDataSource->readAt(data_offset, &version, 1) < 1) {
return ERROR_IO;
}
@@ -312,7 +334,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
}
uint8_t buffer[36 + 60];
- if (mDataSource->read_at(
+ if (mDataSource->readAt(
data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
return ERROR_IO;
}
@@ -329,7 +351,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
}
uint8_t buffer[24 + 60];
- if (mDataSource->read_at(
+ if (mDataSource->readAt(
data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
return ERROR_IO;
}
@@ -351,6 +373,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
mLastTrack = track;
track->meta = new MetaData;
+ track->includes_expensive_metadata = false;
track->timescale = 0;
track->sampleTable = new SampleTable(mDataSource);
track->meta->setCString(kKeyMIMEType, "application/octet-stream");
@@ -366,7 +389,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
}
uint8_t version;
- if (mDataSource->read_at(
+ if (mDataSource->readAt(
data_offset, &version, sizeof(version))
< (ssize_t)sizeof(version)) {
return ERROR_IO;
@@ -383,18 +406,17 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
}
uint32_t timescale;
- if (mDataSource->read_at(
+ if (mDataSource->readAt(
timescale_offset, &timescale, sizeof(timescale))
< (ssize_t)sizeof(timescale)) {
return ERROR_IO;
}
mLastTrack->timescale = ntohl(timescale);
- mLastTrack->meta->setInt32(kKeyTimeScale, mLastTrack->timescale);
int64_t duration;
if (version == 1) {
- if (mDataSource->read_at(
+ if (mDataSource->readAt(
timescale_offset + 4, &duration, sizeof(duration))
< (ssize_t)sizeof(duration)) {
return ERROR_IO;
@@ -402,14 +424,15 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
duration = ntoh64(duration);
} else {
int32_t duration32;
- if (mDataSource->read_at(
+ if (mDataSource->readAt(
timescale_offset + 4, &duration32, sizeof(duration32))
< (ssize_t)sizeof(duration32)) {
return ERROR_IO;
}
duration = ntohl(duration32);
}
- mLastTrack->meta->setInt32(kKeyDuration, duration);
+ mLastTrack->meta->setInt64(
+ kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
*offset += chunk_size;
break;
@@ -422,7 +445,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
}
uint8_t buffer[24];
- if (mDataSource->read_at(data_offset, buffer, 24) < 24) {
+ if (mDataSource->readAt(data_offset, buffer, 24) < 24) {
return ERROR_IO;
}
@@ -449,7 +472,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
uint8_t buffer[8];
CHECK(chunk_data_size >= (off_t)sizeof(buffer));
- if (mDataSource->read_at(
+ if (mDataSource->readAt(
data_offset, buffer, 8) < 8) {
return ERROR_IO;
}
@@ -492,7 +515,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
return ERROR_MALFORMED;
}
- if (mDataSource->read_at(
+ if (mDataSource->readAt(
data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
return ERROR_IO;
}
@@ -544,7 +567,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
return ERROR_MALFORMED;
}
- if (mDataSource->read_at(
+ if (mDataSource->readAt(
data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
return ERROR_IO;
}
@@ -655,7 +678,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
return ERROR_BUFFER_TOO_SMALL;
}
- if (mDataSource->read_at(
+ if (mDataSource->readAt(
data_offset, buffer, chunk_data_size) < chunk_data_size) {
return ERROR_IO;
}
@@ -679,7 +702,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
return ERROR_BUFFER_TOO_SMALL;
}
- if (mDataSource->read_at(
+ if (mDataSource->readAt(
data_offset, buffer, chunk_data_size) < chunk_data_size) {
return ERROR_IO;
}
@@ -722,7 +745,7 @@ sp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
}
return new MPEG4Source(
- track->meta, mDataSource, track->sampleTable);
+ track->meta, mDataSource, track->timescale, track->sampleTable);
}
////////////////////////////////////////////////////////////////////////////////
@@ -730,10 +753,11 @@ sp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
MPEG4Source::MPEG4Source(
const sp<MetaData> &format,
const sp<DataSource> &dataSource,
+ int32_t timeScale,
const sp<SampleTable> &sampleTable)
: mFormat(format),
mDataSource(dataSource),
- mTimescale(0),
+ mTimescale(timeScale),
mSampleTable(sampleTable),
mCurrentSampleIndex(0),
mIsAVC(false),
@@ -746,9 +770,6 @@ MPEG4Source::MPEG4Source(
bool success = mFormat->findCString(kKeyMIMEType, &mime);
CHECK(success);
- success = mFormat->findInt32(kKeyTimeScale, &mTimescale);
- CHECK(success);
-
mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
}
@@ -868,7 +889,7 @@ status_t MPEG4Source::read(
if (!mIsAVC || mWantsNALFragments) {
if (newBuffer) {
ssize_t num_bytes_read =
- mDataSource->read_at(offset, (uint8_t *)mBuffer->data(), size);
+ mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
if (num_bytes_read < (ssize_t)size) {
mBuffer->release();
@@ -879,8 +900,8 @@ status_t MPEG4Source::read(
mBuffer->set_range(0, size);
mBuffer->meta_data()->clear();
- mBuffer->meta_data()->setInt32(kKeyTimeUnits, dts);
- mBuffer->meta_data()->setInt32(kKeyTimeScale, mTimescale);
+ mBuffer->meta_data()->setInt64(
+ kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
++mCurrentSampleIndex;
}
@@ -923,7 +944,7 @@ status_t MPEG4Source::read(
// the start code (0x00 00 00 01).
ssize_t num_bytes_read =
- mDataSource->read_at(offset, mSrcBuffer, size);
+ mDataSource->readAt(offset, mSrcBuffer, size);
if (num_bytes_read < (ssize_t)size) {
mBuffer->release();
@@ -959,8 +980,8 @@ status_t MPEG4Source::read(
mBuffer->set_range(0, dstOffset);
mBuffer->meta_data()->clear();
- mBuffer->meta_data()->setInt32(kKeyTimeUnits, dts);
- mBuffer->meta_data()->setInt32(kKeyTimeScale, mTimescale);
+ mBuffer->meta_data()->setInt64(
+ kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
++mCurrentSampleIndex;
*out = mBuffer;
@@ -974,13 +995,14 @@ bool SniffMPEG4(
const sp<DataSource> &source, String8 *mimeType, float *confidence) {
uint8_t header[8];
- ssize_t n = source->read_at(4, header, sizeof(header));
+ ssize_t n = source->readAt(4, header, sizeof(header));
if (n < (ssize_t)sizeof(header)) {
return false;
}
if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
- || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)) {
+ || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
+ || !memcmp(header, "ftypM4A ", 8)) {
*mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
*confidence = 0.1;