当前位置: 首页 > news >正文

Vulkan视频解码decode显示display之同步

在ReleaseDisplayedPicture函数中消耗图片资源并且显示display完成,设置两个标志m_hasConsummerSignalFence = true 和m_hasConsummerSignalSemaphore = true
    virtual int32_t ReleaseDisplayedPicture(DecodedFrameRelease** pDecodedFramesRelease, uint32_t numFramesToRelease)
    {
        std::lock_guard<std::mutex> lock(m_displayQueueMutex);
        for (uint32_t i = 0; i < numFramesToRelease; i++) {
            const DecodedFrameRelease* pDecodedFrameRelease = pDecodedFramesRelease[i];
            int picId = pDecodedFrameRelease->pictureIndex;
            assert((picId >= 0) && ((uint32_t)picId < m_perFrameDecodeImageSet.size()));

            assert(m_perFrameDecodeImageSet[picId].m_decodeOrder == pDecodedFrameRelease->decodeOrder);
            assert(m_perFrameDecodeImageSet[picId].m_displayOrder == pDecodedFrameRelease->displayOrder);

            assert(m_ownedByDisplayMask & (1 << picId));
            m_ownedByDisplayMask &= ~(1 << picId);
            m_perFrameDecodeImageSet[picId].m_inDecodeQueue = false;
            m_perFrameDecodeImageSet[picId].m_ownedByConsummer = false;
            m_perFrameDecodeImageSet[picId].Release();

            m_perFrameDecodeImageSet[picId].m_hasConsummerSignalFence = pDecodedFrameRelease->hasConsummerSignalFence;
            m_perFrameDecodeImageSet[picId].m_hasConsummerSignalSemaphore = pDecodedFrameRelease->hasConsummerSignalSemaphore;

        }
        return 0;
    }

ReleaseDisplayedPicture被ReleaseFrame调用,pLastDecodedFrame就是当前已经解码的帧

.....................................

        m_videoQueue->ReleaseFrame(pLastDecodedFrame);

        pLastDecodedFrame->Reset();

        bool endOfStream = false;
        int32_t numVideoFrames = 0;

        numVideoFrames = m_videoQueue->GetNextFrame(pLastDecodedFrame, &endOfStream);

.............................................

//-----------------------------------------------------------------------

这两个标志一旦设置为true,在QueuePictureForDecode函数中,将设置pFrameSynchronizationInfo->frameConsumerDoneFence和 pFrameSynchronizationInfo->frameConsumerDoneSemaphore,返回后使用,同时重置两个标志为false

    virtual int32_t QueuePictureForDecode(int8_t picId, VkParserDecodePictureInfo* pDecodePictureInfo,
                                          ReferencedObjectsInfo* pReferencedObjectsInfo,
                                          FrameSynchronizationInfo* pFrameSynchronizationInfo)
    {
        if (pFrameSynchronizationInfo->hasFrameCompleteSignalFence) {
            pFrameSynchronizationInfo->frameCompleteFence = m_perFrameDecodeImageSet[picId].m_frameCompleteFence;
            if (pFrameSynchronizationInfo->frameCompleteFence) {
                m_perFrameDecodeImageSet[picId].m_hasFrameCompleteSignalFence = true;
            }
        }

        if (m_perFrameDecodeImageSet[picId].m_hasConsummerSignalFence) {
            pFrameSynchronizationInfo->frameConsumerDoneFence = m_perFrameDecodeImageSet[picId].m_frameConsumerDoneFence;
            m_perFrameDecodeImageSet[picId].m_hasConsummerSignalFence = false;
        }

        if (pFrameSynchronizationInfo->hasFrameCompleteSignalSemaphore) {
            pFrameSynchronizationInfo->frameCompleteSemaphore = m_perFrameDecodeImageSet[picId].m_frameCompleteSemaphore;
            if (pFrameSynchronizationInfo->frameCompleteSemaphore) {
                m_perFrameDecodeImageSet[picId].m_hasFrameCompleteSignalSemaphore = true;
            }
        }

        if (m_perFrameDecodeImageSet[picId].m_hasConsummerSignalSemaphore) {
            pFrameSynchronizationInfo->frameConsumerDoneSemaphore = m_perFrameDecodeImageSet[picId].m_frameConsumerDoneSemaphore;
            m_perFrameDecodeImageSet[picId].m_hasConsummerSignalSemaphore = false;
        }
.................

}

