Потоковая передача XNA через Expression Engine SDK для прямой трансляции дополненной реальности - PullRequest
1 голос
/ 08 марта 2011

Я пытаюсь написать приложение, которое сначала объединяет видео в игровой движок XNA, добавляет некоторый контент дополненной реальности, а затем передает обработанный контент другому пользователю. Все это должно происходить в реальном времени или почти в реальном времени. По сути, система будет выглядеть так:

Видео -> XNA (Игра) -> (???) -> Двигатель выражений -> Живой эфир -> Сеть -> Клиент

Чистый и элегантный способ сделать это состоит в том, чтобы обработать вывод XNA как LiveDeviceSource и передать его непосредственно в потоковое задание Expression Engine. Можно ли написать собственный LiveDeviceSource или что-то подобное для этого? По сути, кто-то знает, как создать пользовательский источник для механизма выражений, где я могу просто вставить буфер визуализации XNA прямо в кодировщик? Было бы довольно легко выгрузить буфер в файл, и механизм кодирования мог бы это закодировать, но я боюсь, что запись на диск будет слишком большой из-за времени, необходимого для записи на диск.

Альтернатива быстрому и грязному взлому - заставить механизм выражений сделать снимок экрана с выходным окном и затем передать его в поток. Я могу заставить Expression Engine делать снимки экрана, но не могу транслировать их в прямом эфире. Может кто-нибудь посоветовать, как делать оба одновременно?

Заранее извиняюсь за этот вопрос, который не был так хорошо сформирован, так как я все еще знакомлюсь с Expression Engine SDK. Для справки я использую XNA 4, MS Expression Engine 4 и Visual Studio 2010. Наша цель - в конечном итоге интегрировать эту технологию с готовящимся выпуском Goblin XNA.

Я также был бы открыт для предложений о других способах потоковой передачи живого видео напрямую из XNA. Мы не женаты на Expression Engine, просто это лучшее решение для потоковой передачи, с которым мы когда-либо сталкивались (у нас проблемы с ffmpeg).

1 Ответ

0 голосов
/ 15 июня 2011

Вам необходимо реализовать miindriver AVStream, чтобы завершить конвейер, создав драйвер, который распознается как живой источник (подробности см. Здесь http://msdn.microsoft.com/en-us/library/ff554228(v=VS.85).aspx). Другое решение - писать с использованием фильтров DirectShowFilter или MFT, но я не могу вам сильно помочь в этом отделе.

Я работал с кодировщиком выражений sdk, но я не нашел решения для того, о чем вы просили. Однако вы можете ОЧЕНЬ легко перенести данные изображения в Expression Encoder. Одним из способов было бы извлечь байты из объекта rendertarget и перенести их в кодировщик выражений любыми способами, которые вы предпочитаете (для этого подходит WCF), и восстановить данные в битовый массив для использования для потоковой передачи.

Я поместил свой источник для извлечения байтовых данных из Texture2D (и, следовательно, из RenderTarget2D), а затем для создания из них объекта Bitmap.

    public static Bitmap ToBitmap(this Microsoft.Xna.Framework.Graphics.Texture2D rd, int Width, int Height)
    {
        var Bmp = new Bitmap(Width, Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

        byte[] data = ToBytes(rd);

        var bmpData = Bmp.LockBits(new Rectangle(0, 0, rd.Width, rd.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

        System.Runtime.InteropServices.Marshal.Copy(data, 0, bmpData.Scan0, data.Length);

        Bmp.UnlockBits(bmpData);

        return Bmp;
    }

    public static byte[] ToBytes(this Microsoft.Xna.Framework.Graphics.Texture2D rd, byte[] data = null)
    {
        if (data == null || data.Length != 4 * rd.Height * rd.Width)
            data = new byte[4 * rd.Height * rd.Width];

        rd.GetData<byte>(data);

        SwapBytes(data);

        return data;
    }

    private static void SwapBytes(byte[] data)
    {
        System.Threading.Tasks.ParallelOptions po = new System.Threading.Tasks.ParallelOptions();
        po.MaxDegreeOfParallelism = -1;

        System.Threading.Tasks.Parallel.For(0, data.Length / 4, po, t =>
        {
            int bi = t * 4;
            byte temp = data[bi];
            data[bi] = data[bi + 2];
            data[bi + 2] = temp;
        });
    }

    public static void FromBytes(this Texture2D texture, byte[] bytes)
    {
        SwapBytes(bytes);

        texture.SetData<byte>(bytes);
    }

Надеюсь, я помог.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...