MediaExtractor 是什么?

MediaExtractor 就是解复用器,将audio和video分离

Android 4.1目前支持mp4 mkv ogg wav flac amr ts mp3 ps aac wvm这几种分离器

其实android支持分离器支持的不好,很多格式都没有或者不够健壮,毕竟它一般是用在手机上,简单一些就够了,不过可以看到android media正在慢慢改进。


MediaExtractor 在哪被创建呢?

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::Create(
        const sp &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是什么?怎么被使用的

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 gSniffers;

    gSniffers.push_back(func);

}

bool DataSource::sniff(
        String8 *mimeType, float *confidence, sp *meta) {

    for (List::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;

}


如何创建一个MediaExtractor?

目前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 &source, String8 *mimeType,
            float *confidence, sp *meta);

bool SniffMPEG4(
        const sp &source, String8 *mimeType, float *confidence,
        sp *);

需要实现检测功能,例如读取一部分数据,解析后检测是否为该格式。根据检测结果返回分数。

在DataSource.cpp中

void DataSource::RegisterDefaultSniffers() {

RegisterSniffer(你的extractor)

}

sniff完成后,就需要实现具体的extractor了,open的function:

class MediaExtractor : public RefBase {
public:
    static sp Create(
            const sp &source, const char *mime = NULL);


    virtual size_t countTracks() = 0;
    virtual sp getTrack(size_t index) = 0;


    enum GetTrackMetaDataFlags {
        kIncludeExtensiveMetaData = 1
    };
    virtual sp getTrackMetaData(
            size_t index, uint32_t flags = 0) = 0;


    // Return container specific meta-data. The default implementation
    // returns an empty metadata object.
    virtual sp 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;
    }


更多相关文章

  1. 实现Android多张图片选择
  2. Android源码分析-全面理解Context
  3. Android(安卓)Mms专题之:MMS支持
  4. 三端易用的现代跨平台JsBridge之 IOS篇
  5. Android的StatusBar分析
  6. Android(安卓)为应用创建、删除桌面快捷方式
  7. Android支持RTL(从右向左)语言
  8. Android(安卓)httpClient 支持HTTPS
  9. Android学习整理之Activity篇

随机推荐

  1. Android内存管理机制
  2. Android的UI结构试图工具hierarchyviewer
  3. Android(安卓)RelativeLayout 属性
  4. Android(安卓)4.0.3 CTS 测试
  5. 《Android面试宝典》学习笔记(第二章:布局)
  6. Android异步处理一:使用Thread+Handler实
  7. Android(安卓)软键盘功能键(EditText)
  8. Android补间动画原理介绍
  9. Android初次使用遇到的两个有关问题
  10. android的android:taskAffinity