Как получить серию изображений из потока пользовательского интерфейса в поток рисования в Silverlight 5 с помощью XNA

в Silverlight я пытаюсь получить кадры потока с веб-камеры (в прямом эфире), текстурированные на серии 3D-квадратов. Я использую VideoSink в классе контроллера веб-камеры в классе контроллера веб-камеры. Затем я рисую четырехугольники в DrawingSurface. Но я продолжаю работать в CrossAppDomainMarshaledException. В качестве решения я пытаюсь использовать Dispatcher.BeginInvoke, но иногда кажется, что код в BeginInvoke перескакивает через поток или выходит из него. Как человек относится к таким вещам?

    //Video sink capture
    // Is called every time the webcam provides a complete frame (Push)   
    protected override void OnSample(long sampleTime, long frameDuration, byte[] sampleData)
    {
        System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() =>
        {
            WriteableBitmap bmp = new WriteableBitmap(vidFormat.PixelWidth, vidFormat.PixelHeight);
            RaiseFrameCapture(new FrameCapturedEventArgs { Frame = bmp.FromByteArray(sampleData) });
        });
    }

    //Capture from sink into WebCamController
    void sink_FrameCaptured(object sender, FrameCapturedEventArgs e)
    {

        //List<WriteableBitmap>
        _WebCamSource.AddImage(e.Frame.Clone());

    }


    //XNA draw event handler
    private void DrawingSurface_Draw(object sender, DrawEventArgs e)
    {
        List<WriteableBitmap> frames = new List<WriteableBitmap>();

        if (webCamSource.Frames.Count > 0)
        {
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                frames = new List<WriteableBitmap>(webCamSource.Frames.ToArray());

            });
        }

        Draw(frames);

        e.InvalidateSurface();
    }

person Michaud    schedule 09.10.2011    source источник
comment
Теперь я ломал голову над этим и после того, как почти сдался, краткий (все еще слишком длинный) экскурс в THREE.js, который классный, но html не дал мне возможности доступа к веб-камере, я столкнулся со следующим решением: _texture.SetData‹int›(image.Pixels); Почему вы, ребята, не дали мне это простое решение. Никаких маршалинговых потоков, ничего, просто установка данных... Я очень разочарован в вас. Позор тебе ;)   -  person Michaud    schedule 17.10.2011


Ответы (1)


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

В классическом конвейере рендеринга Silverlight вы декларативно строите визуальное дерево и отправляете в него свои изменения. Цикл рендеринга уходит из поля зрения, и вам редко приходится с ним возиться.

Поэтому вы хотите как можно быстрее внести изменения в визуальное дерево. Если вы обновите визуальное дерево в другом потоке, а не в потоке пользовательского интерфейса (тот, который запущен), обновление может произойти во время рендеринга, что приведет к катастрофе. Поэтому поток пользовательского интерфейса предоставляет насос сообщений, который можно использовать с помощью Dispatcher.BeginInvoke, чтобы обеспечить безопасность потока.

С XNA у вас нет ничего из этого... Потому что вы реализуете свой собственный конвейер рендеринга и имеете полный контроль над ним.

Каждый раз, когда вы обрабатываете кадр веб-камеры, устанавливайте его в контроллере веб-камеры (используя блокировку). В каждом кадре XNA, если контроллер веб-камеры получил новый кадр, получить кадр веб-камеры (используя блокировку) и обновить текстуру XNA (не создавать новую текстуру для каждого кадра, это НЕ эффективно). Затем визуализируйте свой 3D-объект, используя эту текстуру.

person Eilistraee    schedule 23.10.2011