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:
@ -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