Android N Audio播放五:如何选择Extractor

  我们在Android N Audio播放三:prepare大揭秘介绍了在prepare的过程中会创建Extractor, Extractor的主要作用是从容器格式中把音频和视频剥离出来,为之后的解码提供音频流和视频流,要知道。音频和视频的解码是分离的, 所以Extractor这一步非常重要。

1. Extractor流程图
  如惯例,我们还是先上流程图,对这个过程涉及到的类有个大概的了解。
  这里写图片描述

2. 流程详解
  接下来我们就按照流程图中的步骤一步一步来细看。
  
  2.1 GenericSource
  在prepare章节介绍过,在GenericSource的onPrepareAsync中会去创建Extractor.
  ./frameworks/av/media/libmediaplayerservice/nuplayer/GenericSource.cpp#onPrepareAsync

void NuPlayer::GenericSource::onPrepareAsync() {
    // delayed data source creation
    if (mDataSource == NULL) {
        ALOGE("onPrepareAsync  mDataSource is null");
        // set to false first, if the extractor
        // comes back as secure, set it to true then.
        mIsSecure = false;
        .....
    //JaychouNote1:创建Extractor
    // init extractor from data source
    status_t err = initFromDataSource();

    if (err != OK) {
        ALOGE("Failed to init from data source!");
        notifyPreparedAndCleanup(err);
        return;
    }
    ......
}
01-02 10:52:29.113 E/GenericSource(  646): onPrepareAsync  mDataSource is null

  ./frameworks/av/media/libmediaplayerservice/nuplayer/GenericSource.cpp#initFromDataSource

status_t NuPlayer::GenericSource::initFromDataSource() {
    ALOGE("initFromDataSource");
    sp<IMediaExtractor> extractor;
    String8 mimeType;
    float confidence;
    sp<AMessage> dummy;
    bool isWidevineStreaming = false;

    CHECK(mDataSource != NULL);
    ......
    //JaychouNote1: 我们这个例子既不是widewine也不是streaming
        extractor = MediaExtractor::Create(mDataSource,
                mimeType.isEmpty() ? NULL : mimeType.string());
    }

    if (extractor == NULL) {
        return UNKNOWN_ERROR;
    }

    if (extractor->getDrmFlag()) {
        checkDrmStatus(mDataSource);
    }

    mFileMeta = extractor->getMetaData();
    if (mFileMeta != NULL) {
        int64_t duration;
        if (mFileMeta->findInt64(kKeyDuration, &duration)) {
            mDurationUs = duration;
        }
       ......
       //JaychouNote2: 这里的mAudioTrack和mVideoTrack就是剥离出来的音频和视频
        // Do the string compare immediately with "mime",
        // we can't assume "mime" would stay valid after another
        // extractor operation, some extractors might modify meta
        // during getTrack() and make it invalid.
        if (!strncasecmp(mime, "audio/", 6)) {
            if (mAudioTrack.mSource == NULL) {
                mAudioTrack.mIndex = i;
                mAudioTrack.mSource = track;
                mAudioTrack.mPackets =
                    new AnotherPacketSource(mAudioTrack.mSource->getFormat());

                if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
                    mAudioIsVorbis = true;
                } else {
                    mAudioIsVorbis = false;
                }

                if (AVNuUtils::get()->isByteStreamModeEnabled(meta)) {
                    mIsByteMode = true;
                }
            }
        } else if (!strncasecmp(mime, "video/", 6)) {
            if (mVideoTrack.mSource == NULL) {
                mVideoTrack.mIndex = i;
                mVideoTrack.mSource = track;
                mVideoTrack.mPackets =
                    new AnotherPacketSource(mVideoTrack.mSource->getFormat());

                // check if the source requires secure buffers
                int32_t secure;
                if (meta->findInt32(kKeyRequiresSecureBuffers, &secure)
                        && secure) {
                    mIsSecure = true;
                    if (mUIDValid) {
                        extractor->setUID(mUID);
                    }
                }
            }
        }
    ......
    return OK;
}
01-02 10:52:29.115 E/GenericSource(  646): initFromDataSource

这里我们看到做了两件比较重要的事情, 一是根据source去创建extractor, 二是根据创建的extractor拿到剥离出来的音频和视频,分别是mAudioTrack和mVideoTrack。

2.2 MediaExtractor
我们来看Create.
  ./frameworks/av/media/libstagefright/MediaExtractor#Create

sp<IMediaExtractor> MediaExtractor::Create(
        const sp<DataSource> &source, const char *mime) {
    ALOGV("MediaExtractor::Create %s", mime);
        char value[PROPERTY_VALUE_MAX];
    if (property_get("media.stagefright.extractremote", value, NULL)
            && (!strcmp("0", value) || !strcasecmp("false", value))) {
        // local extractor
        ALOGW("creating media extractor in calling process");
        return CreateFromService(source, mime);
    } else {
        // Check if it's WVM, since WVMExtractor needs to be created in the media server process,
        // not the extractor process.
        String8 mime8;
        float confidence;
        sp<AMessage> meta;
        if (SniffWVM(source, &mime8, &confidence, &meta) &&
                !strcas
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值