2009-12-02 71 views
11

Một nền tảng nhỏ, tôi đã được giao nhiệm vụ sửa một vài lỗi "nhỏ" và duy trì giải pháp này để phát video qua mạng giữa hai phiên bản ứng dụng của chúng tôi. Giải pháp được viết bởi một người không còn ở đây nên có một số bí ẩn trong mã cũng như một số cạm bẫy thực sự thú vị. Giải pháp được viết bằng cách sử dụng ffmpeg với mã C++ được viết để bọc mã hóa/giải mã có liên quan cũng như một số mã trực tuyến. C++ này sau đó được bọc bằng SWIG sao cho nó có thể tương tác với C# và chuyển các khung hình video lên nơi chúng được hiển thị bằng cách sử dụng VideoRendererElement mà tồn tại trong một điều khiển WPF. Lý do chính là các frame được truyền bởi vì chúng ta có một số giao thức tùy chỉnh chúng ta cần gửi dữ liệu video và những dữ liệu được viết bằng C# để khung hình được truyền lên, chúng ta gói chúng vào gói của chúng ta và gửi chúng lên dây . Giải pháp này hoạt động và chúng tôi có thể truyền video bằng cách sử dụng giao thức tùy chỉnh của chúng tôi mặc dù nó là một cái gì đó của một cơn ác mộng để duy trì và làm việc với.Làm thế nào để mã hóa/giải mã video bằng C#?