返回后如何使用pFrameSynchronizationInfo->frameConsumerDoneFence和 pFrameSynchronizationInfo->frameConsumerDoneSemaphore,代码如下:

    VkFence frameCompleteFence = frameSynchronizationInfo.frameCompleteFence;
    VkSemaphore frameCompleteSemaphore = frameSynchronizationInfo.frameCompleteSemaphore;
    VkSemaphore frameConsumerDoneSemaphore = frameSynchronizationInfo.frameConsumerDoneSemaphore;

    uint32_t waitSemaphoreCount = 0;
    if (frameConsumerDoneSemaphore != VK_NULL_HANDLE) {
       
waitSemaphores[waitSemaphoreCount] = frameConsumerDoneSemaphore;
        waitSemaphoreCount++;
    }

    VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO, nullptr };
    const VkPipelineStageFlags videoDecodeSubmitWaitStages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
    submitInfo.pNext = (m_hwLoadBalancingTimelineSemaphore != VK_NULL_HANDLE) ? &timelineSemaphoreInfos : nullptr;
    submitInfo.waitSemaphoreCount = waitSemaphoreCount;
    submitInfo.pWaitSemaphores = waitSemaphores;
    submitInfo.pWaitDstStageMask = &videoDecodeSubmitWaitStages;
    submitInfo.commandBufferCount = 1;
    submitInfo.pCommandBuffers = &frameDataSlot.commandBuffer;
    submitInfo.signalSemaphoreCount = signalSemaphoreCount;
    submitInfo.pSignalSemaphores = signalSemaphores;

    assert(VK_NOT_READY == m_vkDevCtx->GetFenceStatus(*m_vkDevCtx, videoDecodeCompleteFence));
    VkResult result = m_vkDevCtx->MultiThreadedQueueSubmit(VulkanDeviceContext::DECODE, m_currentVideoQueueIndx,
                                                           1, &submitInfo, videoDecodeCompleteFence);

拷贝pictureIndex视频帧,并进行等待解码完成并且设置显示完成信号

    virtual int32_t DequeueDecodedPicture(VulkanDecodedFrame* pDecodedFrame)
    {


            if (m_perFrameDecodeImageSet[pictureIndex].m_hasFrameCompleteSignalFence) {
                pDecodedFrame->frameCompleteFence = m_perFrameDecodeImageSet[pictureIndex].m_frameCompleteFence;
                m_perFrameDecodeImageSet[pictureIndex].m_hasFrameCompleteSignalFence = false;
            } else {
                pDecodedFrame->frameCompleteFence = VkFence();
            }

            if (m_perFrameDecodeImageSet[pictureIndex].m_hasFrameCompleteSignalSemaphore) {
                pDecodedFrame->frameCompleteSemaphore = m_perFrameDecodeImageSet[pictureIndex].m_frameCompleteSemaphore;
                m_perFrameDecodeImageSet[pictureIndex].m_hasFrameCompleteSignalSemaphore = false;
            } else {
                pDecodedFrame->frameCompleteSemaphore = VkSemaphore();
            }

            pDecodedFrame->frameConsumerDoneFence = m_perFrameDecodeImageSet[pictureIndex].m_frameConsumerDoneFence;
            pDecodedFrame->frameConsumerDoneSemaphore = m_perFrameDecodeImageSet[pictureIndex].m_frameConsumerDoneSemaphore;

            pDecodedFrame->timestamp = m_perFrameDecodeImageSet[pictureIndex].m_timestamp;
            pDecodedFrame->decodeOrder = m_perFrameDecodeImageSet[pictureIndex].m_decodeOrder;
            pDecodedFrame->displayOrder = m_perFrameDecodeImageSet[pictureIndex].m_displayOrder;

            pDecodedFrame->queryPool = m_queryPool;
            pDecodedFrame->startQueryId = pictureIndex;
            pDecodedFrame->numQueries = 1;

}

