8

我目前正在寻找从 .NET 访问 libavutil、libavformat 和 libavcodec(FFMpeg 的所有部分)。

目前,我从每天晚上为 Windows 32 位执行的共享 FFMpeg 包的自动构建中获取库。

我也在使用ffmpeg-sharp 项目中的代码。在那个项目中,我删除了一些未编译的类(它们是包装类而不是 P/Invoke 声明)。

代码编译得很好,但我遇到了一些问题。

首先,av*.dll 的构建似乎使用了cdecl 调用约定PInvokeStackImbalanceException,因为我在尝试调用时收到了一些av_open_input_file。这很容易改变以使其正常工作。该AVFormatContext结构已填充。

之后,我想调用av_find_stream_info以获取有关文件中流的信息。但是,当使用AVFormatContext从调用中检索到的 to调用它时av_open_input_fileAccessViolationException会抛出一个表明我正在尝试从受保护的内存中读取或写入的信息。

有没有人使用 P/Invoke 通过 P/Invoke 访问 libavutil、libavformat 和 libavcodec dll 库并让它工作?

我应该提到,使用 FFMpeg 的命令行版本虽然是一种解决方案,但在这种情况下并不是一个可行的解决方案,需要通过库进行访问。这样做的原因是我不得不过多地敲打磁盘来做我需要做的事情(我必须对一些非常高清的视频进行逐帧分析)并且我想避免磁盘越多越好。

4

4 回答 4

2

这就是我想出来的——也就是说,ffmpeg-sharp 项目中的大量 P/Invoke 声明是不正确的。有很多地方在声明中使用结构,这些结构被封送回来,但随后必须传递给稍后的释放例程。

AccessViolationException因为指针作为编组的一部分已经丢失,所以当试图将该结构传递给其他接受有效指针的方法(如 Windows 中的句柄)时,这就是导致抛出的原因。他们没有将它们视为不透明的(就像 Windows API 一样),它们将结构封送回来并在过程中丢失指针。

解决方案是更改他们的 API 声明以根据需要获取/返回IntPtr并执行结构的编组,而不是将它们包含在 P/Invoke 声明中。

于 2010-09-24T19:57:12.660 回答
1

请参阅C#/.NET 和 Mono 的自动生成的 FFmpeg 包装器

于 2014-02-11T08:41:00.027 回答
0

SharpFFmpeg 导入 c++ 库。C++ 代码是非托管代码。它需要指向非托管内存的指针。“Marshal”类提供了一些分配非托管内存的方法。例如:

    IntPtr buffer = Marshal.AllocHGlobal(buf.Length + FFmpeg.FF_INPUT_BUFFER_PADDING_SIZE); //buf is a byte array

此外,如果要将托管变量(任何 C# 变量)发送到函数,则必须将此变量编组(复制)到非托管内存。

    for (int i = 0; i < buf.Length; i++)
        Marshal.StructureToPtr(buf[i], buffer + i, true);

现在您可以发送一个指向该函数的指针。

    FFmpeg.avcodec_decode_video(codecContextUnmanaged, frame, ref success, buffer, buf.Length);

您可能需要修改一些非托管结构。为此,您必须将结构复制到托管内存(Marshal.PtrToStructure 方法),然后对其进行修改,然后再次将其复制到非托管内存。
我被同样的问题折磨了很多。我解决了它,但无论如何我都无法解码视频))我希望我的解决方案能帮助任何人。

于 2011-08-30T10:54:11.163 回答
0

我已经避开了这些库/项目中的任何一个。我当时发现的所有信息都指向那些太容易被新版本破坏和/或太过时的信息。

正如我在这个答案中提到的那样,我所做的是直接运行 ffmpeg 进程,方法是修改我链接到的博客文章中的示例。到目前为止,我们还没有遇到任何问题:)

如果上述方法不适用于您的方案,祝您好运。

于 2010-09-24T19:11:14.017 回答