1. 程式人生 > >播放媒體檔案找到對應解碼器元件的過程

播放媒體檔案找到對應解碼器元件的過程

以下程式碼流程為一個媒體檔案解碼時找到對應外掛的流程:

函式 status_t NuPlayer::instantiateDecoder(boolaudio, sp<DecoderBase> *decoder) 函式初始化建立解碼器

status_t NuPlayer::instantiateDecoder(boolaudio, sp<DecoderBase> *decoder) {

   if (*decoder != NULL) {

       return OK;

    }

……

   if (audio) {

       sp<AMessage> notify = new AMessage(kWhatAudioNotify, id());

       ++mAudioDecoderGeneration;

       notify->setInt32("generation", mAudioDecoderGeneration);

       if (mOffloadAudio) {

           *decoder = new DecoderPassThrough(notify, mSource, mRenderer);

       } else {

           *decoder = new Decoder(notify, mSource, mRenderer);

       }

    }else {

       sp<AMessage> notify = new AMessage(kWhatVideoNotify, id());

       ++mVideoDecoderGeneration;

       notify->setInt32("generation", mVideoDecoderGeneration);

       *decoder = new Decoder(

                notify, mSource, mRenderer,mNativeWindow, mCCDecoder);

        // enable FRC if high-quality AV sync isrequested, even if not

       // queuing to native window, as this will even improve textureview

       // playback.

       {

           char value[PROPERTY_VALUE_MAX];

           if (property_get("persist.sys.media.avsync", value, NULL)&&

                    (!strcmp("1",value) || !strcasecmp("true", value))) {

               format->setInt32("auto-frc", 1);

           }

       }

    }

   if (mPlayerExtendedStats != NULL) {

       format->setObject(MEDIA_EXTENDED_STATS, mPlayerExtendedStats);

    }

    (*decoder)->init();

(*decoder)->configure(format, mIsStreaming);

……
……

}

void NuPlayer::DecoderBase::configure(constsp<AMessage> &format, bool isStreaming) {

   sp<AMessage> msg = new AMessage(kWhatConfigure, id());

   msg->setMessage("format", format);

   msg->setInt32("isStreaming", isStreaming);

   sp<AMessage> response;

   PostAndAwaitResponse(msg, &response);

}

