2010-09-24 16 views
7

Tôi hiện đang tìm cách truy cập libavutil, libavformat và libavcodec (tất cả các phần của FFMpeg) từ .NET.Có một tập hợp các khai báo P/Invoke hoạt động cho FFMpeg, libavutil, libavformat và libavcodec trong .NET không?

Hiện tại, tôi nhận được libraries from the automated builds of the shared FFMpeg package được thực hiện mỗi đêm cho Windows 32 bit.

Tôi cũng đang sử dụng mã từ ffmpeg-sharp project. Trong dự án đó, tôi đã loại bỏ một số lớp không biên dịch (chúng là các lớp bao bọc chứ không phải các khai báo P/Invoke).

Mã biên dịch tốt, nhưng tôi đang gặp phải một số vấn đề.

Đầu tiên, có vẻ như việc xây dựng av * .dll sử dụng cdecl calling convention, vì tôi đã nhận được một số PInvokeStackImbalanceException khi cố gắng gọi av_open_input_file. Điều này là dễ dàng, đủ để thay đổi để làm cho nó hoạt động đúng. Cấu trúc AVFormatContext được điền.

Sau đó, tôi muốn gọi av_find_stream_info để nhận thông tin về các luồng trong tệp. Tuy nhiên, khi gọi điện thoại với số AVFormatContext được truy lục từ cuộc gọi đến av_open_input_file, một số AccessViolationException được ném cho biết rằng tôi đang cố gắng đọc hoặc ghi từ bộ nhớ được bảo vệ.

Có ai đã sử dụng P/Gọi để truy cập vào các thư viện libavutil, libavformat và libavcodec dll thông qua P/Invoke và đã nhận nó hoạt động không?

Tôi nên đề cập rằng làm việc với phiên bản dòng lệnh của FFMpeg, trong khi giải pháp, không phải là giải pháp khả thi trong trường hợp này, quyền truy cập cần phải xảy ra thông qua thư viện. Lý do cho điều này là tôi sẽ phải đập đĩa quá nhiều để làm những gì tôi cần làm (tôi phải làm một phân tích từng khung hình của một số video độ nét rất cao) và tôi muốn tránh đĩa Càng nhiều càng tốt.

+0

Re: disk thrashing mối quan tâm, tôi chỉ đạt được một số thành công với chụp ffmpeg đầu ra - có nội dung, không siêu dữ liệu - thông qua các đường ống stdout. Nếu điều này có thể phù hợp với kịch bản của bạn, không có tập tin và nó không trúng đĩa. –

Trả lời

2

Đây là những gì tôi đã tìm ra - cụ thể là, một số lượng tốt các khai báo P/Invoke trong dự án ffmpeg-sharp là không chính xác. Có một số lượng tốt các nơi mà họ sử dụng các cấu trúc trong tờ khai được sắp xếp lại, nhưng sau đó, phải được chuyển đến các thói quen giải quyết sau này.

Vì con trỏ đã bị mất như một phần của marshaling, đây là nguyên nhân gây ra AccessViolationException được ném khi cố gắng chuyển cấu trúc đó sang các phương thức khác đang chấp nhận một con trỏ hợp lệ (như một xử lý trong Windows). Thay vì xử lý chúng mờ đục (như chúng cần, như Windows API làm), chúng sắp xếp lại cấu trúc và mất con trỏ trong tiến trình.

Giải pháp là thay đổi các khai báo API của họ để lấy/trả về một IntPtr và thực hiện marshaling của các cấu trúc nếu cần, không bao gồm chúng trong các khai báo P/Invoke.

+0

Tôi hiện đang tìm kiếm một wrapper .NET đơn giản mà nên trưng ra một phương pháp chuyển đổi toàn cầu và nên sử dụng ffmpeg. Tôi cũng cần nó để nâng cao một sự kiện mỗi khi tiến trình của nó thay đổi, vì vậy tôi có thể chạy nó một cách không đồng bộ và thông báo cho người dùng một tỷ lệ phần trăm. – Shimmy

+0

Bây giờ tôi thực sự phải hỏi bạn: họ đã sửa chưa? –

0

Tôi đã xóa rõ ràng khỏi bất kỳ thư viện/dự án nào. Tất cả thông tin tôi tìm thấy vào thời điểm đó đã chỉ ra những thông tin đột phá quá dễ dàng với các phiên bản mới và/hoặc chỉ là quá lỗi thời.

Điều tôi đã làm là chạy quy trình ffmpeg trực tiếp, như tôi đã đề cập trên this answer, bằng cách sửa đổi mẫu trong bài đăng trên blog mà tôi liên kết ở đó. Đến ngày này, chúng tôi đã không gặp sự cố với nó :)

Nếu điều trên không hiệu quả cho kịch bản của bạn, chúc may mắn.

+0

Tôi đã sửa đổi câu hỏi, nhưng tôi nên đề cập rằng việc sử dụng dòng lệnh không phải là một tùy chọn. Tôi sẽ phải đập đĩa quá nhiều để làm những gì tôi cần làm (tôi phải làm một phân tích từng khung hình của một số video độ nét rất cao) và tôi muốn tránh đĩa càng nhiều càng tốt. – casperOne

+0

Tôi đã không làm điều đó, nhưng bạn có thể chuyển hướng đầu ra để tránh phải đi đến đĩa để lấy nó – eglasius

+0

Tôi figurd nó ra, xem câu trả lời của tôi dưới đây. Đó là cách xử lý ffmpeg-sharp P/Invoke. Tôi có thể nhận thông tin về luồng/codec từ các tệp hiện có trong bộ nhớ. – casperOne

0

Nhập khẩu các thư viện C++ của SharpFFmpeg. Mã C++ là một mã không được quản lý. Nó cần con trỏ đến bộ nhớ không được quản lý.Lớp "Marshal" cung cấp một số phương thức để cấp phát bộ nhớ không được quản lý. Ví dụ:

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

Ngoài ra, nếu bạn muốn gửi biến được quản lý (bất kỳ biến C# nào) cho hàm, bạn phải sắp xếp (sao chép) biến này thành bộ nhớ không được quản lý.

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

Bây giờ bạn có thể gửi con trỏ đến hàm.

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

Có thể bạn sẽ cần sửa đổi một số cấu trúc không được quản lý. Để làm điều này, bạn phải sao chép cấu trúc vào bộ nhớ được quản lý (phương thức Marshal.PtrToStructure), sau đó sửa đổi nó và sao chép nó vào bộ nhớ không được quản lý một lần nữa.
Tôi đã bị dày vò bởi cùng một vấn đề. Tôi giải quyết nó, nhưng tôi không thể giải mã video anyway)) Tôi hy vọng giải pháp của tôi sẽ giúp bất cứ ai.

Các vấn đề liên quan