MediaExtractor 就是解复用器,将audio和video分离
Android 4.1目前支持mp4 mkv ogg wav flac amr ts mp3 ps aac wvm这几种分离器
其实android支持分离器支持的不好,很多格式都没有或者不够健壮,毕竟它一般是用在手机上,简单一些就够了,不过可以看到android media正在慢慢改进。
AwesomePlayer::finishSetDataSource_l() {
//如果是http网络流,会创建http datasource
mConnectingDataSource = HTTPBase::Create(
(mFlags & INCOGNITO)
? HTTPBase::kFlagIncognito
: 0);
//如果是本地流:
dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
//最终会调用 source = new FileSource(uri);
extractor = MediaExtractor::Create(
dataSource, sniffedMIME.empty() ? NULL : sniffedMIME.c_str());
}
sp<MediaExtractor> MediaExtractor::Create(
const sp<DataSource> &source, const char *mime) {
//sniff是很重要的模块,其目的是到底选择哪个MediaExtrator进行创建
//通过得到的mime创建对应的
if (!source->sniff(&tmp, &confidence, &meta)) {
ALOGV("FAILED to autodetect media content.");
//例如:
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
ret = new MP3Extractor(source, meta);
}
}
Sniff就是用于判别到底使用哪个Extractor,调用每个MediaExtrator的sniff,得到一个分数,最后返回MIME
void DataSource::RegisterDefaultSniffers() {
//这里就是把每个Extractor的sniff function注册进去
RegisterSniffer(SniffMPEG4);
RegisterSniffer(SniffMatroska);
RegisterSniffer(SniffOgg);
RegisterSniffer(SniffWAV);
RegisterSniffer(SniffFLAC);
RegisterSniffer(SniffAMR);
RegisterSniffer(SniffMPEG2TS);
RegisterSniffer(SniffMP3);
RegisterSniffer(SniffAAC);
// RegisterSniffer(SniffMPEG2PS);
RegisterSniffer(SniffWVM);
}
void DataSource::RegisterSniffer(SnifferFunc func, bool isExtendedExtractor) {
//很简单,把func放进list中 static List<SnifferFunc> gSniffers;
gSniffers.push_back(func);
}
bool DataSource::sniff(
String8 *mimeType, float *confidence, sp<AMessage> *meta) {
for (List<SnifferFunc>::iterator it = gSniffers.begin();
it != gSniffers.end(); ++it) {
if ((*it)(this, &newMimeType, &newConfidence, &newMeta)) {
//得到一个更大的sniff值
if (newConfidence > *confidence) {
//当获得的值 >= 0.6f时,表示就用这个extractor了,直接返回
if(*confidence >= 0.6f) {
break;
}
目前android支持的extractor还是比较弱,可能需要自己新加入一些extractor,实现步骤
首先需要实现sniff,以mpeg4extractor为例:
// 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, sp<AMessage> *meta);
bool SniffMPEG4(
const sp<DataSource> &source, String8 *mimeType, float *confidence,
sp<AMessage> *);
需要实现检测功能,例如读取一部分数据,解析后检测是否为该格式。根据检测结果返回分数。
在DataSource.cpp中
void DataSource::RegisterDefaultSniffers() {
RegisterSniffer(你的extractor)
}
sniff完成后,就需要实现具体的extractor了,open的function:
class MediaExtractor : public RefBase {
public:
static sp<MediaExtractor> Create(
const sp<DataSource> &source, const char *mime = NULL);
virtual size_t countTracks() = 0;
virtual sp<MediaSource> getTrack(size_t index) = 0;
enum GetTrackMetaDataFlags {
kIncludeExtensiveMetaData = 1
};
virtual sp<MetaData> getTrackMetaData(
size_t index, uint32_t flags = 0) = 0;
// Return container specific meta-data. The default implementation
// returns an empty metadata object.
virtual sp<MetaData> getMetaData();
enum Flags {
CAN_SEEK_BACKWARD = 1, // the "seek 10secs back button"
CAN_SEEK_FORWARD = 2, // the "seek 10secs forward button"
CAN_PAUSE = 4,
CAN_SEEK = 8, // the "seek bar"
CAN_SEEK_TO_ZERO = 16, // the "previous button" for ADIF clips
};
// If subclasses do _not_ override this, the default is
// CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK | CAN_PAUSE
virtual uint32_t flags() const;
// for DRM
void setDrmFlag(bool flag) {
mIsDrm = flag;
};
bool getDrmFlag() {
return mIsDrm;
}
virtual char* getDrmTrackInfo(size_t trackID, int *len) {
return NULL;
}