【问题标题】:Converting Unity texture2d to YUV420P for ffmpeg将 Unity texture2d 转换为 YUV420P 用于 ffmpeg
【发布时间】:2018-03-14 16:47:40
【问题描述】:

我正在尝试使用 FFmpeg 在 Unity 播放器中创建录像机。

我有下一个代码 sn-ps:

统一,C#:

Texture2D frameTexture = new Texture2D(frameWidth, frameHeight, TextureFormat.RGB24, false);
//...
frameTexture.ReadPixels(new Rect(0, 0, frameWidth, frameHeight), 0, 0, false);
frameTexture.Apply();
//.....
byte[] pixels = frameTexture.GetRawTextureData();
AddFrame(pixels, pixels.Length, libApi);


//DLL Function Declaration
[DllImport("VideoCapture", CallingConvention = CallingConvention.Cdecl)]
static extern void AddFrame(byte[] data, int size, System.IntPtr api);

C++ 代码:

__declspec(dllexport) void AddFrame(uint8_t *data, int size, VideoCapture *vc) {
    vc->AddFrame(data, size);
}

void VideoCapture::AddFrame(uint8_t *data, int size) {
    Log("\nAdding frame\n");

    int err;
    if (!videoFrame) {
        Log("Allocating Video Frame\n");

        videoFrame = av_frame_alloc();
        videoFrame->format = AV_PIX_FMT_YUV420P;
        videoFrame->width = cctx->width;
        videoFrame->height = cctx->height;

        if ((err = av_frame_get_buffer(videoFrame, 32)) < 0) {
            Debug("Failed to allocate picture", err);
            return;
        }
    }

    if (!swsCtx) {
        Log("Creating SWS context\n");
        swsCtx = sws_getContext(cctx->width, cctx->height, AV_PIX_FMT_RGB24, cctx->width, cctx->height, AV_PIX_FMT_YUV420P, 0, 0, 0, 0);
    }

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

    Log("Scaling data\n");
    // From RGB to YUV
    if ((err = sws_scale(swsCtx, inData, inLinesize, 0, cctx->height, videoFrame->data, videoFrame->linesize)) < 0) {
        Debug("Failed to scale img", err);
        return;
    }
    ...........

Unity 播放器在执行“sws_scale”时崩溃。

来自 Unity 的日志:

  ERROR: SymGetSymFromAddr64, GetLastError: 'Attempt to access invalid address.' (Address: 00007FF8437B49A6)
0x00007FF8437B49A6 (swscale-4) 
  ERROR: SymGetSymFromAddr64, GetLastError: 'Attempt to access invalid address.' (Address: 00007FF8437B2982)
0x00007FF8437B2982 (swscale-4) 
0x00007FF8437E78A6 (swscale-4) sws_get_class
0x00007FF8437E8E47 (swscale-4) sws_scale

我认为是因为 'sws_get_class',但如果我直接调用此函数,它就可以工作。如果我将空数据传递给'sws_scale',它也可以工作,只是抱怨它是NULL。所以,原因在于数据本身,但我不知道它有什么问题。

我也尝试将纹理编码为JPG和PNG,将数组固定到内存中,但结果没有改变。

提前致谢

UPD:::

将DLL函数调用改为

unsafe void AddFrame(byte[] data)
{
    fixed (byte* p = data)
    {
        AddFrame((IntPtr)p, data.Length, customLib);
    }
}
//Function declaration
static extern void AddFrame(IntPtr data, int size, System.IntPtr api);

但错误仍然存​​在。

【问题讨论】:

  • 您的 C# AddFrame 函数需要 3 个参数,但您的 C++ AddFrame 函数只有 2 个参数....另外,您没有固定数组。你基本上忽略了我在other 回答中所说的话。
  • @Programmer,我将所有遗漏的信息添加到主要问题中。我按照你在那个答案中所说的做了一切。
  • 即使您遇到其他问题,以后也不要删除它。如果不需要,我不会花时间写那个。至于你的问题,我真的不知道,因为我想到的大多数东西现在都被消除了,但你怎么知道问题出在sws_scale 行?
  • @Programmer 对不起。我在 sws_scale 之前和之后进行了日志记录,如果我删除此行,它不会失败(只是创建带有绿屏的空视频)
  • 但是你看到“Scaling data”之类的日志了吗?如果有,在哪里?

标签: c# c++ unity3d ffmpeg texture2d


【解决方案1】:

sws_scale 失败的原因是为sws_getContextsws_scale 传递了不正确的源高度和宽度。您应该将维度传递给 Unity 中的方法或核心值。

同样sws_scale 返回输出切片的高度,而不是错误。

【讨论】:

    猜你喜欢
    • 2018-11-19
    • 1970-01-01
    • 2014-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多