2009-12-02 6 views
11

Un peu de contexte, on m'a confié la tâche de corriger quelques "petits" bogues et de maintenir cette solution pour diffuser de la vidéo sur le réseau entre deux instances de notre application. La solution a été écrite par quelqu'un qui n'est plus là, donc il y a du mystère dans le code ainsi que des pièges vraiment amusants. La solution a été écrite en utilisant ffmpeg avec du code C++ écrit pour enrouler le code associé au codage/décodage ainsi qu'une partie du code de streaming. Ce C++ a ensuite été enveloppé avec SWIG afin qu'il puisse interopérer avec C# et transmettre les images vidéo là où elles sont rendues en utilisant VideoRendererElement qui vit dans un contrôle WPF. La raison principale pour laquelle les trames sont transmises est parce que nous avons des protocoles personnalisés dont nous avons besoin d'envoyer des données vidéo et ceux-ci sont écrits en C#, alors que les trames vidéo sont passées, nous les enveloppons dans nos propres paquets. . Cette solution fonctionne et nous pouvons diffuser de la vidéo en utilisant nos protocoles personnalisés, même si c'est quelque chose d'un cauchemar à maintenir et à travailler avec.Comment encoder/décoder de la vidéo en utilisant C#?

Ma question est là une meilleure façon de faire? Je cherche des façons de travailler à un niveau inférieur avec les données vidéo (en C#) afin que je puisse prendre les images vidéo et les emballer dans nos propres paquets et les envoyer et être en mesure de recevoir et de reconstruire la vidéo sur le autre côté. ffmpeg semble être la solution courante, mais j'ai rencontré beaucoup de problèmes avec la GPL/LGPL, je pense que c'est un problème. Le flux de base que je cherche à atteindre, fichier vidéo -> encoder -> wrap dans le paquet -> envoyer sur le fil sur le protocole X -> obtenir des données vidéo de paquet -> décoder -> rendre/enregistrer sur le disque

+0

Pourquoi la LGPL est-elle un problème pour vous? Même si votre application est destinée aux clients commerciaux, cela ne devrait pas poser de problème. –

+0

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

+0

La chose GPL/LGPL a été évoquée par un autre collègue mais ils ont fait comme si nous allions casser la licence avec la façon dont nous utilisons ffmpeg et certaines de ses bibliothèques dépendantes. En ce qui concerne le post en double, j'essaie de m'éloigner de ffmpeg si possible et ffmpeg n'a pas l'air de marcher ou d'être supporté. –

Répondre

0

Ce que vous pourriez essayer est SharpFFmpeg. Il est sous licence GPL, bien que vous puissiez voir comment ils ont écrit leur wrapper, et vous pourriez être en mesure d'écrire le vôtre, ou d'avoir des idées sur la façon de réparer votre solution actuelle.

Edit:

Il y a un emballage similaire appelé à ffmpeg-sharp sur code.google.com, qui utilise un LGPL - vous pouvez l'utiliser dans des applications commerciales. Je suspecte que ces deux enveloppes font la même chose, même si SharpFFmpeg est plus âgé et probablement plus mature.

2

J'ai eu toutes sortes de problèmes en utilisant ffmpeg enveloppé dans une DLL. Mon projet vidéo était assez simple - j'avais juste besoin du convertisseur pour prendre une seule vignette d'un WMV. Après avoir essayé juste ce que vous décrivez, ma solution était de simplement copier le binaire ffmpeg.exe dans mon projet en tant que bibliothèque externe. cela aussi se soigneusement autour des problèmes de licence de code, ... Autant que je sache

 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"; 
      // ... 
     } 

Votre ligne de commande ffmpeg peut varier considérablement de mon exemple, mais c'est la façon la plus stable que j'ai trouvé pour obtenir des vignettes sur. D'autres choses que j'ai trouvées en ligne concernant ffmpeg spécifiquement n'ont pas eu cette solution (basée sur cmd.exe), mais c'est la seule que j'ai eu bien fonctionné. Bonne chance!

0

