2009-12-02 11 views
11

Un po 'di background, mi è stato dato il compito di correggere alcuni "piccoli" bug e mantenere questa soluzione per lo streaming di video attraverso la rete tra due istanze della nostra applicazione. La soluzione è stata scritta da qualcuno che non è più qui, quindi c'è un po 'di mistero nel codice e alcune trappole davvero divertenti. La soluzione è stata scritta usando ffmpeg con codice C++ scritto per avvolgere il codice relativo alla codifica/decodifica e parte del codice di streaming. Questo C++ è stato quindi avvolto con SWIG in modo tale da poter eseguire l'interpunzione con C# e passare i fotogrammi del video su dove sono rappresentati utilizzando VideoRendererElement che risiede in un controllo WPF. Il motivo principale per cui i frame sono passati è perché abbiamo alcuni protocolli personalizzati che abbiamo bisogno di inviare dati video e quelli sono scritti usando C# così come i frame video vengono passati li avvolgiamo nei nostri stessi pacchetti e li mandiamo sul filo . Questa soluzione funziona e possiamo riprodurre video in streaming usando i nostri protocolli personalizzati, anche se è un incubo da gestire e gestire.Come codificare/decodificare video usando C#?

La mia domanda è un modo migliore per fare questo? Sto cercando modi per lavorare a un livello inferiore con i dati del video (in C#) in modo che io possa prendere i frame video e impacchettarli nei nostri pacchetti e inviarli e poter ricevere e ricostruire il video sul l'altra parte. ffmpeg sembra essere la soluzione più comune, ma ho riscontrato molti problemi e la cosa GPL/LGPL è un problema.

Il flusso di base che sto cercando di raggiungere, file video -> codifica -> avvolgere in pacchetto -> inviare su cavo sul protocollo X -> ottenere dati video da pacchetto -> decodificare -> render/salvare su disco

+0

Perché LGPL è un problema per te? Anche se la tua domanda è per i clienti commerciali, non dovrebbe essere un problema. –

+0

Possibile duplicato: http://stackoverflow.com/questions/271003/anyone-know-of-a-set-of-c-bindings-for-ffmpeg –

+0

La cosa GPL/LGPL è stata sollevata da un altro collega ma hanno fatto sembrare che avremmo infranto la licenza con il modo in cui usiamo ffmpeg e alcune delle sue librerie dipendenti. Per quanto riguarda il post duplicato, sto cercando di allontanarmi da ffmpeg se possibile e ffmpeg nitido non ha funzionato o è stato supportato più. –

risposta

0

Quello che si potrebbe provare è SharpFFmpeg. È concesso in licenza con GPL, anche se potresti essere in grado di vedere come hanno scritto il loro wrapper, e potresti essere in grado di scrivere il tuo o avere idee su come correggere la tua soluzione corrente.

Edit:

C'è un involucro simile chiamato ffmpeg-sharp sopra a code.google.com, che utilizza un LGPL - è possibile utilizzare questo in applicazioni commerciali. Sospetto che entrambi questi wrapper facciano lo stesso, sebbene SharpFFmpeg sia più vecchio e probabilmente più maturo.

2

Ho avuto tutti i tipi di problemi utilizzando ffmpeg in una DLL. Il mio progetto video era piuttosto semplice: avevo solo bisogno che il convertitore prendesse una singola miniatura da un WMV.

Dopo aver provato solo ciò che descrivi, la mia soluzione era copiare semplicemente il file binario ffmpeg.exe nel mio progetto come libreria esterna. anche questo diventa ordinatamente attorno eventuali problemi di licenza codice, 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"; 
      // ... 
     } 

la riga di comando ffmpeg può variare drasticamente da mio esempio, ma questo è il modo più stabile che ho trovato per ottenere le miniature fuori. Altre cose che ho trovato online riguardo a ffmpeg in particolare non hanno questa soluzione (basata su cmd.exe), ma questa è l'unica che ho funzionato bene. In bocca al lupo!

0

