我正在使用ffmpeg为Unity制作视频录制插件。我是视频编码领域的新手,今天就让我的代码工作了。但我认为可能有一些内存泄漏并试图修复它们会导致Unity崩溃。
该插件是用c ++编写的(作为外部“C”代码),并通过简单的DllImport以c#脚本统一导入。同样,这也不是我的舒适区域,但它确实有效。
当渲染一个屏幕缓冲区时,我放入一个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);
}
现在,这段代码可能有很多我不知道的问题,如果你愿意,可以自由指出它们。但是给我错误的行是av_frame_free(&frame);
。
如果我在c ++中的合成测试应用程序中运行它,它就可以了。我甚至可以在一个c#综合测试应用程序中运行它(就像c ++一样),它可以工作。但如果我通过Unity运行它,它会在第一帧崩溃。日志显示“从位置fe7f8097读取导致访问冲突。”。
我尝试过使用av_freep()
和av_free()
。不确定究竟是什么使它们不同(不同的示例代码使用不同的代码),但都没有效果。
那么,我错过了什么? frame
如果我没有正确释放它会泄漏吗?但为什么它会在Unity中崩溃?
如果我没有av_frame_free(&frame);
,整个过程在Unity中运行良好。结果视频看起来很棒!
PS。我知道(据我所知)如果出现故障并且返回错误代码,框架也会泄漏。但有一点是一次。