Подтвердить что ты не робот

Потоковая передача веб-камеры из Silverlight 4 (бета-версия)

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

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

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

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

Существует тонна кодеков с открытым исходным кодом (например, в проекте ffmpeg здесь), но все они написаны на 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 (здесь) содержит несколько аудиокодеков в С# (ADPCM и Ogg Vorbis) и один видеокодек ( Dirac), но все они, похоже, реализуют только часть декодирования своих соответствующих форматов, также как и реализации Java, из которых они были перенесены.

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

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

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

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

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

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

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

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

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

    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. если у меня есть время.

Ответ 2

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


Увидел свой пост в блоге Майка Таута о VideoSink/AudioSink в бета-версии Silverlight 4.

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

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

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

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

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

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


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

Ответ 3

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

Ответ 4

затычка?

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

  • Требуется, чтобы пользователь установил кодировщик
  • WME больше не будет поддерживаться

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