zoukankan      html  css  js  c++  java
  • 内存、分配OMXCodec源码分析part2by小雨

    查了好多资料,发现还是不全,干脆自己整理吧,至少保证在我的做法正确的,以免误导读者,也是给自己做个记录吧!

        书接前文

        omxcodec创立完了当前,前面就要开始读取数据,码解,送出数据一系列的作操

        接着看initvideodecoder,create omxcodec当前,调用了strat法方,代码如下

    {
        CODEC_LOGV("OMXCodec::start ");
        Mutex::Autolock autoLock(mLock);
    
        if (mState != LOADED) {
            return UNKNOWN_ERROR;
        }
    
        sp<MetaData> params = new MetaData;
        if (mQuirks & kWantsNALFragments) {
            params->setInt32(kKeyWantsNALFragments, true);
        }
        if (meta) {
            int64_t startTimeUs = 0;
            int64_t timeUs;
            if (meta->findInt64(kKeyTime, &timeUs)) {
                startTimeUs = timeUs;
            }
            params->setInt64(kKeyTime, startTimeUs);
        }
        status_t err = mSource->start(params.get());
    
        if (err != OK) {
            return err;
        }
    
        mCodecSpecificDataIndex = 0;
        mInitialBufferSubmit = true;
        mSignalledEOS = false;
        mNoMoreOutputData = false;
        mOutputPortSettingsHaveChanged = false;
        mSeekTimeUs = -1;
        mSeekMode = ReadOptions::SEEK_CLOSEST_SYNC;
        mTargetTimeUs = -1;
        mFilledBuffers.clear();
        mPaused = false;
    
        err = init();
        if (err != OK) {
            ALOGV("init failed, so stop source");
            mSource->stop();
        }
        return err;
    }

        初始化一些参数,init数函接着看

    {
        // mLock is held.
    
        CHECK_EQ((int)mState, (int)LOADED);
    
        status_t err;
        if (!(mQuirks & kRequiresLoadedToIdleAfterAllocation)) {
            err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
            setState(LOADED_TO_IDLE);
        }
    
        err = allocateBuffers();
        if (err != (status_t)OK) {
            return err;
        }
    
        if (mQuirks & kRequiresLoadedToIdleAfterAllocation) {
            err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
            CHECK_EQ(err, (status_t)OK);
    
            setState(LOADED_TO_IDLE);
        }
    
        while (mState != EXECUTING && mState != ERROR) {
    		mAsyncCompletion.wait(mLock);
        }
        return mState == ERROR ? UNKNOWN_ERROR : OK;
    }

        omxcodec有一些状态的换转,然后就是allocateBuffers这个数函了

    {
        if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
            return allocateOutputBuffersFromNativeWindow();
        }
    
        if ((mFlags & kEnableGrallocUsageProtected) && portIndex == kPortIndexOutput) {
            ALOGE("protected output buffers must be stent to an ANativeWindow");
            return PERMISSION_DENIED;
        }
    
        status_t err = OK;
        if ((mFlags & kStoreMetaDataInVideoBuffers)
                && portIndex == kPortIndexInput) {
            err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexInput, OMX_TRUE);
            if (err != OK) {
                ALOGE("Storing meta data in video buffers is not supported");
                return err;
            }
        }
    
        OMX_PARAM_PORTDEFINITIONTYPE def;
        InitOMXParams(&def);
        def.nPortIndex = portIndex;
    
        err = mOMX->getParameter(
                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
    
        if (err != OK) {
            return err;
        }
    
    
        size_t totalSize = def.nBufferCountActual * def.nBufferSize;
        mDealer[portIndex] = new MemoryDealer(totalSize, "OMXCodec");
    
        for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
            sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
            CHECK(mem.get() != NULL);
    
            BufferInfo info;
            info.mData = NULL;
            info.mSize = def.nBufferSize;
    
            IOMX::buffer_id buffer;
            if (portIndex == kPortIndexInput
                    && ((mQuirks & kRequiresAllocateBufferOnInputPorts)
                        || (mFlags & kUseSecureInputBuffers))) {
                if (mOMXLivesLocally) {
                    mem.clear();
    
                    err = mOMX->allocateBuffer(
                            mNode, portIndex, def.nBufferSize, &buffer,
                            &info.mData);
                } else {
                    err = mOMX->allocateBufferWithBackup(
                            mNode, portIndex, mem, &buffer);
                }
            } else if (portIndex == kPortIndexOutput
                    && (mQuirks & kRequiresAllocateBufferOnOutputPorts)) {
                if (mOMXLivesLocally) {
                    mem.clear();
    
                    err = mOMX->allocateBuffer(
                            mNode, portIndex, def.nBufferSize, &buffer,
                            &info.mData);
                } else {
                    err = mOMX->allocateBufferWithBackup(
                            mNode, portIndex, mem, &buffer);
                }
            } else {
                err = mOMX->useBuffer(mNode, portIndex, mem, &buffer);
            }
    
            if (err != OK) {
                ALOGE("allocate_buffer_with_backup failed");
                return err;
            }
    
            if (mem != NULL) {
                info.mData = mem->pointer();
            }
    
            info.mBuffer = buffer;
            info.mStatus = OWNED_BY_US;
            info.mMem = mem;
            info.mMediaBuffer = NULL;
    
            if (portIndex == kPortIndexOutput) {
                if (!(mOMXLivesLocally
                            && (mQuirks & kRequiresAllocateBufferOnOutputPorts)
                            && (mQuirks & kDefersOutputBufferAllocation))) {
                    // If the node does not fill in the buffer ptr at this time,
                    // we will defer creating the MediaBuffer until receiving
                    // the first FILL_BUFFER_DONE notification instead.
                    info.mMediaBuffer = new MediaBuffer(info.mData, info.mSize);
                    info.mMediaBuffer->setObserver(this);
                }
            }
    
            mPortBuffers[portIndex].push(info);
    
            CODEC_LOGV("allocated buffer %p on %s port", buffer,
                 portIndex == kPortIndexInput ? "input" : "output");
        }
    
        if (portIndex == kPortIndexOutput) {
    
            sp<MetaData> meta = mSource->getFormat();
            int32_t delay = 0;
            if (!meta->findInt32(kKeyEncoderDelay, &delay)) {
                delay = 0;
            }
            int32_t padding = 0;
            if (!meta->findInt32(kKeyEncoderPadding, &padding)) {
                padding = 0;
            }
            int32_t numchannels = 0;
            if (delay + padding) {
                if (mOutputFormat->findInt32(kKeyChannelCount, &numchannels)) {
                    size_t frameSize = numchannels * sizeof(int16_t);
                    if (mSkipCutBuffer != NULL) {
                        size_t prevbuffersize = mSkipCutBuffer->size();
                        if (prevbuffersize != 0) {
                            ALOGW("Replacing SkipCutBuffer holding %d bytes", prevbuffersize);
                        }
                    }
                    mSkipCutBuffer = new SkipCutBuffer(delay * frameSize, padding * frameSize);
                }
            }
        }
    
        // dumpPortStatus(portIndex);
    
        if (portIndex == kPortIndexInput && (mFlags & kUseSecureInputBuffers)) {
            Vector<MediaBuffer *> buffers;
            for (size_t i = 0; i < def.nBufferCountActual; ++i) {
                const BufferInfo &info = mPortBuffers[kPortIndexInput].itemAt(i);
    
                MediaBuffer *mbuf = new MediaBuffer(info.mData, info.mSize);
                buffers.push(mbuf);
            }
    
            status_t err = mSource->setBuffers(buffers);
    
            if (err != OK) {
                for (size_t i = 0; i < def.nBufferCountActual; ++i) {
                    buffers.editItemAt(i)->release();
                }
                buffers.clear();
    
                CODEC_LOGE(
                        "Codec requested to use secure input buffers but "
                        "upstream source didn't support that.");
    
                return err;
            }
        }
    
        return OK;
    }

        这个数函挺主要的,omx node是通过port来通信的,inport和output,入输node只有inport,而输出node就只有outport,间中码解的node就要需两个port

        先看inport的内存分配,有两个数函 allocatebuffer 和 usebuffer,如果不要需node重新分配内存,那就只要需用使application分配的内存,否则会在port面上重新分配内存

        为什么要需再port面上重新分配内存呢,多是DRM等原因虑考。

        在看一下outport的分配

    {
        // Get the number of buffers needed.
        OMX_PARAM_PORTDEFINITIONTYPE def;
        InitOMXParams(&def);
        def.nPortIndex = kPortIndexOutput;
    
        status_t err = mOMX->getParameter(
                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
        if (err != OK) {
            return err;
        }
    
        err = native_window_set_buffers_geometry(
                mNativeWindow.get(),
                def.format.video.nFrameWidth,
                def.format.video.nFrameHeight,
                def.format.video.eColorFormat);
    
        if (err != 0) {
            ALOGE("native_window_set_buffers_geometry failed: %s (%d)",
                    strerror(-err), -err);
            return err;
        }
        initNativeWindowCrop();
        err = applyRotation();
        if (err != OK) {
            return err;
        }
    
        // Set up the native window.
        OMX_U32 usage = 0;
        err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage);
        if (err != 0) {
            ALOGW("querying usage flags from OMX IL component failed: %d", err);
            // XXX: Currently this error is logged, but not fatal.
            usage = 0;
        }
        if (mFlags & kEnableGrallocUsageProtected) {
            usage |= GRALLOC_USAGE_PROTECTED;
        }
    
        // Make sure to check whether either Stagefright or the video decoder
        // requested protected buffers.
        if (usage & GRALLOC_USAGE_PROTECTED) {
            // Verify that the ANativeWindow sends images directly to
            // SurfaceFlinger.
            int queuesToNativeWindow = 0;
            err = mNativeWindow->query(
                    mNativeWindow.get(), NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER,
                    &queuesToNativeWindow);
            if (err != 0) {
                ALOGE("error authenticating native window: %d", err);
                return err;
            }
            if (queuesToNativeWindow != 1) {
                ALOGE("native window could not be authenticated");
                return PERMISSION_DENIED;
            }
        }
    
        ALOGV("native_window_set_usage usage=0x%lx", usage);
    
        /* all commons */
        usage |= (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
    
        ALOGV("native_window_set_usage usage=0x%lx", usage);
        err = native_window_set_usage(
                mNativeWindow.get(), usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
        if (err != 0) {
            ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err);
            return err;
        }
        int minUndequeuedBufs = 0;
        err = mNativeWindow->query(mNativeWindow.get(),
                NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs);
        if (err != 0) {
            ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
                    strerror(-err), -err);
            return err;
        }
    
        // XXX: Is this the right logic to use?  It's not clear to me what the OMX
        // buffer counts refer to - how do they account for the renderer holding on
        // to buffers?
        if (def.nBufferCountActual < def.nBufferCountMin + minUndequeuedBufs) {
            OMX_U32 newBufferCount = def.nBufferCountMin + minUndequeuedBufs;
            def.nBufferCountActual = newBufferCount;
            err = mOMX->setParameter(
                    mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
            if (err != OK) {
                CODEC_LOGE("setting nBufferCountActual to %lu failed: %d",
                        newBufferCount, err);
                return err;
            }
        }
    
        err = native_window_set_buffer_count(
                mNativeWindow.get(), def.nBufferCountActual);
        if (err != 0) {
            ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
                    -err);
            return err;
        }
    
        CODEC_LOGV("allocating %lu buffers from a native window of size %lu on "
                "output port", def.nBufferCountActual, def.nBufferSize);
    
        // Dequeue buffers and send them to OMX
        for (OMX_U32 i = 0; i < def.nBufferCountActual; i++) {
            ANativeWindowBuffer* buf;
            err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf);
            if (err != 0) {
                ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
                break;
            }
    
            sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
            BufferInfo info;
            info.mData = NULL;
            info.mSize = def.nBufferSize;
            info.mStatus = OWNED_BY_US;
            info.mMem = NULL;
            info.mMediaBuffer = new MediaBuffer(graphicBuffer);
            info.mMediaBuffer->setObserver(this);
            mPortBuffers[kPortIndexOutput].push(info);
    
            IOMX::buffer_id bufferId;
            err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer,
                    &bufferId);
            if (err != 0) {
                CODEC_LOGE("registering GraphicBuffer with OMX IL component "
                        "failed: %d", err);
                break;
            }
    
            mPortBuffers[kPortIndexOutput].editItemAt(i).mBuffer = bufferId;
    
            CODEC_LOGV("registered graphic buffer with ID %p (pointer = %p)",
                    bufferId, graphicBuffer.get());
        }
    
        OMX_U32 cancelStart;
        OMX_U32 cancelEnd;
        if (err != 0) {
            // If an error occurred while dequeuing we need to cancel any buffers
            // that were dequeued.
            cancelStart = 0;
            cancelEnd = mPortBuffers[kPortIndexOutput].size();
        } else {
            // Return the last two buffers to the native window.
            cancelStart = def.nBufferCountActual - minUndequeuedBufs;
            cancelEnd = def.nBufferCountActual;
        }
    
        for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
            BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(i);
            cancelBufferToNativeWindow(info);
        }
    
        return err;
    }

        start的预备也做完了,主要是给port分配内存,基本也只是摘抄代码了

        start当前,就要kick off了,下篇开始播放了

        

        

    文章结束给大家分享下程序员的一些笑话语录: IT业众生相
    第一级:神人,天资过人而又是技术狂热者同时还拥有过人的商业头脑,高瞻远瞩,技术过人,大器也。如丁磊,求伯君。
    第二级:高人,有天赋,技术过人但没有过人的商业头脑,通常此类人不是顶尖黑客就是技术总监之流。
    第三级:牛人,技术精湛,熟悉行业知识,敢于创新,有自己的公司和软件产品。
    第四级:工头,技术精湛,有领导团队的能力,此类人大公司项目经理居多。
    第五级:技术工人,技术精湛,熟悉行业知识但领导能力欠加,此类人大多为系分人员或资深程序员,基本上桀骜不逊,自视清高,不愿于一般技术人员为伍,在论坛上基本以高手面目出现。
    第六级:熟练工人,技术有广度无深度,喜欢钻研但浅尝辄止。此类人大多为老程序员,其中一部分喜欢利用工具去查找网上有漏洞的服务器,干点坏事以获取成绩感。如果心情好,在论坛上他们会回答菜鸟的大部分问题。此级别为软件业苦力的重要组成部分。
    第七级:工人,某些技术较熟练但缺乏深度和广度,此类人大多为程序员级别,经常在论坛上提问偶尔也回答菜鸟的问题。为软件产业苦力的主要组成部分。
    第八级:菜鸟,入门时间不长,在论坛上会反复提问很初级的问题,有一种唐僧的精神。虽然招人烦但基本很可爱。只要认真钻研,一两年后就能升级到上一层。
    第九级:大忽悠,利用中国教育的弊病,顶着一顶高学历的帽子,在小公司里混个软件部经理,设计不行,代码不行,只会胡乱支配下属,拍领导马屁,在领导面前胡吹海侃,把自己打扮成技术高手的模样。把勾心斗角的办公室文化引入技术部门,实在龌龊!
    第十级:驴或傻X,会写SELECT语句就说自己精通ORALCE,连寄存器有几种都不知道就说自己懂汇编,建议全部送到日本当IT产业工人,挣了日本人的钱还严重打击日本的软件业!

  • 相关阅读:
    [转]手把手硬件电路详细设计过程
    虚拟机检测技术攻防
    TTL电平和CMOS电平总结
    每个程序员都应注意的9种反面模式
    优化Laravel网站打开速度
    如何在 PHP 中处理 Protocol Buffers 数据
    日请求亿级的 QQ 会员 AMS 平台 PHP7 升级实践
    跨境电商国际物流模式
    2016跨境电商五大物流模式盘点
    10个值得深思的PHP面试问题
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3023060.html
Copyright © 2011-2022 走看看