J'ai écrit le VideoRendererElement lorsqu'il n'y avait pas de moyens efficaces pour rendre la vidéo dans WPF (v3.0). Il utilise un hackery pour le faire fonctionner.

Si vous voulez simplifier un peu les choses, supprimez l'ERV et utilisez InteropBitmap pour le rendu (WriteableBitmap est correct, mais pas aussi efficace). Déposez aussi SWIG et faites de votre DLL C++ une DLL CLI/C++, de cette façon vous pouvez directement parler à votre C++ à partir de C# (et vice versa). Vous pouvez également créer un filtre source DirectShow qui contient votre contenu de transport/décodage et vous pouvez utiliser quelque chose comme mon WPF MediaKit pour le rendre dans WPF (il utilise le D3DImage. 0 hacks).

Aussi, n'ayez pas peur de la LGPL. Tant que vous le gardez dans sa propre DLL et ne changez pas la source, vous êtes dans les limites de la licence.

0

Vous pouvez également consulter les divers SDK Microsoft Windows Media disponibles en téléchargement. Dans un projet il y a quelques années, nous avons utilisé le Windows Media Format SDK pour extraire les vignettes de la vidéo téléchargée. Ces SDK possèdent également un exemple de code .NET.

4

Dans notre projet, nous utilisons Microsoft Expression Encoder. Ce n'est pas gratuit. Il peut convertir des vidéos en différents formats et tailles, des vignettes d'extraits, etc.

est par exemple ici:

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

J'ai téléchargé la version gratuite de l'Expression Encoder et joué un peu avec l'API, des échantillons et regardé à travers les bibliothèques dans le réflecteur pour essayer de comprendre si cela pouvait fonctionner. Cela ressemble à une bonne solution, mais je ne suis toujours pas sûr de pouvoir obtenir ce dont j'ai besoin pour contrôler le streaming sur un protocole personnalisé. J'ai trouvé que l'objet LiveJob a une propriété, OutputFormat, qui a l'air d'être implémentée de façon à faire une implémentation de streaming personnalisée, donc cela peut fonctionner à la fin. –

0

Nous convertissons des fichiers vidéo dans différents formats de sortie (AVI codé divx, flv, mp4, etc.) pour notre application mediadatabase. Puisque nous avons toujours travaillé avec les applications CLI pour faire la conversion des médias (parler de pixelliser les fichiers EPS en JPG en utilisant ImageMagick/GS), nous nous sommes fortement appuyés sur FFMPEG-CLI.

Dans notre environnement spécial, nous avons utilisé des serveurs UNIX «idiots» comme machines de conversion (seules les bibliothèques sshd, ffmpeg, diverses ffmpeg et samba sont installées). Ils sont contrôlés via CLI de PuTTy à partir de C# (service web WCF) via les commandes SSH pour faire la vraie conversion.

L'appel de ffmpeg se fait via ssh et est spécialisé pour chaque TransformationType. L'interface de ligne de commande putty est démarrée via l'espace de noms System.Diagnostics.Process de C#, les événements pour les messages de sortie et d'erreur sont gérés à des fins de consignation.

Internet offre beaucoup de ressources concernant des questions comme "Comment puis-je convertir mpg en flv en utilisant ffmpeg?", Un peu de recherche vous aidera. Puisque nous parlons d'une application de droit d'auteur, je ne peux pas poster des extraits de code complets. Mais cela devrait vous donner une idée architecturale d'un backend d'encodage vidéo fiable et rapide utilisant C#.

6

DirectShow est votre ami. DirectShow est la couche de bas niveau utilisée par la plupart des applications Windows «multimédia» telles que Media Player, Audio Encoders, etc.

Même si cette bibliothèque a été créée pour les développeurs natifs, vous pouvez y accéder depuis le monde géré grâce à DirectShow.net. http://directshownet.sourceforge.net Il s'agit d'un wrapper géré bien connu et stable pour DirectShow.

La seule chose que vous avez à faire est d'apprendre un peu de DirectShow pour comprendre le concept de graphes et de filtres, puis de créer vos propres filtres et graphiques pour utiliser la puissance de DirectShow!

Questions connexes