Câu hỏi của tôi là có cách nào tốt hơn để thực hiện việc này? Tôi đang tìm cách để làm việc ở mức thấp hơn với dữ liệu video (trong C#) để tôi có thể lấy các khung hình video và gói chúng trong các gói riêng của chúng tôi và gửi chúng ra và có thể nhận và xây dựng lại video trên phía bên kia. ffmpeg có vẻ là giải pháp phổ biến nhưng tôi đã gặp rất nhiều vấn đề với nó và điều GPL/LGPL mà tôi nghĩ là một vấn đề.

Luồng cơ bản tôi muốn đạt được, tệp video -> mã hóa -> gói trong gói -> gửi qua dây trên giao thức X -> lấy dữ liệu video từ gói -> giải mã -> hiển thị/lưu vào đĩa

+0

Tại sao LGPL là vấn đề với bạn? Ngay cả khi ứng dụng của bạn dành cho khách hàng thương mại, nó không phải là một vấn đề. –

+0

Có thể trùng lặp: http://stackoverflow.com/questions/271003/anyone-know-of-a-set-of-c-bindings-for-ffmpeg –

+0

Điều GPL/LGPL được đưa lên bởi một đồng nghiệp khác nhưng họ làm cho nó có vẻ như chúng tôi sẽ phá vỡ giấy phép với cách chúng tôi đang sử dụng ffmpeg và một số thư viện phụ thuộc của nó. Đối với các bài đăng trùng lặp tôi đang cố gắng để có được đi từ ffmpeg nếu có thể và sắc nét ffmpeg dường như không làm việc hoặc nó đã được hỗ trợ nữa. –

Trả lời

0

Những gì bạn có thể thử xem là SharpFFmpeg. Nó được cấp phép sử dụng GPL, mặc dù bạn có thể thấy cách họ viết trình bao bọc của họ và bạn có thể viết trình bao bọc của riêng mình hoặc lấy ý tưởng về cách khắc phục giải pháp hiện tại của mình.

Edit:

Có một wrapper tương tự gọi là ffmpeg-sharp qua tại code.google.com, trong đó sử dụng một LGPL - bạn có thể sử dụng trong các ứng dụng thương mại. Tôi nghi ngờ cả hai trình bao bọc này làm được điều tương tự, mặc dù SharpFFmpeg là cũ hơn và có thể trưởng thành hơn.

2

Tôi có tất cả các loại sự cố khi sử dụng ffmpeg được bao bọc thành một DLL. Dự án video của tôi khá đơn giản - tôi chỉ cần bộ chuyển đổi để chụp một hình thu nhỏ từ một WMV.

Sau khi thử chỉ những gì bạn mô tả, giải pháp của tôi là chỉ cần sao chép nhị phân ffmpeg.exe vào dự án của tôi như một thư viện bên ngoài. điều này cũng gọn gàng được xung quanh bất kỳ vấn đề cấp phép mã, AFAIK ...

 Guid temp = Guid.NewGuid(); 

     // just throw our ffmpeg commands at cmd.exe 
     System.Diagnostics.ProcessStartInfo psi = 
      new System.Diagnostics.ProcessStartInfo("cmd.exe"); 

     psi.WorkingDirectory = Page.MapPath(@"~\Lib\ffmpeg.rev12665"); 

     psi.UseShellExecute = false; 
     psi.RedirectStandardError = true; 
     psi.RedirectStandardOutput = true; 
     psi.RedirectStandardInput = true; 

     System.Diagnostics.Process ps = System.Diagnostics.Process.Start(psi); 

     StreamReader outputReader = ps.StandardOutput; 
     StreamReader errorReader = ps.StandardError; 
     StreamWriter inputWrite = ps.StandardInput; 

     // uses extra cheap logging facility 
     inputWrite.WriteLine("echo \"Ripping " + copiedFile + " " + 
      temp.ToString() + "\" >> log.txt"); 

     inputWrite.WriteLine("ffmpeg.exe -i \"" + copiedFile + 
      "\" -f image2 -vframes 1 -y -ss 2 tmp\\" + temp.ToString() + 
      ".jpg"); 

     inputWrite.WriteLine("exit"); 

     ps.WaitForExit(3000); 

     if (ps.HasExited) 
     { 
      string thumbFile = Page.MapPath(@"~\Lib\ffmpeg.rev12665\tmp") + 
       @"\" + temp.ToString() + ".jpg"; 
      // ... 
     } 

dòng lệnh ffmpeg của bạn có thể khác nhau đáng kể từ ví dụ của tôi, nhưng đây là cách ổn định nhất mà tôi đã tìm thấy để có được hình thu nhỏ ra. Những thứ khác tôi tìm thấy trực tuyến về ffmpeg đặc biệt không có giải pháp này (dựa trên cmd.exe), nhưng đây là thứ duy nhất tôi đã làm việc tốt. Chúc may mắn!

0

Tôi đã viết lại VideoRendererElement khi không có cách hiệu quả để hiển thị video trong WPF (v3.0). Nó sử dụng một số hackery để làm cho nó hoạt động.

Nếu bạn muốn đơn giản hóa mọi thứ một chút, hãy thả VRE và sử dụng InteropBitmap để hiển thị (WriteableBitmap là ok, nhưng không hiệu quả). Cũng thả SWIG và làm cho C++ của bạn dll một CLI/C + + dll, theo cách này bạn có thể trực tiếp nói chuyện với C + + của bạn từ C# (và ngược lại). Một tuyến đường khác mà bạn có thể thực hiện là tạo bộ lọc nguồn DirectShow chứa công cụ giải mã/giải mã của bạn và bạn có thể sử dụng thứ gì đó giống như WPF MediaKit để nó hiển thị trong WPF (nó sử dụng D3DImage. 0 hacks).

Ngoài ra, đừng sợ LGPL. Miễn là bạn giữ nó trong nó riêng của DLL và không thay đổi nguồn, bạn đang trong giới hạn giấy phép.

0

Bạn cũng có thể xem nhiều Microsoft Windows Media SDK khác nhau có sẵn để tải xuống. Trong một dự án một vài năm trước, chúng tôi đã sử dụng Windows Media Format SDK để trích xuất hình thu nhỏ từ video đã tải lên. Các SDK này cũng có mã mẫu .NET.

4

Trong dự án của chúng tôi, chúng tôi sử dụng Bộ mã hóa biểu thức Microsoft. Nó không phải là miễn phí. Nó có thể chuyển đổi video sang các định dạng khác nhau và kích cỡ, chiết xuất từ ​​hình thu nhỏ vv

Dưới đây là ví dụ:

using Microsoft.Expression.Encoder; 

//... 
//skiped 
//... 

MediaItem mediaItem = new MediaItem(videoToEncode.SourceFilePath); 
mediaItem.ApplyPreset(PresetFilePath); 

Job job = new Job(); 
job.ApplyPreset(PresetFilePath); // path to preset file, where settings of bit-rate, codec etc 
job.MediaItems.Add(mediaItem); 

job.EncodeProgress += OnProgress; 
job.EncodeCompleted += EncodeCompleted; 

job.DefaultMediaOutputFileName = "{OriginalFilename}.encoded.{DefaultExtension}"; 
job.CreateSubfolder = false; 

job.OutputDirectory = videoToEncode.EncodedFilePath; 
job.Encode(); 
+0

Tôi đã tải xuống phiên bản miễn phí của Bộ mã hóa biểu thức và phát xung quanh một chút với API, các mẫu và xem qua các thư viện trong bộ phản xạ để thử và xử lý nếu điều này có thể hoạt động. Nó trông giống như một giải pháp tốt đẹp nhưng tôi vẫn không chắc chắn tôi sẽ có thể có được những gì tôi cần để kiểm soát streaming trên một giao thức tùy chỉnh. Tôi đã thấy rằng đối tượng LiveJob có một thuộc tính, OutputFormat, có vẻ như nó có thể được thực hiện theo cách để thực hiện triển khai luồng tùy chỉnh để điều này có thể hoạt động cuối cùng. –

0

Chúng tôi đang chuyển đổi các file video sang các định dạng đầu ra khác nhau (divx mã hóa avi, flv, mp4, vv) cho ứng dụng mediadatabase của chúng tôi. Vì chúng tôi luôn làm việc với các ứng dụng CLI để thực hiện chuyển đổi phương tiện truyền thông (nói về việc rasterizing tệp EPS thành JPG bằng ImageMagick/GS), chúng tôi dựa nhiều vào FFMPEG-CLI.

Trong môi trường đặc biệt, chúng tôi sử dụng máy chủ UNIX "câm" làm máy chuyển đổi (chỉ có sshd, ffmpeg, misc. Ffmpeg library và samba đã cài đặt). Chúng được điều khiển thông qua CLI của PuTT từ C# (WCF webservice) thông qua các lệnh SSH để thực hiện chuyển đổi thực.

Cuộc gọi cho ffmpeg xảy ra thông qua ssh và chuyên biệt cho mỗi TransformationType. CLI putty được bắt đầu thông qua không gian tên System.Diagnostics.Process của C#, các sự kiện cho các thông điệp đầu ra và lỗi được xử lý cho các mục đích ghi nhật ký.

Internet cung cấp rất nhiều tài nguyên liên quan đến các câu hỏi như "Làm thế nào tôi có thể chuyển đổi mpg sang flv bằng ffmpeg?", Một ít nghiên cứu sẽ giúp bạn. Vì chúng ta đang nói về một ứng dụng có bản quyền, tôi không thể đăng các trích đoạn mã hoàn chỉnh. Nhưng nó sẽ cung cấp cho bạn một ý tưởng kiến ​​trúc về một phần mềm mã hóa video đáng tin cậy, nhanh chóng bằng C#.

6

DirectShow là bạn của bạn. DirectShow là tầng mức thấp được sử dụng bởi hầu hết các ứng dụng "đa phương tiện" windows như Media Player, Audio Encoder, v.v.

Ngay cả khi thư viện này đã được tạo cho các nhà phát triển gốc, bạn có thể truy cập thư viện đó từ thế giới được quản lý nhờ DirectShow.net. http://directshownet.sourceforge.net Đây là trình bao bọc được quản lý tốt và ổn định dành cho DirectShow. Điều duy nhất bạn phải làm là tìm hiểu một chút DirectShow để hiểu khái niệm đồ thị và bộ lọc và sau đó tạo bộ lọc và đồ thị của riêng bạn để sử dụng sức mạnh của DirectShow!

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