Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/264.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# FFmpeg,通过Unity运行时av_frame_free上的访问冲突_C#_C++_Unity3d_Memory Leaks_Ffmpeg - Fatal编程技术网

C# FFmpeg,通过Unity运行时av_frame_free上的访问冲突

C# FFmpeg,通过Unity运行时av_frame_free上的访问冲突,c#,c++,unity3d,memory-leaks,ffmpeg,C#,C++,Unity3d,Memory Leaks,Ffmpeg,我正在使用ffmpeg为Unity开发一个视频录制插件。我是视频编码领域的新手,今天刚开始使用我的代码。但我认为a可能有一些内存泄漏,并试图修复它们 插件是用C++编写的(作为外部的C代码),并在一个C语言脚本中导入一个简单的DLIMPOLT。再说一次,这也不是我的舒适区,但它很有效 当呈现一个屏幕缓冲区时,我放进一个RGB24缓冲区并将其发送给我的C++函数,这个函数: int encode_frame(uint8_t* rgb24Data) { AVFrame *frame = av

我正在使用ffmpeg为Unity开发一个视频录制插件。我是视频编码领域的新手,今天刚开始使用我的代码。但我认为a可能有一些内存泄漏,并试图修复它们

插件是用C++编写的(作为外部的C代码),并在一个C语言脚本中导入一个简单的DLIMPOLT。再说一次,这也不是我的舒适区,但它很有效

当呈现一个屏幕缓冲区时,我放进一个RGB24缓冲区并将其发送给我的C++函数,这个函数:

int encode_frame(uint8_t* rgb24Data)
{
    AVFrame *frame = av_frame_alloc();
    if (!frame)
        return COULD_NOT_ALLOCATE_FRAME;

    frame->format = codec_context->pix_fmt;
    frame->width = codec_context->width;
    frame->height = codec_context->height;

    int ret = av_image_alloc(frame->data, frame->linesize, codec_context->width, codec_context->height, codec_context->pix_fmt, 32);
    if (ret < 0)
        return COULD_NOT_ALLOCATE_PIC_BUF;

    SwsContext * ctx = sws_getContext(codec_context->width, codec_context->height,
        AV_PIX_FMT_RGB24, codec_context->width, codec_context->height,
        AV_PIX_FMT_YUV420P, 0, 0, 0, 0);


    uint8_t * inData[1] = { rgb24Data };
    int inLinesize[1] = { 3 * codec_context->width };

    sws_scale(ctx, inData, inLinesize, 0, codec_context->height, frame->data, frame->linesize); // From RGB to YUV

    frame->pts = frame_counter++;

    ret = avcodec_send_frame(codec_context, frame);
    if (ret < 0)
        return ERROR_ENCODING_FRAME_SEND;

    AVPacket pkt;
    av_init_packet(&pkt);
    pkt.data = NULL;
    pkt.size = 0;

    while (true)
    {
        ret = avcodec_receive_packet(codec_context, &pkt);
        if (!ret)
        {
            if (pkt.pts != AV_NOPTS_VALUE)
                pkt.pts = av_rescale_q(pkt.pts, codec_context->time_base, video_st->time_base);
            if (pkt.dts != AV_NOPTS_VALUE)
                pkt.dts = av_rescale_q(pkt.dts, codec_context->time_base, video_st->time_base);

            av_write_frame(outctx, &pkt);
            av_packet_unref(&pkt);
        }
        else if (ret == AVERROR(EAGAIN))
        {
            frame->pts = frame_counter++;
            ret = avcodec_send_frame(codec_context, frame);
            if (ret < 0)
                return ERROR_ENCODING_FRAME_SEND;
        }
        else if (ret < 0)
            return ERROR_ENCODING_FRAME_RECEIVE;
        else
            break;
    }

    // This one
    av_frame_free(&frame);
}
int编码帧(uint8*rgb24Data)
{
AVFrame*frame=av_frame_alloc();
如果(!帧)
返回无法分配帧;
帧->格式=编解码器\u上下文->pix\u fmt;
帧->宽度=编解码器上下文->宽度;
帧->高度=编解码器上下文->高度;
int-ret=av_-image_-alloc(帧->数据,帧->线宽,编解码器上下文->宽度,编解码器上下文->高度,编解码器上下文->pix_fmt,32);
如果(ret<0)
返回不能分配图片;
SwsContext*ctx=sws\u getContext(编解码器上下文->宽度,编解码器上下文->高度,
AV_PIX_FMT_RGB24,编解码器上下文->宽度,编解码器上下文->高度,
AV_PIX_FMT_YUV420P,0,0,0);
uint8_t*inData[1]={rgb24Data};
int inLinesize[1]={3*codec_context->width};
sws_比例(ctx、inData、inLinesize、0、编解码器_上下文->高度、帧->数据、帧->线宽);//从RGB到YUV
frame->pts=frame_counter++;
ret=avcodec\u发送\u帧(codec\u上下文,帧);
如果(ret<0)
返回错误\u编码\u帧\u发送;
AVPacket-pkt;
av_初始_数据包(&pkt);
pkt.data=NULL;
pkt.size=0;
while(true)
{
ret=avcodec\u receive\u数据包(codec\u上下文和pkt);
如果(!ret)
{
如果(pkt.pts!=平均值)
pkt.pts=av_rescale_q(pkt.pts,编解码器上下文->时基,视频->时基);
如果(pkt.dts!=平均值)
pkt.dts=av_rescale_q(pkt.dts,编解码器上下文->时基,视频->时基);
av写入帧(outctx和pkt);
av_数据包_unref(&pkt);
}
else if(ret==averor(EAGAIN))
{
frame->pts=frame_counter++;
ret=avcodec\u发送\u帧(codec\u上下文,帧);
如果(ret<0)
返回错误\u编码\u帧\u发送;
}
否则如果(ret<0)
返回错误\u编码\u帧\u接收;
其他的
打破
}
//这个
av_无帧(&帧);
}
现在,这段代码可能有很多我不知道的问题,如果您愿意,您可以自由地指出它们。但给出错误的行是
av\u frame\u free(&frame)

