2009-12-02 19 views
11

Un poco de historia, me dieron la tarea de corregir algunos errores "pequeños" y mantener esta solución para la transmisión de video a través de la red entre dos instancias de nuestra aplicación. La solución fue escrita por alguien que ya no está aquí, así que hay algo de misterio en el código, así como algunas trampas realmente divertidas. La solución se escribió usando ffmpeg con código C++ escrito para envolver el código relacionado con la codificación/descodificación, así como parte del código de transmisión. Este C++ luego se envolvió con SWIG para que pudiera interoperar con C# y pasar los cuadros de video hacia arriba donde se representan usando VideoRendererElement que vive en un control WPF. La razón principal por la que se pasan los marcos es porque tenemos algunos protocolos personalizados que necesitamos para enviar datos de video y esos están escritos usando C# para que los fotogramas de video se pasen, los envolvemos en nuestros propios paquetes y los enviamos por cable . Esta solución funciona y podemos transmitir video utilizando nuestros protocolos personalizados, aunque es algo así como una pesadilla para mantener y trabajar.Cómo codificar/decodificar video usando C#?

Mi pregunta es ¿hay una mejor manera de hacerlo? Estoy buscando formas de trabajar en un nivel inferior con los datos de video (en C#) para poder tomar los marcos de video y empaquetarlos en nuestros propios paquetes y enviarlos y poder recibir y reconstruir el video en el otro lado. ffmpeg parece ser la solución común, pero me he encontrado con un montón de problemas y la cosa GPL/LGPL creo que es un problema.

El flujo básico que estoy buscando lograr, archivo de video -> codificar -> envolver en paquete -> enviar por cable en el protocolo X -> obtener datos de video del paquete -> decodificar -> renderizar/guardar en el disco

+0

¿Por qué es LGPL un problema para usted? Incluso si su aplicación es para clientes comerciales, no debería ser un problema. –

+0

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

+0

La cosa GPL/LGPL fue planteada por otro compañero de trabajo, pero lo hicieron sonar como si estuviéramos rompiendo la licencia con la forma en que estamos usando ffmpeg y algunas de sus bibliotecas dependientes. En cuanto a la publicación duplicada, estoy tratando de alejarme de ffmpeg si es posible y el ffmpeg afilado no parecía funcionar o que ya estaba siendo respaldado. –

Respuesta

0

Lo que puede probar es SharpFFmpeg. Tiene licencia con GPL, aunque es posible que pueda ver cómo escribieron su envoltorio, y usted podría escribir el suyo, u obtener ideas sobre cómo solucionar su solución actual.

Editar:

Hay un envoltorio similar llamado ffmpeg-sharp más en code.google.com, que utiliza un LGPL - Se puede utilizar esta en aplicaciones comerciales. Sospecho que ambas envolturas hacen lo mismo, aunque SharpFFmpeg es más viejo y probablemente más maduro.

2

Tuve todo tipo de problemas para usar ffmpeg en una DLL. Mi proyecto de video fue bastante simple: solo necesitaba el convertidor para tomar una miniatura de un WMV.

Después de intentar exactamente lo que describes, mi solución fue simplemente copiar el archivo binario ffmpeg.exe en mi proyecto como una biblioteca externa. esto también se pone cuidadosamente alrededor de los problemas de licencia de código, que yo sepa ...

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

Su línea de comando ffmpeg puede variar drásticamente de mi ejemplo, pero esta es la forma más estable que he encontrado para conseguir imágenes en miniatura a cabo. Otras cosas que encontré en línea con respecto a ffmpeg específicamente no tenían esta solución (basada en cmd.exe), pero esta es la única en la que he trabajado bien. ¡Buena suerte!

0

Escribí VideoRendererElement cuando no había maneras eficientes de procesar videos en WPF (v3.0). Utiliza algunos hackers para que funcione.

Si quiere simplificar un poco las cosas, suelte el VRE y use el Interopitmap para renderizar (WriteableBitmap está bien, pero no es tan eficiente). También suelte SWIG y convierta su C++ dll en CLI/C++ dll, de esta manera usted puede hablar directamente con su C++ desde C# (y viceversa).

Otra ruta que puede realizar es simplemente crear un filtro de fuente DirectShow que contenga sus elementos de transporte/decodificación y puede usar algo como mi WPF MediaKit para hacer que se presente en WPF (usa el D3DImage. 0 hacks).

Además, no tengas miedo de LGPL. Siempre que lo guarde en su propia DLL y no cambie la fuente, usted está dentro de las restricciones de la licencia.

0

También puede echar un vistazo a los diversos SDK de Microsoft Windows Media que están disponibles para su descarga. En un proyecto de hace unos años, utilizamos el SDK de Windows Media Format para extraer miniaturas del video cargado. Estos SDK también tienen código de ejemplo .NET.

4

En nuestro proyecto utilizamos Microsoft Expression Encoder. No es gratis Puede convertir vídeos a diferentes formatos y tamaños, miniaturas, etc. extracto

Aquí es ejemplo:

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

Descargué la versión gratuita de Expression Encoder y jugué un poco con la API, ejemplos y revisé las bibliotecas en un reflector para intentar controlar si esto podía funcionar. Parece una buena solución, pero todavía no estoy seguro de poder obtener lo que necesito para controlar la transmisión a través de un protocolo personalizado. Encontré que el objeto LiveJob tiene una propiedad, OutputFormat, que parece que podría implementarse de una manera para hacer una implementación de transmisión personalizada, así que esto podría funcionar al final. –

0

Estamos convirtiendo archivos de vídeo en varios formatos de salida (divx codificados AVI, FLV, MP4, etc.) para nuestra aplicación de base de datos media Como siempre trabajamos con aplicaciones de CLI para hacer conversiones de medios (hablar sobre rasterización de archivos de EPS a JPG usando ImageMagick/GS), confiamos mucho en FFMPEG-CLI.

En nuestro entorno especial, utilizamos servidores UNIX "tontos" como máquinas de conversión (solo hay sshd, ffmpeg, misc. Ffmpeg libraries y samba instalados). Se controlan a través de la CLI de PuTTy desde C# (WCF webservice) a través de comandos SSH para realizar la conversión real.

La llamada para ffmpeg ocurre a través de ssh y está especializada para cada TransformationType. La CLI de masilla se inicia a través del espacio de nombres System.Diagnostics.Process de C#, los eventos para los mensajes de salida y de error se manejan con fines de registro.

El Internet proporciona una gran cantidad de recursos relacionados con preguntas como "¿Cómo puedo convertir mpg a flv usando ffmpeg?", Un poco de investigación te ayudará. Como estamos hablando de una aplicación protegida por derechos de autor, no puedo publicar extractos completos del código. Pero debería darle una idea arquitectónica sobre un backend de codificación de video confiable y rápido usando C#.

6

DirectShow es tu amigo. DirectShow es la capa de bajo nivel utilizada por la mayoría de las aplicaciones "multimedia" de Windows como Media Player, Audio Encoders, etc.

Aunque esta biblioteca se haya creado para desarrolladores nativos, puede acceder a ella desde el mundo administrado gracias a DirectShow.net. http://directshownet.sourceforge.net Se trata de un contenedor gestionado estable y bien conocido para DirectShow.

Lo único que tienes que hacer es aprender un poco DirectShow para entender el concepto de graphes y filtros y luego crear tus propios filtros y graphes para usar el poder de DirectShow.

Cuestiones relacionadas