am b8814dce: Merge "Allow sniffers to return a packet of opaque data that the corresponding extractor can take advantage of to not duplicate work already done sniffing. The mp3 extractor takes advantage of this now." into gingerbread

Merge commit 'b8814dce287552c1bdf13fa999296ebc7387776d' into gingerbread-plus-aosp

* commit 'b8814dce287552c1bdf13fa999296ebc7387776d':
  Allow sniffers to return a packet of opaque data that the corresponding extractor can take advantage of to not duplicate work already done sniffing. The mp3 extractor takes advantage of this now.
This commit is contained in:
Andreas Huber
2010-08-25 13:13:57 -07:00
committed by Android Git Automerger
17 changed files with 87 additions and 32 deletions

View File

@ -28,6 +28,7 @@
namespace android { namespace android {
struct AMessage;
class String8; class String8;
class DataSource : public RefBase { class DataSource : public RefBase {
@ -59,10 +60,14 @@ public:
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
bool sniff(String8 *mimeType, float *confidence); bool sniff(String8 *mimeType, float *confidence, sp<AMessage> *meta);
// The sniffer can optionally fill in "meta" with an AMessage containing
// a dictionary of values that helps the corresponding extractor initialize
// its state without duplicating effort already exerted by the sniffer.
typedef bool (*SnifferFunc)( typedef bool (*SnifferFunc)(
const sp<DataSource> &source, String8 *mimeType, float *confidence); const sp<DataSource> &source, String8 *mimeType,
float *confidence, sp<AMessage> *meta);
static void RegisterSniffer(SnifferFunc func); static void RegisterSniffer(SnifferFunc func);
static void RegisterDefaultSniffers(); static void RegisterDefaultSniffers();

View File

@ -87,7 +87,7 @@ AMRExtractor::AMRExtractor(const sp<DataSource> &source)
mInitCheck(NO_INIT) { mInitCheck(NO_INIT) {
String8 mimeType; String8 mimeType;
float confidence; float confidence;
if (!SniffAMR(mDataSource, &mimeType, &confidence)) { if (!SniffAMR(mDataSource, &mimeType, &confidence, NULL)) {
return; return;
} }
@ -276,7 +276,8 @@ status_t AMRSource::read(
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool SniffAMR( bool SniffAMR(
const sp<DataSource> &source, String8 *mimeType, float *confidence) { const sp<DataSource> &source, String8 *mimeType, float *confidence,
sp<AMessage> *) {
char header[9]; char header[9];
if (source->readAt(0, header, sizeof(header)) != sizeof(header)) { if (source->readAt(0, header, sizeof(header)) != sizeof(header)) {

View File

@ -25,6 +25,7 @@
#include "matroska/MatroskaExtractor.h" #include "matroska/MatroskaExtractor.h"
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/DataSource.h> #include <media/stagefright/DataSource.h>
#include <media/stagefright/FileSource.h> #include <media/stagefright/FileSource.h>
#include <media/stagefright/MediaErrors.h> #include <media/stagefright/MediaErrors.h>
@ -56,19 +57,23 @@ status_t DataSource::getSize(off_t *size) {
Mutex DataSource::gSnifferMutex; Mutex DataSource::gSnifferMutex;
List<DataSource::SnifferFunc> DataSource::gSniffers; List<DataSource::SnifferFunc> DataSource::gSniffers;
bool DataSource::sniff(String8 *mimeType, float *confidence) { bool DataSource::sniff(
String8 *mimeType, float *confidence, sp<AMessage> *meta) {
*mimeType = ""; *mimeType = "";
*confidence = 0.0f; *confidence = 0.0f;
meta->clear();
Mutex::Autolock autoLock(gSnifferMutex); Mutex::Autolock autoLock(gSnifferMutex);
for (List<SnifferFunc>::iterator it = gSniffers.begin(); for (List<SnifferFunc>::iterator it = gSniffers.begin();
it != gSniffers.end(); ++it) { it != gSniffers.end(); ++it) {
String8 newMimeType; String8 newMimeType;
float newConfidence; float newConfidence;
if ((*it)(this, &newMimeType, &newConfidence)) { sp<AMessage> newMeta;
if ((*it)(this, &newMimeType, &newConfidence, &newMeta)) {
if (newConfidence > *confidence) { if (newConfidence > *confidence) {
*mimeType = newMimeType; *mimeType = newMimeType;
*confidence = newConfidence; *confidence = newConfidence;
*meta = newMeta;
} }
} }
} }
@ -92,13 +97,13 @@ void DataSource::RegisterSniffer(SnifferFunc func) {
// static // static
void DataSource::RegisterDefaultSniffers() { void DataSource::RegisterDefaultSniffers() {
RegisterSniffer(SniffMP3);
RegisterSniffer(SniffMPEG4); RegisterSniffer(SniffMPEG4);
RegisterSniffer(SniffAMR);
RegisterSniffer(SniffWAV);
RegisterSniffer(SniffOgg);
RegisterSniffer(SniffMatroska); RegisterSniffer(SniffMatroska);
RegisterSniffer(SniffOgg);
RegisterSniffer(SniffWAV);
RegisterSniffer(SniffAMR);
RegisterSniffer(SniffMPEG2TS); RegisterSniffer(SniffMPEG2TS);
RegisterSniffer(SniffMP3);
} }
// static // static

View File

@ -22,6 +22,7 @@
#include "include/ID3.h" #include "include/ID3.h"
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/DataSource.h> #include <media/stagefright/DataSource.h>
#include <media/stagefright/MediaBuffer.h> #include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaBufferGroup.h> #include <media/stagefright/MediaBufferGroup.h>
@ -456,15 +457,31 @@ private:
MP3Source &operator=(const MP3Source &); MP3Source &operator=(const MP3Source &);
}; };
MP3Extractor::MP3Extractor(const sp<DataSource> &source) MP3Extractor::MP3Extractor(
const sp<DataSource> &source, const sp<AMessage> &meta)
: mDataSource(source), : mDataSource(source),
mFirstFramePos(-1), mFirstFramePos(-1),
mFixedHeader(0), mFixedHeader(0),
mByteNumber(0) { mByteNumber(0) {
off_t pos = 0; off_t pos = 0;
uint32_t header; uint32_t header;
bool success = Resync(mDataSource, 0, &pos, &header); bool success;
CHECK(success);
int64_t meta_offset;
uint32_t meta_header;
if (meta != NULL
&& meta->findInt64("offset", &meta_offset)
&& meta->findInt32("header", (int32_t *)&meta_header)) {
// The sniffer has already done all the hard work for us, simply
// accept its judgement.
pos = (off_t)meta_offset;
header = meta_header;
success = true;
} else {
success = Resync(mDataSource, 0, &pos, &header);
CHECK(success);
}
if (success) { if (success) {
mFirstFramePos = pos; mFirstFramePos = pos;
@ -759,15 +776,20 @@ sp<MetaData> MP3Extractor::getMetaData() {
} }
bool SniffMP3( bool SniffMP3(
const sp<DataSource> &source, String8 *mimeType, float *confidence) { const sp<DataSource> &source, String8 *mimeType,
float *confidence, sp<AMessage> *meta) {
off_t pos = 0; off_t pos = 0;
uint32_t header; uint32_t header;
if (!Resync(source, 0, &pos, &header)) { if (!Resync(source, 0, &pos, &header)) {
return false; return false;
} }
*meta = new AMessage;
(*meta)->setInt64("offset", pos);
(*meta)->setInt32("header", header);
*mimeType = MEDIA_MIMETYPE_AUDIO_MPEG; *mimeType = MEDIA_MIMETYPE_AUDIO_MPEG;
*confidence = 0.3f; *confidence = 0.2f;
return true; return true;
} }

View File

@ -1738,7 +1738,7 @@ static bool LegacySniffMPEG4(
|| !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8) || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)
|| !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) { || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) {
*mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4; *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
*confidence = 0.1; *confidence = 0.4;
return true; return true;
} }
@ -1805,13 +1805,14 @@ static bool BetterSniffMPEG4(
} }
*mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4; *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
*confidence = 0.3f; *confidence = 0.4f;
return true; return true;
} }
bool SniffMPEG4( bool SniffMPEG4(
const sp<DataSource> &source, String8 *mimeType, float *confidence) { const sp<DataSource> &source, String8 *mimeType, float *confidence,
sp<AMessage> *) {
if (BetterSniffMPEG4(source, mimeType, confidence)) { if (BetterSniffMPEG4(source, mimeType, confidence)) {
return true; return true;
} }

View File

@ -27,6 +27,7 @@
#include "matroska/MatroskaExtractor.h" #include "matroska/MatroskaExtractor.h"
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/DataSource.h> #include <media/stagefright/DataSource.h>
#include <media/stagefright/MediaDefs.h> #include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaExtractor.h> #include <media/stagefright/MediaExtractor.h>
@ -46,10 +47,12 @@ uint32_t MediaExtractor::flags() const {
// static // static
sp<MediaExtractor> MediaExtractor::Create( sp<MediaExtractor> MediaExtractor::Create(
const sp<DataSource> &source, const char *mime) { const sp<DataSource> &source, const char *mime) {
sp<AMessage> meta;
String8 tmp; String8 tmp;
if (mime == NULL) { if (mime == NULL) {
float confidence; float confidence;
if (!source->sniff(&tmp, &confidence)) { if (!source->sniff(&tmp, &confidence, &meta)) {
LOGV("FAILED to autodetect media content."); LOGV("FAILED to autodetect media content.");
return NULL; return NULL;
@ -64,7 +67,7 @@ sp<MediaExtractor> MediaExtractor::Create(
|| !strcasecmp(mime, "audio/mp4")) { || !strcasecmp(mime, "audio/mp4")) {
return new MPEG4Extractor(source); return new MPEG4Extractor(source);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) { } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
return new MP3Extractor(source); return new MP3Extractor(source, meta);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB) } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)
|| !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) { || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
return new AMRExtractor(source); return new AMRExtractor(source);

View File

@ -804,7 +804,8 @@ sp<MetaData> OggExtractor::getMetaData() {
} }
bool SniffOgg( bool SniffOgg(
const sp<DataSource> &source, String8 *mimeType, float *confidence) { const sp<DataSource> &source, String8 *mimeType, float *confidence,
sp<AMessage> *) {
char tmp[4]; char tmp[4];
if (source->readAt(0, tmp, 4) < 4 || memcmp(tmp, "OggS", 4)) { if (source->readAt(0, tmp, 4) < 4 || memcmp(tmp, "OggS", 4)) {
return false; return false;

View File

@ -404,7 +404,8 @@ status_t WAVSource::read(
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool SniffWAV( bool SniffWAV(
const sp<DataSource> &source, String8 *mimeType, float *confidence) { const sp<DataSource> &source, String8 *mimeType, float *confidence,
sp<AMessage> *) {
char header[12]; char header[12];
if (source->readAt(0, header, sizeof(header)) < (ssize_t)sizeof(header)) { if (source->readAt(0, header, sizeof(header)) < (ssize_t)sizeof(header)) {
return false; return false;

View File

@ -22,6 +22,7 @@
namespace android { namespace android {
struct AMessage;
class String8; class String8;
class AMRExtractor : public MediaExtractor { class AMRExtractor : public MediaExtractor {
@ -49,7 +50,8 @@ private:
}; };
bool SniffAMR( bool SniffAMR(
const sp<DataSource> &source, String8 *mimeType, float *confidence); const sp<DataSource> &source, String8 *mimeType, float *confidence,
sp<AMessage> *);
} // namespace android } // namespace android

View File

@ -22,13 +22,14 @@
namespace android { namespace android {
struct AMessage;
class DataSource; class DataSource;
class String8; class String8;
class MP3Extractor : public MediaExtractor { class MP3Extractor : public MediaExtractor {
public: public:
// Extractor assumes ownership of "source". // Extractor assumes ownership of "source".
MP3Extractor(const sp<DataSource> &source); MP3Extractor(const sp<DataSource> &source, const sp<AMessage> &meta);
virtual size_t countTracks(); virtual size_t countTracks();
virtual sp<MediaSource> getTrack(size_t index); virtual sp<MediaSource> getTrack(size_t index);
@ -52,7 +53,8 @@ private:
}; };
bool SniffMP3( bool SniffMP3(
const sp<DataSource> &source, String8 *mimeType, float *confidence); const sp<DataSource> &source, String8 *mimeType, float *confidence,
sp<AMessage> *meta);
} // namespace android } // namespace android

View File

@ -9,6 +9,7 @@
namespace android { namespace android {
struct AMessage;
struct AnotherPacketSource; struct AnotherPacketSource;
struct ATSParser; struct ATSParser;
struct DataSource; struct DataSource;
@ -47,7 +48,8 @@ private:
}; };
bool SniffMPEG2TS( bool SniffMPEG2TS(
const sp<DataSource> &source, String8 *mimeType, float *confidence); const sp<DataSource> &source, String8 *mimeType, float *confidence,
sp<AMessage> *);
} // namespace android } // namespace android

View File

@ -23,6 +23,7 @@
namespace android { namespace android {
struct AMessage;
class DataSource; class DataSource;
class SampleTable; class SampleTable;
class String8; class String8;
@ -75,7 +76,8 @@ private:
}; };
bool SniffMPEG4( bool SniffMPEG4(
const sp<DataSource> &source, String8 *mimeType, float *confidence); const sp<DataSource> &source, String8 *mimeType, float *confidence,
sp<AMessage> *);
} // namespace android } // namespace android

View File

@ -22,6 +22,7 @@
namespace android { namespace android {
struct AMessage;
class DataSource; class DataSource;
class String8; class String8;
@ -53,7 +54,8 @@ private:
}; };
bool SniffOgg( bool SniffOgg(
const sp<DataSource> &source, String8 *mimeType, float *confidence); const sp<DataSource> &source, String8 *mimeType, float *confidence,
sp<AMessage> *);
} // namespace android } // namespace android

View File

@ -22,6 +22,7 @@
namespace android { namespace android {
struct AMessage;
class DataSource; class DataSource;
class String8; class String8;
@ -58,7 +59,8 @@ private:
}; };
bool SniffWAV( bool SniffWAV(
const sp<DataSource> &source, String8 *mimeType, float *confidence); const sp<DataSource> &source, String8 *mimeType, float *confidence,
sp<AMessage> *);
} // namespace android } // namespace android

View File

@ -579,7 +579,8 @@ sp<MetaData> MatroskaExtractor::getMetaData() {
} }
bool SniffMatroska( bool SniffMatroska(
const sp<DataSource> &source, String8 *mimeType, float *confidence) { const sp<DataSource> &source, String8 *mimeType, float *confidence,
sp<AMessage> *) {
DataSourceReader reader(source); DataSourceReader reader(source);
mkvparser::EBMLHeader ebmlHeader; mkvparser::EBMLHeader ebmlHeader;
long long pos; long long pos;

View File

@ -27,6 +27,7 @@ struct Segment;
namespace android { namespace android {
struct AMessage;
class String8; class String8;
struct DataSourceReader; struct DataSourceReader;
@ -69,7 +70,8 @@ private:
}; };
bool SniffMatroska( bool SniffMatroska(
const sp<DataSource> &source, String8 *mimeType, float *confidence); const sp<DataSource> &source, String8 *mimeType, float *confidence,
sp<AMessage> *);
} // namespace android } // namespace android

View File

@ -174,7 +174,8 @@ status_t MPEG2TSExtractor::feedMore() {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool SniffMPEG2TS( bool SniffMPEG2TS(
const sp<DataSource> &source, String8 *mimeType, float *confidence) { const sp<DataSource> &source, String8 *mimeType, float *confidence,
sp<AMessage> *) {
#if 0 #if 0
char header; char header;
if (source->readAt(0, &header, 1) != 1 || header != 0x47) { if (source->readAt(0, &header, 1) != 1 || header != 0x47) {