Наконец блок будут всегда называть (хорошо не действительно всегда ...), даже если исключение будет выдано, или оператор возврата достигнут (хотя это может быть языковозависимым). Это - способ очистить это, Вы знаете, будет всегда называться.
Я решил сообщить заинтересованным лицам, какой подход я использовал на самом деле. Для кодирования голоса я использую CSpeex, а для кодирования видео я написал свой собственный блочный видеокодек. Он делит каждый кадр на блоки 16x16, определяет, какие блоки достаточно изменились, чтобы их можно было передать, а затем Jpeg-кодирует измененные блоки с помощью сильно модифицированной версии FJCore. (FJCore в целом хорошо сделан, но его пришлось модифицировать, чтобы не писать заголовки JFIF и ускорить инициализацию различных объектов). Все это передается на проприетарный медиа-сервер по проприетарному протоколу, примерно основанному на RTP.
С одним потоком вверх и четырьмя потоками вниз при 144x176, я в настоящее время получаю 5 кадров в секунду, используя в общей сложности 474 Кбит/с (~82 Кбит/с / видео поток + 32 Кбит/с / аудио), и потребляя около 30% процессора на моей приставке. Качество не очень хорошее, но приемлемое для большинства приложений видеочата.
С тех пор, как я опубликовал свой первоначальный вопрос, было предпринято несколько попыток реализовать решение. Вероятно, лучшая - на сайте SocketCoder здесь (и здесь).
Однако, поскольку видеокодек SocketCoder motion JPEG-стиля переводит весь кадр целиком, а не только измененные блоки, я предполагаю, что требования к процессору и пропускной способности будут непомерно высоки для большинства приложений.
К сожалению, мое собственное решение в обозримом будущем придется оставить закрытым :-(.
Редактирование 7/3/10: Я только что получил разрешение поделиться своими модификациями библиотеки FJCore. Я выложил проект (без примера кода, к сожалению) здесь:
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 должны работать практически так же, как и всегда, хотя я провел лишь очень небольшое тестирование, чтобы подтвердить это.
Есть много вещей, которые я хотел бы улучшить (мне не нравятся статические объекты - они должны инстанцироваться и передаваться отдельно), но на данный момент это работает достаточно хорошо для наших целей. Надеюсь, это будет полезно для кого-то еще. Я посмотрю, смогу ли я улучшить код/документацию/пример кода/и т.д., если у меня будет время.
Я только что получил этот ответ от Джейсона Клэри в своем блоге:
Видел ваше сообщение в блоге Майка Тэлти о VideoSink / AudioSink в бета-версии Silverlight 4.
Я подумал, что укажу Out, что OnSample VideoSink дает вам один несжатый ARGB-кадр 32bpp, который можно скопировать прямо в WritableBitmap.
С его помощью возьмите FJCore, кодек jpeg на C #, и измените его, чтобы не выводить заголовок JFIF. Затем просто запишите их один за другим, и вы получите кодек Motion JPEG. RFC2435 объясняет, как вставить это в пакеты RTP для потоковой передачи RTSP.
Сжатие звука PCM в ADPCM также довольно просто, но я еще не нашел готовой реализации. RFC3551 объясняет, как поместить PCM или ADPCM в пакеты RTP.
Также должно быть достаточно легко вставить MJPEG и PCM или ADPCM в файл AVI. У MS есть неплохая документация по модифицированному формату AVI RIFF, и как MJPEG, так и ADPCM являются широко поддерживаемыми кодеками.
В любом случае это начало.
Конечно, если вы пройдете через все эти проблемы, вероятно, выйдет следующая бета-версия. с встроенной поддержкой сжатия и потоковой передачи в WMS с гораздо лучшими кодеками WMV.
Подумал, что выложу это. Это лучшее предложение, которое я когда-либо видел.
следующая бета-версия, вероятно, выйдет с встроенной поддержкой сжатия и потоковой передачи в WMS с гораздо лучшими кодеками WMV.Подумал, что выложу это. Это лучшее предложение, которое я когда-либо видел.
следующая бета, вероятно, выйдет с встроенной поддержкой сжатия и потоковой передачи в WMS с гораздо лучшими кодеками WMV.Подумал, что выложу это. Это лучшее предложение, которое я когда-либо видел.
Я добавлю еще один комментарий. Я только что услышал сегодня от контактного лица Microsoft, что Microsoft не планирует добавлять в Silverlight какую-либо поддержку восходящего аудио и видео кодирования / потоковой передачи, поэтому вариант № 1, похоже, не рассматривается, по крайней мере, на данный момент . Я предполагаю, что поиск поддержки для этого будет обязанностью сообщества, то есть до вас и меня.
Stop-Gap?
Можно ли использовать Windows Media Encoder в качестве метода сжатия необработанного видео, предоставляемого Silverlight? После захвата в хранилище ISO закодируйте с WME и отправьте на сервер через WebClient . Две большие проблемы:
Похоже, это может быть временным решением, пока не появится что-то лучшее. Я раньше не работал с WME , поэтому не знаю, насколько это возможно. Мысли?
Вы пробовали новые кодировщики Expression 4?
http://www.microsoft.com/expression/products/EncoderPro_Overview.aspx