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.
Change-Id: Icb77ae3ee95a69c7da25b4d3b8696c0a2d33028a related-to-bug: 2948754
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
|
||||
namespace android {
|
||||
|
||||
struct AMessage;
|
||||
class String8;
|
||||
|
||||
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)(
|
||||
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 RegisterDefaultSniffers();
|
||||
|
||||
@@ -87,7 +87,7 @@ AMRExtractor::AMRExtractor(const sp<DataSource> &source)
|
||||
mInitCheck(NO_INIT) {
|
||||
String8 mimeType;
|
||||
float confidence;
|
||||
if (!SniffAMR(mDataSource, &mimeType, &confidence)) {
|
||||
if (!SniffAMR(mDataSource, &mimeType, &confidence, NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -276,7 +276,8 @@ status_t AMRSource::read(
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool SniffAMR(
|
||||
const sp<DataSource> &source, String8 *mimeType, float *confidence) {
|
||||
const sp<DataSource> &source, String8 *mimeType, float *confidence,
|
||||
sp<AMessage> *) {
|
||||
char header[9];
|
||||
|
||||
if (source->readAt(0, header, sizeof(header)) != sizeof(header)) {
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "matroska/MatroskaExtractor.h"
|
||||
|
||||
#include <media/stagefright/foundation/AMessage.h>
|
||||
#include <media/stagefright/DataSource.h>
|
||||
#include <media/stagefright/FileSource.h>
|
||||
#include <media/stagefright/MediaErrors.h>
|
||||
@@ -56,19 +57,23 @@ status_t DataSource::getSize(off_t *size) {
|
||||
Mutex DataSource::gSnifferMutex;
|
||||
List<DataSource::SnifferFunc> DataSource::gSniffers;
|
||||
|
||||
bool DataSource::sniff(String8 *mimeType, float *confidence) {
|
||||
bool DataSource::sniff(
|
||||
String8 *mimeType, float *confidence, sp<AMessage> *meta) {
|
||||
*mimeType = "";
|
||||
*confidence = 0.0f;
|
||||
meta->clear();
|
||||
|
||||
Mutex::Autolock autoLock(gSnifferMutex);
|
||||
for (List<SnifferFunc>::iterator it = gSniffers.begin();
|
||||
it != gSniffers.end(); ++it) {
|
||||
String8 newMimeType;
|
||||
float newConfidence;
|
||||
if ((*it)(this, &newMimeType, &newConfidence)) {
|
||||
sp<AMessage> newMeta;
|
||||
if ((*it)(this, &newMimeType, &newConfidence, &newMeta)) {
|
||||
if (newConfidence > *confidence) {
|
||||
*mimeType = newMimeType;
|
||||
*confidence = newConfidence;
|
||||
*meta = newMeta;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -92,13 +97,13 @@ void DataSource::RegisterSniffer(SnifferFunc func) {
|
||||
|
||||
// static
|
||||
void DataSource::RegisterDefaultSniffers() {
|
||||
RegisterSniffer(SniffMP3);
|
||||
RegisterSniffer(SniffMPEG4);
|
||||
RegisterSniffer(SniffAMR);
|
||||
RegisterSniffer(SniffWAV);
|
||||
RegisterSniffer(SniffOgg);
|
||||
RegisterSniffer(SniffMatroska);
|
||||
RegisterSniffer(SniffOgg);
|
||||
RegisterSniffer(SniffWAV);
|
||||
RegisterSniffer(SniffAMR);
|
||||
RegisterSniffer(SniffMPEG2TS);
|
||||
RegisterSniffer(SniffMP3);
|
||||
}
|
||||
|
||||
// static
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include "include/ID3.h"
|
||||
|
||||
#include <media/stagefright/foundation/AMessage.h>
|
||||
#include <media/stagefright/DataSource.h>
|
||||
#include <media/stagefright/MediaBuffer.h>
|
||||
#include <media/stagefright/MediaBufferGroup.h>
|
||||
@@ -456,15 +457,31 @@ private:
|
||||
MP3Source &operator=(const MP3Source &);
|
||||
};
|
||||
|
||||
MP3Extractor::MP3Extractor(const sp<DataSource> &source)
|
||||
MP3Extractor::MP3Extractor(
|
||||
const sp<DataSource> &source, const sp<AMessage> &meta)
|
||||
: mDataSource(source),
|
||||
mFirstFramePos(-1),
|
||||
mFixedHeader(0),
|
||||
mByteNumber(0) {
|
||||
off_t pos = 0;
|
||||
uint32_t header;
|
||||
bool success = Resync(mDataSource, 0, &pos, &header);
|
||||
CHECK(success);
|
||||
bool 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) {
|
||||
mFirstFramePos = pos;
|
||||
@@ -759,15 +776,20 @@ sp<MetaData> MP3Extractor::getMetaData() {
|
||||
}
|
||||
|
||||
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;
|
||||
uint32_t header;
|
||||
if (!Resync(source, 0, &pos, &header)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*meta = new AMessage;
|
||||
(*meta)->setInt64("offset", pos);
|
||||
(*meta)->setInt32("header", header);
|
||||
|
||||
*mimeType = MEDIA_MIMETYPE_AUDIO_MPEG;
|
||||
*confidence = 0.3f;
|
||||
*confidence = 0.2f;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1738,7 +1738,7 @@ static bool LegacySniffMPEG4(
|
||||
|| !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)
|
||||
|| !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) {
|
||||
*mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
|
||||
*confidence = 0.1;
|
||||
*confidence = 0.4;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1805,13 +1805,14 @@ static bool BetterSniffMPEG4(
|
||||
}
|
||||
|
||||
*mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
|
||||
*confidence = 0.3f;
|
||||
*confidence = 0.4f;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "matroska/MatroskaExtractor.h"
|
||||
|
||||
#include <media/stagefright/foundation/AMessage.h>
|
||||
#include <media/stagefright/DataSource.h>
|
||||
#include <media/stagefright/MediaDefs.h>
|
||||
#include <media/stagefright/MediaExtractor.h>
|
||||
@@ -46,10 +47,12 @@ uint32_t MediaExtractor::flags() const {
|
||||
// static
|
||||
sp<MediaExtractor> MediaExtractor::Create(
|
||||
const sp<DataSource> &source, const char *mime) {
|
||||
sp<AMessage> meta;
|
||||
|
||||
String8 tmp;
|
||||
if (mime == NULL) {
|
||||
float confidence;
|
||||
if (!source->sniff(&tmp, &confidence)) {
|
||||
if (!source->sniff(&tmp, &confidence, &meta)) {
|
||||
LOGV("FAILED to autodetect media content.");
|
||||
|
||||
return NULL;
|
||||
@@ -64,7 +67,7 @@ sp<MediaExtractor> MediaExtractor::Create(
|
||||
|| !strcasecmp(mime, "audio/mp4")) {
|
||||
return new MPEG4Extractor(source);
|
||||
} 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)
|
||||
|| !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
|
||||
return new AMRExtractor(source);
|
||||
|
||||
@@ -804,7 +804,8 @@ sp<MetaData> OggExtractor::getMetaData() {
|
||||
}
|
||||
|
||||
bool SniffOgg(
|
||||
const sp<DataSource> &source, String8 *mimeType, float *confidence) {
|
||||
const sp<DataSource> &source, String8 *mimeType, float *confidence,
|
||||
sp<AMessage> *) {
|
||||
char tmp[4];
|
||||
if (source->readAt(0, tmp, 4) < 4 || memcmp(tmp, "OggS", 4)) {
|
||||
return false;
|
||||
|
||||
@@ -404,7 +404,8 @@ status_t WAVSource::read(
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool SniffWAV(
|
||||
const sp<DataSource> &source, String8 *mimeType, float *confidence) {
|
||||
const sp<DataSource> &source, String8 *mimeType, float *confidence,
|
||||
sp<AMessage> *) {
|
||||
char header[12];
|
||||
if (source->readAt(0, header, sizeof(header)) < (ssize_t)sizeof(header)) {
|
||||
return false;
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
namespace android {
|
||||
|
||||
struct AMessage;
|
||||
class String8;
|
||||
|
||||
class AMRExtractor : public MediaExtractor {
|
||||
@@ -49,7 +50,8 @@ private:
|
||||
};
|
||||
|
||||
bool SniffAMR(
|
||||
const sp<DataSource> &source, String8 *mimeType, float *confidence);
|
||||
const sp<DataSource> &source, String8 *mimeType, float *confidence,
|
||||
sp<AMessage> *);
|
||||
|
||||
} // namespace android
|
||||
|
||||
|
||||
@@ -22,13 +22,14 @@
|
||||
|
||||
namespace android {
|
||||
|
||||
struct AMessage;
|
||||
class DataSource;
|
||||
class String8;
|
||||
|
||||
class MP3Extractor : public MediaExtractor {
|
||||
public:
|
||||
// Extractor assumes ownership of "source".
|
||||
MP3Extractor(const sp<DataSource> &source);
|
||||
MP3Extractor(const sp<DataSource> &source, const sp<AMessage> &meta);
|
||||
|
||||
virtual size_t countTracks();
|
||||
virtual sp<MediaSource> getTrack(size_t index);
|
||||
@@ -52,7 +53,8 @@ private:
|
||||
};
|
||||
|
||||
bool SniffMP3(
|
||||
const sp<DataSource> &source, String8 *mimeType, float *confidence);
|
||||
const sp<DataSource> &source, String8 *mimeType, float *confidence,
|
||||
sp<AMessage> *meta);
|
||||
|
||||
} // namespace android
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
namespace android {
|
||||
|
||||
struct AMessage;
|
||||
struct AnotherPacketSource;
|
||||
struct ATSParser;
|
||||
struct DataSource;
|
||||
@@ -47,7 +48,8 @@ private:
|
||||
};
|
||||
|
||||
bool SniffMPEG2TS(
|
||||
const sp<DataSource> &source, String8 *mimeType, float *confidence);
|
||||
const sp<DataSource> &source, String8 *mimeType, float *confidence,
|
||||
sp<AMessage> *);
|
||||
|
||||
} // namespace android
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
namespace android {
|
||||
|
||||
struct AMessage;
|
||||
class DataSource;
|
||||
class SampleTable;
|
||||
class String8;
|
||||
@@ -75,7 +76,8 @@ private:
|
||||
};
|
||||
|
||||
bool SniffMPEG4(
|
||||
const sp<DataSource> &source, String8 *mimeType, float *confidence);
|
||||
const sp<DataSource> &source, String8 *mimeType, float *confidence,
|
||||
sp<AMessage> *);
|
||||
|
||||
} // namespace android
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
namespace android {
|
||||
|
||||
struct AMessage;
|
||||
class DataSource;
|
||||
class String8;
|
||||
|
||||
@@ -53,7 +54,8 @@ private:
|
||||
};
|
||||
|
||||
bool SniffOgg(
|
||||
const sp<DataSource> &source, String8 *mimeType, float *confidence);
|
||||
const sp<DataSource> &source, String8 *mimeType, float *confidence,
|
||||
sp<AMessage> *);
|
||||
|
||||
} // namespace android
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
namespace android {
|
||||
|
||||
struct AMessage;
|
||||
class DataSource;
|
||||
class String8;
|
||||
|
||||
@@ -58,7 +59,8 @@ private:
|
||||
};
|
||||
|
||||
bool SniffWAV(
|
||||
const sp<DataSource> &source, String8 *mimeType, float *confidence);
|
||||
const sp<DataSource> &source, String8 *mimeType, float *confidence,
|
||||
sp<AMessage> *);
|
||||
|
||||
} // namespace android
|
||||
|
||||
|
||||
@@ -579,7 +579,8 @@ sp<MetaData> MatroskaExtractor::getMetaData() {
|
||||
}
|
||||
|
||||
bool SniffMatroska(
|
||||
const sp<DataSource> &source, String8 *mimeType, float *confidence) {
|
||||
const sp<DataSource> &source, String8 *mimeType, float *confidence,
|
||||
sp<AMessage> *) {
|
||||
DataSourceReader reader(source);
|
||||
mkvparser::EBMLHeader ebmlHeader;
|
||||
long long pos;
|
||||
|
||||
@@ -27,6 +27,7 @@ struct Segment;
|
||||
|
||||
namespace android {
|
||||
|
||||
struct AMessage;
|
||||
class String8;
|
||||
|
||||
struct DataSourceReader;
|
||||
@@ -69,7 +70,8 @@ private:
|
||||
};
|
||||
|
||||
bool SniffMatroska(
|
||||
const sp<DataSource> &source, String8 *mimeType, float *confidence);
|
||||
const sp<DataSource> &source, String8 *mimeType, float *confidence,
|
||||
sp<AMessage> *);
|
||||
|
||||
} // namespace android
|
||||
|
||||
|
||||
@@ -174,7 +174,8 @@ status_t MPEG2TSExtractor::feedMore() {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool SniffMPEG2TS(
|
||||
const sp<DataSource> &source, String8 *mimeType, float *confidence) {
|
||||
const sp<DataSource> &source, String8 *mimeType, float *confidence,
|
||||
sp<AMessage> *) {
|
||||
#if 0
|
||||
char header;
|
||||
if (source->readAt(0, &header, 1) != 1 || header != 0x47) {
|
||||
|
||||
Reference in New Issue
Block a user