实现FFMPEG 使用CUDA解码播放

播放器使用ffmpeg读取视频文件,packet发给cuda解码,解码后OpenGL直接映射给pbo,pbo绑定texture,然后显示出来

流程读取文件,判断packet,丢到CUDA那

if (av_read_frame(m_pFormatContext, &packet) >= 0)
        {
            if (packet.stream_index == m_VideoStreamIndex)
            {

                if (m_UseGPUDecode)
                {
                    //MiniConsole::getInstance().Output("ThreadDecodeVideoGPU begin  
");
                    ThreadDecodeVideoGPU(packet);

                    //MiniConsole::getInstance().Output("ThreadDecodeVideoGPU  end 
");
                }
                else
                {
                    ThreadDecodeVideoCPU(packet);
                }
                
            }
            else if (packet.stream_index == m_AudioStreamIndex)
            {

                ThreadDecodeAudio(packet);
            }
            else
            {
                av_free_packet(&packet);
            }
        }

 数据丢给cuvidParseVideoData

CUVIDSOURCEDATAPACKET cudaPkt;
    CUresult oResult;
    if (pData == NULL)
    {
        cudaPkt.flags = CUVID_PKT_ENDOFSTREAM; //end of stream
    }
    else
    {
        cudaPkt.flags = CUVID_PKT_TIMESTAMP;
    }
    cudaPkt.payload_size = (unsigned long)nSize;
    cudaPkt.payload = (const unsigned char*)pData;

    cudaPkt.timestamp = packpts;

    cuCtxPushCurrent(m_cudaResPtr->m_CuContext);

    
    oResult = cuvidParseVideoData(m_CuVideoParser, &cudaPkt);
    

    if ((cudaPkt.flags & CUVID_PKT_ENDOFSTREAM) || (oResult != CUDA_SUCCESS))
    {
        checkCudaErrors(cuCtxPopCurrent(NULL));
        return false;
    }
    
    //printf("Succeed to read avpkt %d !
", iPkt);
    checkCudaErrors(cuCtxPopCurrent(NULL));

然后数据到

HandlePictureDecode(CUVIDPICPARAMS *pPicParams)  发送解码

HandlePictureDisplay(CUVIDPARSERDISPINFO *pDispInfo)  GPU解码结束发送到这里,存起来

然后映射pbo ,map texture就到纹理上了,就可以绘制了

这个4k x60fps的,如果CPU解码cpu使用率100%都会卡顿

这个8k的视频,CPU解码无法播放

原文地址:https://www.cnblogs.com/dragon2012/p/12371403.html