2009-11-20 3 views
16

Новый материал для веб-камеры в Silverlight 4 проклят прохладно. Выставляя его как кисть, он позволяет сценарии, выходящие за рамки всего, что есть в Flash.Потоковое видео с сайта Silverlight 4 (Beta)

В то же время доступ к веб-камере на месте кажется, что это только половина истории. Никто не покупает веб-камеру, поэтому они могут фотографировать себя и делать из них забавные лица. Они покупают веб-камеру, потому что хотят, чтобы другие люди увидели результирующий видеопоток, т. Е. Они хотят транслировать это видео в Интернет, проложить Skype или любой из десятков других сайтов/приложений для видеочата. И до сих пор я не понял, как это сделать с

Оказалось, что довольно просто получить контроль над исходным (Format32bppArgb отформатированным) байтом, как показано на рисунке here.

Но если мы не хотим передавать этот необработанный поток на сервер (который будет переваривать слишком большую пропускную способность), нам нужно каким-то образом закодировать его. И это сложнее. MS реализовала несколько кодеков в Silverlight, но, насколько я могу судить, все они ориентированы на декодирование видеопотока, а не на кодирование в первую очередь. И это не связано с тем, что я не могу понять, как получить прямой доступ, скажем, к кодеку H.264.

Есть тонна кодеков с открытым исходным кодом (например, в проекте ffmpeg here), но все они написаны на C, и они не выглядят легко переносимыми на C#. Если перевод строки 10000 + кода, которые выглядят, как это не ваша идея веселья :-)

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)]; 

Папка mooncodecs в рамках проекта Mono (here) имеет несколько аудиокодеки в C# (ADPCM и Ogg Vorbis), а также один видеокодек (Dirac), но все они, похоже, реализуют только часть декодирования своих соответствующих форматов, также как и реализации Java, из которых они были перенесены.

Я нашел кодек C# для Ogg Theora (csTheora, http://www.wreckedgames.com/forum/index.php?topic=1053.0), но опять же, это только декодирование, как и кодек jheora, на котором он основан.

Конечно, было бы проще переносить кодек из Java, чем из C или C++, но только видеокодеки java, которые я нашел, были только декодированными (например, jheora или jirac).

Так что я вернусь на квадратный. Похоже, что наши возможности подключения веб-камеры (или микрофона) через Silverlight к Интернету:

(1) Подождите, пока Microsoft предоставит вам некоторые рекомендации;

(2) Проведите мозговые циклы, перенося один из кодеков C или C++ на Silverlight-совместимый C#;

(3) Отправьте необработанный несжатый поток на сервер (или, возможно, слегка сжатый с помощью чего-то вроде zlib), а затем закодируйте его на стороне сервера; или

(4) Подождите, пока кто-нибудь умнее меня, чтобы понять это и предоставить решение.

Есть ли у кого-нибудь еще лучшее руководство? Я пропустил что-то, что просто ослепительно очевидно для всех остальных? (Например, есть ли у Silverlight 4 какие-то классы, которые я пропустил, которые позаботятся об этом?)

ответ

3

Я думал, что позволю заинтересованным людям понять подход, который я действительно принял. Я использую CSpeex для кодирования голоса, но я написал свой собственный блочный видеокодек для кодирования видео. Он делит каждый фрейм на 16x16 блоков, определяет, какие блоки были достаточно изменены, чтобы гарантировать передачу, а затем Jpeg-кодирует измененные блоки с использованием сильно модифицированной версии FJCore. (FJCore, как правило, хорошо сделан, но его нужно было модифицировать, чтобы не писать заголовки JFIF, а также ускорить инициализацию различных объектов.) Все это передается на собственный медиасервер, используя проприетарный протокол, основанный на RTP.

С одним потоком вверх и четырьмя потоками вниз на 144x176 я в настоящее время получаю 5 кадров в секунду, используя в общей сложности 474 Кбит/с (~ 82 Кбит/с/видеопоток + 32 Кбит/с/аудио) и пережевывая около 30 % CPU на моем блоке dev. Качество не очень хорошее, но оно приемлемо для большинства приложений для видеочатов.

Поскольку я опубликовал свой первоначальный вопрос, было предпринято несколько попыток реализовать решение. Вероятно, лучше всего на сайте SocketCoder herehere).

Однако, поскольку видеокодек в формате JPEG в формате SocketCoder в формате JPEG преобразует все кадры, а не только измененные блоки, я полагаю, что требования к процессору и пропускной способности будут запретительными для большинства приложений.

К сожалению, мое решение будет иметь оставаться собственностью в обозримом будущем :-(

Редактировать 7/3/10:.. Я только что получил разрешение поделиться изменениями в библиотеку FJCore I» ве опубликовал проект (без каких-либо примеров кода, к сожалению) здесь:

http://www.alanta.com/Alanta.Client.Media.Jpeg.zip

(очень грубый) пример того, как использовать его:

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(); 
    } 