voidNuPlayer::DecoderBase::onMessageReceived(const sp<AMessage> &msg) {

   switch (msg->what()) {

       case kWhatConfigure:

       {

           uint32_t replyID;

           CHECK(msg->senderAwaitsResponse(&replyID));

           sp<AMessage> format;

           uint32_t isStreaming;

           CHECK(msg->findMessage("format", &format));

           CHECK(msg->findInt32("isStreaming", (int32_t*)&isStreaming));

           onConfigure(format,isStreaming);

           (new AMessage)->postReply(replyID);

           break;

       }

voidNuPlayer::Decoder::onConfigure(const sp<AMessage> &format, boolisStreaming) {

   CHECK(mCodec == NULL);

……

   ExtendedCodec::overrideMimeType(format, &mime);

   /* time allocateNode here */

    {

       if (mPlayerExtendedStats == NULL) {

            format->findObject(MEDIA_EXTENDED_STATS,(sp<RefBase>*)&mPlayerExtendedStats);

       }

       int32_t isVideo = !strncasecmp(mime.c_str(), "video/", 6);

       ExtendedStats::AutoProfile autoProfile(

                STATS_PROFILE_ALLOCATE_NODE(isVideo),mPlayerExtendedStats);

       mCodec = MediaCodec::CreateByType(mCodecLooper,mime.c_str(), false /* encoder */);

    }

   int32_t secure = 0;

   if (format->findInt32("secure", &secure) &&secure != 0) {

       if (mCodec != NULL) {

           mCodec->getName(&mComponentName);

           mComponentName.append(".secure");

           mCodec->release();

           ALOGI("[%s] creating", mComponentName.c_str());

           mCodec =MediaCodec::CreateByComponentName(

                    mCodecLooper, mComponentName.c_str());

       }

    }

   if (mCodec == NULL) {

       ALOGE("Failed to create %s%s decoder",

                (secure ? "secure " :""), mime.c_str());

       handleError(UNKNOWN_ERROR);

       return;

    }

   mIsSecure = secure;

mCodec->getName(&mComponentName);

    status_t err;

    if (mNativeWindow != NULL) {

        // disconnect from surface asMediaCodec will reconnect

        err = native_window_api_disconnect(

                surface.get(), NATIVE_WINDOW_API_MEDIA);

        // We treat this as a warning, as thisis a preparatory step.

        // Codec will try to connect to thesurface, which is where

        // any error signaling will occur.

        ALOGW_IF(err != OK, "failed todisconnect from surface: %d", err);

    }

    if (mPlayerExtendedStats != NULL) {

       format->setObject(MEDIA_EXTENDED_STATS, mPlayerExtendedStats);

    }

    err =mCodec->configure(

            format,surface, NULL /* crypto */, 0 /* flags */);

    if (err != OK) {

        ALOGE("Failed to configure %sdecoder (err=%d)", mComponentName.c_str(), err);

        mCodec->release();

        mCodec.clear();

        handleError(err);

        return;

    }

    rememberCodecSpecificData(format);

    // the following should work in configuredstate

    CHECK_EQ((status_t)OK,mCodec->getInputFormat(&mInputFormat));

    err =mCodec->start();

    if (err != OK) {

        ALOGE("Failed to start %s decoder(err=%d)", mComponentName.c_str(), err);

        mCodec->release();

        mCodec.clear();

        handleError(err);

        return;

    }

    // the following should work after start

    CHECK_EQ((status_t)OK,mCodec->getInputBuffers(&mInputBuffers));

    releaseAndResetMediaBuffers();

    CHECK_EQ((status_t)OK,mCodec->getOutputBuffers(&mOutputBuffers));

    ALOGV("[%s] got %zu input and %zuoutput buffers",

            mComponentName.c_str(),

            mInputBuffers.size(),

            mOutputBuffers.size());

    if (mRenderer != NULL) {

        requestCodecNotification();

    }

    mPaused = false;

    mResumePending = false;

}

sp<MediaCodec> MediaCodec::CreateByType(

        const sp<ALooper> &looper,const char *mime, bool encoder, status_t *err) {

    sp<MediaCodec> codec = newMediaCodec(looper);

    const status_t ret = codec->init(mime,true /* nameIsType */, encoder);

    if (err != NULL) {

        *err = ret;

    }

    return ret == OK ? codec : NULL; // NULLdeallocates codec.

}

void MediaCodec::onMessageReceived(const sp<AMessage>&msg) {

    switch (msg->what()) {

        case kWhatCodecNotify:

        {

        case kWhatInit:

        {

            uint32_t replyID;

           CHECK(msg->senderAwaitsResponse(&replyID));

            if (mState != UNINITIALIZED) {

                PostReplyWithError(replyID,INVALID_OPERATION);

                break;

            }

            mReplyID = replyID;

            setState(INITIALIZING);

            AString name;

            CHECK(msg->findString("name",&name));

            int32_t nameIsType;

            int32_t encoder = false;

           CHECK(msg->findInt32("nameIsType", &nameIsType));

            if (nameIsType) {

               CHECK(msg->findInt32("encoder", &encoder));

            }

            sp<AMessage> format = newAMessage;

            if (nameIsType) {

               format->setString("mime", name.c_str());

               format->setInt32("encoder", encoder);

            } else {

                format->setString("componentName",name.c_str());

            }

            mCodec->initiateAllocateComponent(format);

            break;

……

}

void ACodec::initiateAllocateComponent(const sp<AMessage>&msg) {

    msg->setWhat(kWhatAllocateComponent);

    msg->setTarget(id());

    msg->post();

}

bool ACodec::UninitializedState::onAllocateComponent(constsp<AMessage> &msg) {

    ALOGV("onAllocateComponent");

   ATRACE_NAME("onAllocatecomponent");

……

#ifdefENABLE_AV_ENHANCEMENTS

    // Call UseQCHWAACEncoder with no argumentsto get the correct state since

    // MediaCodecSource does not pass theoutput format details when calling

    // kInit leading to msg passed not havingenough details

    if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)

        &&ExtendedUtils::UseQCHWAACEncoder()) {

        //use hw aac encoder

        ALOGD("use QCOM HW AACencoder");

        OMXCodec::findMatchingCodecs(

                mime.c_str(),

                encoder, // createEncoder

                "OMX.qcom.audio.encoder.aac",  // OMX.qcom.audio.encoder.aac

                0,     // flags

                &matchingCodecs);

    } else if (!strcasecmp(mime.c_str(),MEDIA_MIMETYPE_AUDIO_FLAC) && !encoder) {

        //use google's raw decoder

        OMXCodec::findMatchingCodecs(

                MEDIA_MIMETYPE_AUDIO_RAW,

                encoder, //createEncoder

               "OMX.google.raw.decoder",

                0, //flags

                &matchingCodecs);

    } else

        OMXCodec::findMatchingCodecs(

                mime.c_str(),

                encoder, // createEncoder

                NULL,  // matchComponentName

                0,     // flags

                &matchingCodecs);

#else

    OMXCodec::findMatchingCodecs(

                mime.c_str(),

                encoder, // createEncoder

                NULL,  // matchComponentName

                0,     // flags

                &matchingCodecs);

#endif

    }

    sp<CodecObserver> observer = newCodecObserver;

    IOMX::node_id node = NULL;

    for (size_t matchIndex = 0; matchIndex <matchingCodecs.size();

            ++matchIndex) {

        componentName =matchingCodecs.itemAt(matchIndex).mName.string();

        quirks =matchingCodecs.itemAt(matchIndex).mQuirks;

       ExtendedCodec::overrideComponentName(quirks, msg, &componentName,&mime, encoder);

        pid_t tid = androidGetTid();

        int prevPriority =androidGetThreadPriority(tid);

        androidSetThreadPriority(tid,ANDROID_PRIORITY_FOREGROUND);

        status_t err = omx->allocateNode(componentName.c_str(), observer, &node);

        androidSetThreadPriority(tid,prevPriority);

……

}

status_t OMX::allocateNode(

        const char *name, constsp<IOMXObserver> &observer, node_id *node) {

    Mutex::Autolock autoLock(mLock);

    *node = 0;

    OMXNodeInstance *instance = newOMXNodeInstance(this, observer, name);

    OMX_COMPONENTTYPE *handle;

    OMX_ERRORTYPE err =mMaster->makeComponentInstance(

            name,&OMXNodeInstance::kCallbacks,

            instance,&handle);

    if (err != OMX_ErrorNone) {

        ALOGE("FAILED to allocate omxcomponent '%s'", name);

        instance->onGetHandleFailed();

        return UNKNOWN_ERROR;

    }

    *node = makeNodeID(instance);

    mDispatchers.add(*node, newCallbackDispatcher(instance));

    instance->setHandle(*node, handle);

    mLiveNodes.add(observer->asBinder(),instance);

   observer->asBinder()->linkToDeath(this);

    return OK;

}

OMX_ERRORTYPE OMXMaster::makeComponentInstance(

        const char *name,

        const OMX_CALLBACKTYPE *callbacks,

        OMX_PTR appData,

        OMX_COMPONENTTYPE **component) {

    Mutex::Autolock autoLock(mLock);

    *component = NULL;

    ssize_t index = mPluginByComponentName.indexOfKey(String8(name));

    if (index < 0) {

        return OMX_ErrorInvalidComponentName;

    }

    OMXPluginBase *plugin =mPluginByComponentName.valueAt(index);

    OMX_ERRORTYPE err =

       plugin->makeComponentInstance(name, callbacks, appData, component);

    if (err != OMX_ErrorNone) {

        return err;

    }

    mPluginByInstance.add(*component, plugin);

    return err;

}

OMX_ERRORTYPESoftOMXPlugin::makeComponentInstance(

        const char *name,

        const OMX_CALLBACKTYPE *callbacks,

        OMX_PTR appData,

        OMX_COMPONENTTYPE **component) {

    ALOGV("makeComponentInstance'%s'", name);

……

        CreateSoftOMXComponentFunccreateSoftOMXComponent =

            (CreateSoftOMXComponentFunc)dlsym(

                    libHandle,

                   "_Z22createSoftOMXComponentPKcPK16OMX_CALLBACKTYPE"

                   "PvPP17OMX_COMPONENTTYPE");

        if (createSoftOMXComponent == NULL) {

            dlclose(libHandle);

            libHandle = NULL;

            return OMX_ErrorComponentNotFound;

        }

       sp<SoftOMXComponent> codec =

           (*createSoftOMXComponent)(name, callbacks, appData, component);

        if (codec == NULL) {

            dlclose(libHandle);

            libHandle = NULL;

            returnOMX_ErrorInsufficientResources;

        }

        OMX_ERRORTYPE err =codec->initCheck();

        if (err != OMX_ErrorNone) {

            dlclose(libHandle);

……

}