我目前正在寻求从.NET访问libavutil,libavformat和libavcodec(FFMpeg的所有部分)。
目前,我每晚都会为Windows 32位执行libraries from the automated builds of the shared FFMpeg package。
我也在使用ffmpeg-sharp project中的代码。在该项目中,我删除了许多未编译的类(它们是包装类而不是P / Invoke声明)。
代码编译得很好,但我遇到了一些问题。
首先,av * .dll的构建似乎使用cdecl calling convention,因为我在尝试呼叫av_open_input_file
时收到了一些PInvokeStackImbalanceException
。这很容易改变以使其正常工作。填充了AVFormatContext
结构。
之后,我想调用av_find_stream_info
来获取有关文件中的流的信息。但是,当调用从AVFormatContext
调用中检索到的av_open_input_file
时,会抛出AccessViolationException
,表示我正在尝试从受保护的内存中读取或写入。
是否有人使用P / Invoke通过P / Invoke访问libavutil,libavformat和libavcodec dll库并使其工作?
我应该提到使用FFMpeg的命令行版本,虽然解决方案在这种情况下不是可行的解决方案,但是需要通过库进行访问。这样做的原因是我不得不把磁盘方式过多地做我需要做的事情(我必须对一些非常高清晰度的视频进行逐帧分析)并且我想避免磁盘尽可能多。
答案 0 :(得分:2)
这就是我想到的 - 即ffmpeg-sharp项目中的大量P / Invoke声明是不正确的。有很多地方他们在声明中使用结构,这些结构被编组回来,但随后必须传递给释放例程。
因为指针在编组过程中已经丢失了,所以当尝试将该结构传递给接受有效指针的其他方法(如Windows中的句柄)时,这会导致AccessViolationException
被抛出)。它们不像将它们视为不透明(就像它们应该像Windows API一样),而是将结构编组回来并在过程中丢失指针。
解决方案是更改其API声明以获取/返回IntPtr
并根据需要执行结构的编组,而不是将它们包含在P / Invoke声明中。
答案 1 :(得分:1)
答案 2 :(得分:0)
我已从任何这些图书馆/项目中明确指出。我当时发现的所有信息都指出那些新版本太容易破坏和/或过于过时。
我所做的是直接运行ffmpeg进程,就像我在this answer上提到的那样,通过修改我在那里链接的博客文章中的示例。到目前为止,我们没有遇到过麻烦:)
如果以上情况对您的情况不起作用,祝您好运。
答案 3 :(得分: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方法),然后修改它,并再次将其复制到非托管内存。 我被同样的问题折磨得很厉害。我解决了它,但无论如何我无法解码视频))我希望我的解决方案能帮助任何人。