//pDecodedFrame传递给DrawFrame最后一个参数pLastDecodedFrame

    VkResult result = DrawFrame(renderIndex,
                                waitSemaphoreCount,
                                pWaitSemaphores,
                                signalSemaphoreCount,
                                pSignalSemaphores,
                                pLastDecodedFrame)

VkResult VulkanFrame<FrameDataType>::DrawFrame( int32_t            renderIndex,
                                                uint32_t           waitSemaphoreCount,
                                                const VkSemaphore* pWaitSemaphores,
                                                uint32_t           signalSemaphoreCount,
                                                const VkSemaphore* pSignalSemaphores,
                                                FrameDataType*     inFrame)

{


    const uint32_t maxWaitSemaphores = 2;
    uint32_t numWaitSemaphores = 0;
    VkSemaphore waitSemaphores[maxWaitSemaphores] = {};

    assert(waitSemaphoreCount <= 1);
    if ((waitSemaphoreCount > 0) && (pWaitSemaphores != nullptr)) {

//这个是等待上一次present完成
        waitSemaphores[numWaitSemaphores++] = *pWaitSemaphores;
    }

    if (inFrame && (inFrame->frameCompleteSemaphore != VkSemaphore())) {

//等待解码完成信号
        waitSemaphores[numWaitSemaphores++] = inFrame->frameCompleteSemaphore;
    }
    assert(numWaitSemaphores <= maxWaitSemaphores);

    const uint32_t maxSignalSemaphores = 2;
    uint32_t numSignalSemaphores = 0;
    VkSemaphore signalSemaphores[maxSignalSemaphores] = {};

    assert(signalSemaphoreCount <= 1);
    if ((signalSemaphoreCount > 0) && (pSignalSemaphores != nullptr)) {
        signalSemaphores[numSignalSemaphores++] = *pSignalSemaphores;
    }

    if (inFrame && (inFrame->frameConsumerDoneSemaphore != VkSemaphore())) {

//显示完成消费信号激活,这样这个图片资源才能被用来继续解码新视频帧,解码函数中需要等待这个frameConsumerDoneSemaphore有信号才能使用这个图片资源解码
        signalSemaphores[numSignalSemaphores++] = inFrame->frameConsumerDoneSemaphore;
        inFrame->hasConsummerSignalSemaphore = true;
    }
    assert(numSignalSemaphores <= maxSignalSemaphores);

    if (frameConsumerDoneFence != VkFence()) {
        inFrame->hasConsummerSignalFence = true;
    }


    // Wait for the image to be owned and signal for render completion
    VkPipelineStageFlags primaryCmdSubmitWaitStages[2] = { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
                                                           VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT };
    VkSubmitInfo primaryCmdSubmitInfo = VkSubmitInfo();
    primaryCmdSubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
    primaryCmdSubmitInfo.pWaitDstStageMask = primaryCmdSubmitWaitStages;
    primaryCmdSubmitInfo.commandBufferCount = 1;

    primaryCmdSubmitInfo.waitSemaphoreCount = numWaitSemaphores;
    primaryCmdSubmitInfo.pWaitSemaphores = numWaitSemaphores ? waitSemaphores : NULL;
    primaryCmdSubmitInfo.pCommandBuffers = pPerDrawContext->commandBuffer.GetCommandBuffer();

    primaryCmdSubmitInfo.signalSemaphoreCount = numSignalSemaphores;
    primaryCmdSubmitInfo.pSignalSemaphores = numSignalSemaphores ? signalSemaphores : NULL;

    // For fence/sync debugging
    if (false && inFrame && inFrame->frameCompleteFence) {
        result = m_vkDevCtx->WaitForFences(*m_vkDevCtx, 1, &inFrame->frameCompleteFence, true, 100 * 1000 * 1000);
        assert(result == VK_SUCCESS);
        if (result != VK_SUCCESS) {
            fprintf(stderr, "\nERROR: WaitForFences() result: 0x%x\n", result);
        }
        result = m_vkDevCtx->GetFenceStatus(*m_vkDevCtx, inFrame->frameCompleteFence);
        assert(result == VK_SUCCESS);
        if (result != VK_SUCCESS) {
            fprintf(stderr, "\nERROR: GetFenceStatus() result: 0x%x\n", result);
        }
    }

    result = m_vkDevCtx->MultiThreadedQueueSubmit(VulkanDeviceContext::GRAPHICS, 0, 1, &primaryCmdSubmitInfo, frameConsumerDoneFence);
    if (result != VK_SUCCESS) {
        assert(result == VK_SUCCESS);
        fprintf(stderr, "\nERROR: MultiThreadedQueueSubmit() result: 0x%x\n", result);
        return result;
    }

    if (false && (frameConsumerDoneFence != VkFence())) { // For fence/sync debugging
        const uint64_t fenceTimeout = 100 * 1000 * 1000 /* 100 mSec */;
        result = m_vkDevCtx->WaitForFences(*m_vkDevCtx, 1, &frameConsumerDoneFence, true, fenceTimeout);
        assert(result == VK_SUCCESS);
        if (result != VK_SUCCESS) {
            fprintf(stderr, "\nERROR: WaitForFences() result: 0x%x\n", result);
        }
        result = m_vkDevCtx->GetFenceStatus(*m_vkDevCtx, frameConsumerDoneFence);
        assert(result == VK_SUCCESS);
        if (result != VK_SUCCESS) {
            fprintf(stderr, "\nERROR: GetFenceStatus() result: 0x%x\n", result);
        }
    }

#if 0 // for testing VK_KHR_external_fence_fd
    int fd = -1; // VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT
    const VkFenceGetFdInfoKHR getFdInfo =  { VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR, NULL, data.lastDecodedFrame.frameConsumerDoneFence, VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT};
    res = m_vkDevCtx->GetFenceFdKHR(*m_vkDevCtx, &getFdInfo, &fd);
    close(fd);
#endif

    m_frameDataIndex = (m_frameDataIndex + 1) % m_frameData.size();

    return result;

}

