本帖最后由 fuliangjun 于 2017-12-16 23:06 编辑  
 
最近在做FFMPEG硬解码的一些东西的时候遇到了一个问题:  
        我在GPU解码完之后,在dxva2_retrieve_data里把解码后的数据取回CPU,开始刚弄完的时候运行都没问题,可是我把视频解码改成在线程里运行,然后创建了很多个线程同时解码多个视频时,就遇到问题了。 
每多创建一个线程解码视频,应用程序的占用内存就会增加一点,开了大概30个线程的时候,占用的内存就达到了4G(每个视频解码的分辨率都调得很低,大概128*128左右) 
然后最大的问题是 视频解码完以后把该释放的变量都释放了,然后关闭线程,内存不会释放! 
然后继续加线程解码,内存就会不停的增加。。。(解码的过程中内存不会有很大变化,没有出现边解码边加内存的情况),下面是我dxva2_retrieve_data函数 
 
static int dxva2_retrieve_data(AVCodecContext *s, AVFrame *frame) 
{ 
        LPDIRECT3DSURFACE9 surface = (LPDIRECT3DSURFACE9)frame->data[3]; 
        InputStream                *ist = (InputStream *)s->opaque; 
        DXVA2Context            *ctx = (DXVA2Context *)ist->hwaccel_ctx; 
        D3DSURFACE_DESC    surfaceDesc; 
        D3DLOCKED_RECT      LockedRect; 
        HRESULT                     hr; 
        int                               ret; 
                 
        IDirect3DSurface9_GetDesc(surface, &surfaceDesc); 
                 
        ctx->tmp_frame->width = frame->width; 
        ctx->tmp_frame->height = frame->height; 
        ctx->tmp_frame->format = AV_PIX_FMT_NV12; 
 
        ret = av_frame_get_buffer(ctx->tmp_frame, 32); 
        if (ret < 0) 
            return ret; 
 
                //*param Pointer to a D3DLOCKED_RECT structure that describes the locked region. 
                //*param Pointer to a rectangle to lock. Specified by a pointer to a RECT structure. Specifying NULL for this parameter expands the dirty region to cover the entire surface. 
        hr = surface->LockRect(&LockedRect, NULL, D3DLOCK_READONLY);//获取指向surface存储区的指针,调试过程中发现执行了这一步 就会出现占用内存增加而且不释放的问题 
        if (FAILED(hr)) { 
            av_log(NULL, AV_LOG_ERROR, "Unable to lock DXVA2 surface\n"); 
            return AVERROR_UNKNOWN; 
        } 
         
                av_image_copy_plane(ctx->tmp_frame->data[0], ctx->tmp_frame->linesize[0], 
            (uint8_t*)LockedRect.pBits, 
            LockedRect.Pitch, frame->width, frame->height); 
 
                av_image_copy_plane(ctx->tmp_frame->data[1], ctx->tmp_frame->linesize[1], 
            (uint8_t*)LockedRect.pBits + LockedRect.Pitch * surfaceDesc.Height, 
            LockedRect.Pitch, frame->width, frame->height / 2); 
                 
        surface->UnlockRect(); 
 
        ret = av_frame_copy_props(ctx->tmp_frame, frame); 
        if (ret < 0) 
            goto fail; 
 
        av_frame_unref(frame); 
        av_frame_move_ref(frame, ctx->tmp_frame); 
                 
        return 0; 
    fail: 
        av_frame_unref(ctx->tmp_frame); 
        return ret; 
                 
    } 
 
 
并且,我如果改成软解码的话,就不会有内存的问题,而且我调试之后发现 : 就是执行 LockRect 的时候 内存才开始加的。 
 
 
我是最近才接触视频解码的东西,对DXVA和FFMPEG都还不是很熟,求大佬帮忙~ 
如果不能解决的话,能给个有效的从GPU取回数据的方法或者教我直接把解码后的图渲染到UE的Texture2d上也行~  
 
---------------------------------------------------------------------- 
问题已经解决了~  
原因其实不在这,还是解码完成后 释放内存的操作有问题,内存占用这么多是正常的,今天来论坛看看突然想起这个帖子,就上来改一下。 
 
 
 
 |