如果我用C++编写的合成测试应用程序运行,它就可以工作了。我甚至可以用C语言合成测试程序(就像C++一样)运行,它是有效的。但是如果我通过Unity运行它,它会在第一帧崩溃。日志显示“从位置fe7f8097读取导致访问冲突。”

我试过使用
av\u freep()
av\u free()
。不确定到底是什么使它们不同(不同的示例代码使用不同的代码),但都不起作用

那么,我错过了什么?如果我没有正确释放
框架
会泄漏吗?但为什么它会在统一中崩溃呢

如果我没有
av\u-frame\u-free(&frame),那么整件事在统一中工作得非常好。结果视频看起来很棒


另外,据我所知,如果出现故障并返回错误代码,帧也会泄漏。但每次只做一件事。

出于某种原因,您对同一帧进行了多次编码-这似乎是错误的,但不应导致崩溃。我看不出这个代码还有什么问题。作为一个无害的想法-尝试使用
av\u frame\u get\u buffer
而不是
av\u image\u alloc
,也许会有所帮助;“AVERROR(EAGAIN)返回值表示需要新的输入数据才能返回新的输出。在这种情况下,继续发送输入”。我应该一次发送更多的帧。呃,不。这只是意味着到目前为止编码器必须提供的一切都得到了。您应该在有新帧时继续发送它们,而不是重新发送您已经发送的帧。此函数中应该只有一个
avcodec\u send\u frame
调用。谢谢!我没有意识到我看错了。我现在已经修复了它,问题可能是在编码完成之前,
数据还没有准备好发布。因为当我重用
对象,并且仅在编码完成后才取消分配它时(
avcodec\u receive\u packet89()
返回
NULL
),它工作了!根据文件,情况不应该如此;但至少有一个编码器有一个错误与非refcounted数据(h264_qsv)。因此,我建议使用
av\u frame\u get\u buffer
——这将使您的图像数据重新计数,并与
frame
对象更不耦合;这也可能让一切变得更快。