代码之家  ›  专栏  ›  技术社区  ›  casperOne

.NET中是否有一组用于ffmpeg、libavutil、libavformat和libavcodec的工作p/invoke声明?

  •  7
  • casperOne  · 技术社区  · 14 年前

    我目前正在寻找从.NET访问libavutil、libavformat和libavcodec(全部是ffmpeg的一部分)。

    目前,我正在获取 libraries from the automated builds of the shared FFMpeg package 每晚为32位Windows执行。

    我也在使用 ffmpeg-sharp project . 在那个项目中,我删除了一些没有编译的类(它们是包装类而不是p/invoke声明)。

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

    首先,似乎av.dll的构建使用 cdecl calling convention ,因为我收到了 PInvokeStackImbalanceException 打电话的时候 av_open_input_file . 这很容易改变以使它正常工作。这个 AVFormatContext 结构已填充。

    之后,我想打电话给 av_find_stream_info 以获取有关文件中流的信息。但是,当使用 avformatContext格式 从呼叫中检索到 打开输入文件 ,一个 AccessViolationException 被抛出,表示我正试图从受保护的内存中读或写。

    是否有人使用p/invoke通过p/invoke访问libavutil、libavformat和libavcodec dll库并使其工作?

    我应该提到,使用命令行版本的ffmpeg虽然不是一个可行的解决方案,但在这种情况下,需要通过库进行访问。这样做的原因是,我要做我需要做的事情(我必须对一些非常高清晰度的视频进行逐帧分析),我要尽可能避免使用磁盘。

    4 回复  |  直到 10 年前
        1
  •  2
  •   casperOne    13 年前

    这就是我发现的——也就是说,在ffmpeg-sharp项目中有大量的p/invoke声明是不正确的。在许多地方,它们在声明中使用被封回的结构,但随后必须传递给释放例程。

    由于指针已作为封送的一部分丢失,因此导致 AccessViolationException 当试图将该结构传递给其他接受有效指针的方法(如Windows中的句柄)时抛出。而不是像WindowsAPI那样将它们视为不透明的(它们应该这样做),而是重新封送结构,并在进程中丢失指针。

    解决方案是将其API声明更改为获取/返回 IntPtr 并根据需要执行结构的封送处理,而不是将它们包含在P/Invoke声明中。

        3
  •  0
  •   Community Mohan Dere    7 年前

    我已经从这些库/项目中脱离出来了。当时我发现的所有信息都指向那些用新版本太容易破坏和/或太过时的东西。

    我所做的就是直接运行ffmpeg进程,正如我在上面提到的那样。 this answer ,通过修改博客文章中的示例,我链接到那里。到目前为止,我们还没有遇到过问题。)

    如果上述情况不适合您的场景,祝您好运。

        4
  •  0
  •   mazharenko.a    13 年前

    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方法),然后修改它,然后再次复制到非托管内存。
    我经常被同样的问题折磨。我解决了这个问题,但无论如何我都不能解码视频),我希望我的解决方案能帮助任何人。