silverlight - laptop - como instalar una camara web
Transmitir una cámara web desde Silverlight 4(Beta) (5)
¿Has probado los nuevos Expression 4 Encoders?
http://www.microsoft.com/expression/products/EncoderPro_Overview.aspx
La nueva cámara web en Silverlight 4 es genial. Al exponerlo como un pincel, permite escenarios que van mucho más allá de lo que Flash tiene.
Al mismo tiempo, el acceso local a la cámara web parece ser solo la mitad de la historia. Nadie compra una cámara web para que puedan tomar fotos de ellos mismos y hacerles caras divertidas. Compran una cámara web porque quieren que otras personas vean la transmisión de video resultante, es decir, quieren transmitir ese video a Internet, un Skype cualquiera o cualquiera de las docenas de otros sitios / aplicaciones de chat de video. Y hasta ahora, no he descubierto cómo hacer eso con
Resulta que es bastante simple obtener la versión sin procesar (Format32bppArgb formateada) bytestream, como se demuestra aquí .
Pero a menos que deseemos transmitir esa corriente de bits sin procesar a un servidor (lo que mastica demasiado ancho de banda), necesitamos codificar eso de alguna manera. Y eso es más complicado. MS ha implementado varios códecs en Silverlight, pero por lo que yo sé, todos están enfocados en decodificar un flujo de video, no en codificarlo en primer lugar. Y eso es aparte del hecho de que no puedo entender cómo obtener acceso directo, por ejemplo, al códec H.264 en primer lugar.
Hay un montón de códecs de código abierto (por ejemplo, en el proyecto ffmpeg aquí ), pero están escritos en C, y no parecen fáciles de portar a C #. A menos que traduzca más de 10000 líneas de código que se parezcan a esta, es su idea de diversión :-)
const int b_xy= h->mb2b_xy[left_xy[i]] + 3;
const int b8_xy= h->mb2b8_xy[left_xy[i]] + 1;
*(uint32_t*)h->mv_cache[list][cache_idx ]= *(uint32_t*)s->current_picture.motion_val[list][b_xy + h->b_stride*left_block[0+i*2]];
*(uint32_t*)h->mv_cache[list][cache_idx+8]= *(uint32_t*)s->current_picture.motion_val[list][b_xy + h->b_stride*left_block[1+i*2]];
h->ref_cache[list][cache_idx ]= s->current_picture.ref_index[list][b8_xy + h->b8_stride*(left_block[0+i*2]>>1)];
h->ref_cache[list][cache_idx+8]= s->current_picture.ref_index[list][b8_xy + h->b8_stride*(left_block[1+i*2]>>1)];
La carpeta mooncodecs dentro del proyecto Mono ( aquí ) tiene varios códecs de audio en C # (ADPCM y Ogg Vorbis), y un códec de video (Dirac), pero todos parecen implementar solo la parte decodificada de sus respectivos formatos, al igual que el java implementaciones desde las que fueron portados.
Encontré un códec C # para Ogg Theora (csTheora, http://www.wreckedgames.com/forum/index.php?topic=1053.0 ), pero una vez más, solo está decodificado, como es el códec jheora en el que está basado.
Por supuesto, presumiblemente sería más fácil portar un códec desde Java que desde C o C ++, pero los únicos codecs de video java que encontré fueron decodificados (como jheora o jirac).
Así que estoy un poco atrás en el cuadrado uno. Parece que nuestras opciones para conectar una cámara web (o micrófono) a través de Silverlight a Internet son:
(1) Espere a que Microsoft brinde alguna orientación sobre esto;
(2) Pasar los ciclos cerebrales portando uno de los códecs C o C ++ a C # compatible con Silverlight;
(3) Envíe la corriente de bits sin comprimir sin comprimir a un servidor (o tal vez comprimido ligeramente con algo como zlib), y luego codifíquelo en el lado del servidor; o
(4) Espere a que alguien más inteligente que yo lo descubra y brinde una solución.
¿Alguien más tiene una mejor guía? ¿Me he perdido algo que es cegadoramente obvio para todos los demás? (Por ejemplo, ¿tiene Silverlight 4 en algún lado algunas clases que he echado de menos que se ocupan de esto?)
¿Recurso provisional?
¿Sería posible usar Windows Media Encoder como método de compresión para el video en bruto que proporciona Silverlight? Después de capturar en almacenamiento ISO , codifique w / WME y envíe al servidor a través del WebClient . Dos grandes problemas son:
- Requiere que un usuario instale el codificador
- WME ya no será compatible
Parece que podría ser una solución provisional hasta que llegue algo mejor. No he trabajado antes con WME, así que no sé qué tan factible sería. ¿Pensamientos?
Añadiré otro comentario. Acabo de enterarme hoy de un contacto de Microsoft de que Microsoft no tiene previsto agregar ningún soporte para la codificación / transmisión de audio y video aguas arriba a Silverlight, por lo que la opción n. ° 1 parece estar fuera de lugar, al menos por ahora. Mi suposición es que encontrar el apoyo para esto será responsabilidad de la comunidad, es decir, depende de usted y de mí.
Acabo de recibir esta respuesta de Jason Clary en mi blog:
Vi tu publicación en el blog de Mike Taulty sobre VideoSink / AudioSink en Silverlight 4 beta.
Pensé que señalaría que OnSample de VideoSink ofrece un solo marco ARGB de 32bbs sin comprimir que se puede copiar directamente en un WritableBitmap.
Con eso en la mano toma FJCore, un códec jpeg en C #, y modifícalo para que no salga el encabezado JFIF. Luego solo escríbelas una tras otra y obtendrá un códec Motion JPEG. RFC2435 explica cómo incluir eso en paquetes RTP para la transmisión RTSP.
Comprimir audio PCM a ADPCM también es bastante fácil, pero aún no he encontrado una implementación lista. RFC3551 explica cómo poner PCM o ADPCM en paquetes RTP.
También debería ser razonablemente fácil incluir MJPEG y PCM o ADPCM en un archivo AVI. MS tiene algunos documentos decentes en el formato RIFF modificado de AVI, y tanto MJPEG como ADPCM son códecs ampliamente compatibles.
Es un comienzo de todos modos.
Por supuesto, una vez que haya pasado por todos esos problemas, la próxima versión Beta probablemente saldrá con soporte nativo para comprimir y transmitir a WMS con los mejores códecs WMV.
Pensé que lo publicaría. Es la mejor sugerencia que he visto hasta ahora.
Pensé que dejaría que la gente interesada supiera el enfoque que realmente tomé. Estoy usando CSpeex para codificar la voz, pero escribí mi propio códec de video basado en bloques para codificar el video. Divide cada cuadro en bloques de 16x16, determina qué bloques han cambiado lo suficiente para justificar la transmisión y luego codifica Jpeg los bloques modificados utilizando una versión muy modificada de FJCore. (FJCore generalmente está bien hecho, pero se tuvo que modificar para que no se escriban los encabezados JFIF y para acelerar la inicialización de los diversos objetos). Todo esto se pasa a un servidor de medios propietario que usa un protocolo propietario basado aproximadamente en RTP.
Con un flujo de subida y cuatro transmisiones de 144x176, actualmente obtengo 5 fotogramas por segundo, usando un total de 474 Kbps (~ 82 Kbps / stream de video + 32 Kbps / audio), y masticando alrededor de 30% de CPU en mi caja de desarrollo La calidad no es buena, pero es aceptable para la mayoría de las aplicaciones de video chat.
Desde que publiqué mi pregunta original, ha habido varios intentos de implementar una solución. Probablemente lo mejor esté en el sitio web de SocketCoder aquí (y aquí ).
Sin embargo, debido a que el códec de video de estilo JPEG en movimiento de SocketCoder traduce la totalidad de cada cuadro en lugar de solo los bloques que han cambiado, mi suposición es que los requisitos de CPU y ancho de banda serán prohibitivos para la mayoría de las aplicaciones.
Desafortunadamente, mi propia solución va a tener que seguir siendo propietaria en el futuro previsible :-(.
Editar 3/07/10: Acabo de obtener permisos para compartir mis modificaciones a la biblioteca FJCore. He publicado el proyecto (sin ningún código de muestra, por desgracia) aquí:
http://www.alanta.com/Alanta.Client.Media.Jpeg.zip
Un ejemplo (muy difícil) de cómo usarlo:
public void EncodeAsJpeg()
{
byte[][,] raster = GetSubsampledRaster();
var image = new Alanta.Client.Media.Jpeg.Image(colorModel, raster);
EncodedStream = new MemoryStream();
var encoder = new JpegFrameEncoder(image, MediaConstants.JpegQuality, EncodedStream);
encoder.Encode();
}
public void DecodeFromJpeg()
{
EncodedStream.Seek(0, SeekOrigin.Begin);
var decoder = new JpegFrameDecoder(EncodedStream, height, width, MediaConstants.JpegQuality);
var raster = decoder.Decode();
}
La mayoría de mis cambios están en torno a las dos nuevas clases JpegFrameEncoder (en lugar de JpegEncoder) y JpegFrameDecoder (en lugar de JpegDecoder). Básicamente, el JpegFrameEncoder escribe el marco codificado sin ningún encabezado JFIF, y el JpegFrameDecoder decodifica el marco sin esperar que los encabezados JFIF le digan qué valores usar (se supone que va a compartir los valores de alguna otra manera fuera de banda) ) También crea instancias de cualquier objeto que necesite una sola vez (como "estático"), para que pueda crear una instancia de JpegFrameEncoder y JpegFrameDecoder rápidamente, con una sobrecarga mínima. Las clases preexistentes JpegEncoder y JpegDecoder deberían funcionar de forma similar a como lo han hecho siempre, aunque solo he probado un poco para confirmarlo.
Hay muchas cosas que me gustaría mejorar al respecto (no me gustan los objetos estáticos, deben crearse instancias y pasarse por separado), pero funciona bastante bien para nuestros propósitos en este momento. Espero que sea útil para otra persona. Veré si puedo mejorar el código / documentación / código de muestra / etc. si tengo tiempo.