相关文章:

  • 贪吃蛇小游戏-简单开发版
  • 【大模型基础_毛玉仁】2.4 基于 Encoder-Decoder 架构的大语言模型
  • AI芯片设计
  • Web3到底解决了什么问题?
  • Android 数据持久化之 SharedPreferences 存储
  • 稳定运行的以Oracle数据库为数据源和目标的ETL性能变差时提高性能方法和步骤
  • 压敏电阻结构特点及选型指南
  • WebRTC中音视频服务质量QoS之RTT衡量网络往返时延的加权平均RTT计算机制‌详解
  • Spring Boot应用首次请求性能优化实战:从数据库连接池到JVM调优
  • 利用 OpenCV 库进行实时目标物体检测
  • 基于Python+SQLite实现(Web)验室设备管理系统
  • 7、基于osg引擎实现读取vtk数据通过着色器实现简单体渲染(1)
  • 服务性能防腐体系:基于自动化压测的熔断机制
  • NPM 常用操作指令大全
  • 网页制作12-html,css,javascript初认识のJavascipt脚本基础
  • 备赛蓝桥杯-Python-Day1-基础语法回顾
  • SWPU 2021 新生赛
  • 设计模式之备忘录设计模式
  • 解密乐天音乐如何通过抗指纹浏览器刷变现
  • 保持docker内容器一直运行
  • 澳大利亚首例“漂绿”诉讼开庭:能源巨头因“碳中和”承诺遭起诉
  • 押井守在30年前创造的虚拟世界何以比当下更超前?
  • 因存在安全隐患,福特公司召回约27.4万辆SUV
  • 上海市国防动员办公室副主任吴斌接受审查调查
  • 费高云不再担任安徽省人民政府副省长
  • 持续8年仍难终了的纠纷:败诉方因拒执罪被立案,胜诉方银行账户遭冻结