Большинство моих изменений связаны с двумя новыми классами JpegFrameEncoder (вместо JpegEncoder) и JpegFrameDecoder (вместо JpegDecoder). В принципе, JpegFrameEncoder записывает кодированный кадр без заголовков JFIF, а JpegFrameDecoder декодирует кадр, не ожидая, что заголовки JFIF скажут, какие значения использовать (предполагается, что вы будете делиться значениями в каком-то другом, внеполосном режиме). Он также создает экземпляры любых объектов, которые ему нужны только один раз (как «статические»), чтобы вы могли быстро создавать JpegFrameEncoder и JpegFrameDecoder с минимальными издержками. Существующие классы JpegEncoder и JpegDecoder должны работать практически так же, как и всегда, хотя я только что провел очень немного тестирования, чтобы подтвердить это.

Есть много вещей, которые я хотел бы улучшить (мне не нравятся статические объекты - они должны быть созданы и переданы отдельно), но он работает достаточно хорошо для наших целей на данный момент. Надеюсь, это полезно для кого-то другого. Я посмотрю, смогу ли я улучшить код/​​документацию/пример кода/etc. если у меня будет время.

+0

Спасибо, например, Ken. У меня есть приложение silverlight, которое я ЛЮБЛЮ, чтобы разрешить загрузку созданных пользователем видео в facebook. Однако, несмотря на то, что я работал с m-jpeg-кодированием, это не поддерживаемый кодек через FB. Grrrr. Жаль, что MS не помогает нам здесь. – tyshock

3

Я только что получил этот ответ от Джейсона Клари на моем блоге:


Видел ваш пост в блоге Майка Taulty в о VideoSink/AudioSink в Silverlight 4 беты.

Я думал, что хочу отметить, что OnSample от VideoSink дает вам один несжатый 32-битный ARGB-кадр, который можно скопировать прямо в WritableBitmap.

С этим в руке захватите FJCore, кодек jpeg на C# и измените его, чтобы не выводить заголовок JFIF. Затем просто напишите их один за другим, и у вас есть кодек Motion JPEG. RFC2435 объясняет, как передать это в RTP-пакеты для потоковой передачи RTSP.

Сжатие аудио PCM в ADPCM довольно просто, но пока я не нашел готовой реализации. В RFC3551 объясняется, как переносить PCM или ADPCM в пакеты RTP.

Также должно быть достаточно легко набить MJPEG и PCM или ADPCM в файл AVI. MS имеет несколько достойных документов в модифицированном формате RIFF от AVI, и MJPEG и ADPCM являются широко поддерживаемыми кодеками.

Это все равно.

Конечно, после того, как вы преодолеете все эти проблемы, следующая бета-версия, вероятно, выйдет с поддержкой поддержки сжатия и потоковой передачи на WMS с гораздо лучшими кодеками WMV.


Думал, что опубликую его. Это лучшее предложение, которое я видел до сих пор.

0

Я добавлю еще один комментарий. Я только что услышал сегодня от контакта Microsoft, что Microsoft не планирует добавить любую поддержку для кодирования и потоковой передачи аудио и видео в потоковом потоке в Silverlight, так что опция № 1, кажется, находится вне таблицы, по крайней мере, сейчас. Я предполагаю, что выяснение поддержки этого будет ответственностью сообщества, то есть до вас и меня.

0

Stop-Gap?

Можно ли использовать Кодер Windows Media в качестве метода сжатия для необработанного видео Silverlight? После захвата до Хранение ISO, кодируйте w/WME и отправляйте на сервер через WebClient. Две большие вопросы:

  • Требуется пользователю установить Кодер
  • WME больше не будет поддерживаться

Похоже, что может быть затычка решение, пока что-то лучше не приходит вдоль. Я еще не работал w/WME, хотя я не знаю, насколько это возможно. Мысли?

+0

Помимо необходимости устанавливать Windows Media Encoder, Silverlight не сможет разговаривать с WME, если приложение не работает вне браузера и в режиме полного доверия: в этот момент уже не совсем понятно, почему мы должны делать это в Silverlight :-). –

-4

Вы пробовали новый Expression 4 Encoders?

http://www.microsoft.com/expression/products/EncoderPro_Overview.aspx

+0

Если мне не хватает чего-то огромного, WME не является решением для клиентской части Silverlight в режиме реального времени. –

+0

Вы что-то пропустили. Это не WME. Потому что это QuickTime, H.264, AAC-LC, которые в настоящее время не поддерживаются в Windows Media Encoder. Он также поддерживает AVI, MPEG-2 и другие. Не совсем уверен в вашем вопросе, но это ядро ​​инструмента Microsoft Expressions Endcoder, которое является клиентским приложением и поддерживает не только формат Windows Media. –

+0

Ник, акцент Кен не на «WME», а на «в реальном времени». –