Ho scritto il VideoRendererElement quando non c'erano modi efficienti per eseguire il rendering di video in WPF (v3.0). Usa alcuni hackery per farlo funzionare.

Se si desidera semplificare un po 'le cose, rilasciare il VRE e utilizzare InteropBitmap per il rendering (WriteableBitmap è ok, ma non altrettanto efficiente). Lascia anche SWIG e rendi la tua DLL C++ una dll CLI/C++, in questo modo puoi parlare direttamente con il tuo C++ da C# (e viceversa).

Un altro itinerario si può andare è quello di creare solo un filtro di origine DirectShow che contiene la tua roba trasporto/decodifica e si può usare qualcosa come il mio WPF MediaKit di averlo rendere in WPF (utilizza la D3DImage. 0 hack).

Inoltre, non abbiate paura di LGPL. Finché lo si mantiene nella propria DLL e non si cambia la fonte, ci si trova entro le restrizioni della licenza.

0

Si potrebbe anche dare un'occhiata ai vari SDK di Microsoft Windows Media che sono disponibili per il download. In un progetto alcuni anni fa abbiamo utilizzato l'SDK Windows Media Format per estrarre le miniature dal video caricato. Questi SDK hanno anche codice di esempio .NET.

4

Nel nostro progetto utilizziamo Microsoft Expression Encoder. Non è gratis E 'possibile convertire i video in diversi formati e dimensioni, le miniature estratto, ecc

Ecco esempio:

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

Ho scaricato la versione gratuita di Expression Encoder e ho giocato un po 'con l'API, i campioni e ho esaminato le librerie in Reflector per cercare di ottenere una soluzione se questo potesse funzionare. Sembra una buona soluzione, ma non sono ancora sicuro di essere in grado di ottenere ciò di cui ho bisogno per controllare lo streaming su un protocollo personalizzato. Ho trovato che l'oggetto LiveJob ha una proprietà, OutputFormat, che sembra possa essere implementata in un modo per eseguire un'implementazione di streaming personalizzata, quindi potrebbe funzionare alla fine. –

0

Stiamo convertire file video in vari formati di output (divx codificato avi, flv, mp4, ecc) per la nostra applicazione mediadatabase. Dal momento che abbiamo sempre lavorato con le applicazioni CLI per convertire i file multimediali (parliamo di rasterizzare file EPS in JPG utilizzando ImageMagick/GS), abbiamo fatto molto affidamento su FFMPEG-CLI.

Nel nostro ambiente speciale, abbiamo usato "stupidi" server UNIX come macchine di conversione (ci sono solo le librerie sshd, ffmpeg, misc. Ffmpeg e samba installate). Sono controllati tramite la CLI di PuTTy da C# (servizio web WCF) tramite i comandi SSH per eseguire la conversione reale.

La chiamata per ffmpeg avviene tramite ssh ed è specializzata per ogni tipo di trasformazione. La CLI di mastice viene avviata attraverso lo spazio dei nomi System.Diagnostics.Process di C#, gli eventi per i messaggi di output e di errore vengono gestiti per scopi di registrazione.

Internet offre molte risorse relative a domande come "Come posso convertire mpg in flv utilizzando ffmpeg?", Un po 'di ricerca ti aiuterà. Dato che stiamo parlando di un'applicazione protetta da copyright, non posso pubblicare estratti completi di codice. Ma dovrebbe darti un'idea architettonica di un backend affidabile e veloce per la codifica video usando C#.

6

DirectShow è tuo amico. DirectShow è il livello di basso livello utilizzato dalla maggior parte delle applicazioni "multimediali" di Windows come Media Player, Encoder Audio e così via.

Anche se questa libreria è stata creata per sviluppatori nativi, è possibile accedervi dal mondo gestito grazie a DirectShow.net. http://directshownet.sourceforge.net Questo è un wrapper gestito ben noto e stabile per DirectShow.

L'unica cosa che devi fare è imparare un po 'DirectShow per capire il concetto di grafici e filtri e quindi creare i tuoi filtri e grafici per usare la potenza di DirectShow!

Problemi correlati