Render video off-screen.

Jun 3, 2011 at 8:53 PM
Edited Jun 4, 2011 at 8:18 PM

I am currently developing an application which is very dynamic, and has lot's of little bells and whistles, and i can't afford to spend a lot of time learning directshow, but I have a simple request. I need to be able to render video to a D3DImage in code, off the screen, and then set it as a source on multiple images. For some reason, when I create MediaUriElement in code, it does not work. Please advise.

What i want to do:

 

MediaUriElement m = new MediaUriElement();

m.Source = new Uri("c:\temp\video.avi");
m.Play();

Image img = new Image();
img.Source = m.D3DImage;

Image img2 = new Image();
img2.source = m.D3DImage;

Jun 4, 2011 at 8:16 PM
Edited Jun 4, 2011 at 8:17 PM

I've figured out a workaround for this. It's not very elegant, but it works for me. If I will have some time in the future, i will rewrite this whole thing, and leave only the options that i need, and provide an interface (D3DImage) as an output. My current solution is:

XAML File:

 

<UserControl
    x:Class="N.DMediaPlayer"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:m="clr-namespace:WPFMediaKit.DirectShow.Controls;assembly=WPFMediaKit">
    <m:MediaUriElement x:Name="m" LoadedBehavior="Manual" />
</UserControl>
CS Class:
using System;
using System.Windows;
using System.Windows.Controls;
using WPFMediaKit.DirectShow.MediaPlayers;
using System.Windows.Interop;

namespace N
{
    /// <summary>
    /// This is a dummy INTERFACE module for WpfMediaKit::MediaUriElement. It provides a subset of properties,
    /// and a WPF initializer which is a workaround for the control not being able to self-initialize when created in C#
    /// </summary>
    public partial class DMediaPlayer : UserControl
    {
        public Uri Source { get { return m.Source; } set { m.Source = value; } }
        public long MediaPosition { get { return m.MediaPosition; } set { m.MediaPosition = value; } }
        public long MediaDuration { get { return m.MediaDuration; } }
        public MediaPositionFormat PreferedPositionFormat { get { return m.PreferedPositionFormat; } set { m.PreferedPositionFormat = value; } }
        public MediaPositionFormat CurrentPositionFormat { get { return m.CurrentPositionFormat; } }
        
        public bool Loop { get { return m.Loop; } set { m.Loop = value; } }
        public void Pause() { m.Pause(); }
        public void Play() { m.Play(); }
        public void Stop() { m.Stop(); }
        public D3DImage CurrentVideoImage { get { return m.CurrentVideoImage; } }

        public event RoutedEventHandler MediaOpened;
        public event RoutedEventHandler MediaEnded;
        public event EventHandler<MediaFailedEventArgs> MediaFailed;
        public string AudioRenderer { get { return m.AudioRenderer; } set { m.AudioRenderer = value; } }
        public VideoRendererType VideoRenderer { get { return m.VideoRenderer; } set { m.VideoRenderer = value; } }
        public double Volume { get { return m.Volume; } set { m.Volume = value; } }

        public DMediaPlayer()
        {
            InitializeComponent();
            m.MediaOpened += (s, e) => { if (this.MediaOpened != null)this.MediaOpened(s, e); };
            m.MediaEnded += (s, e) => { if (this.MediaEnded != null)this.MediaEnded(s, e); };
            m.MediaFailed += (s, e) => { if (this.MediaFailed != null)this.MediaFailed(s, e); };
        }

    }
}

And, finally, here's how to use it:
DMediaPlayer player = new DMediaPlayer();
player.Source = new Uri("c:/temp/video.wmv");
player.Play();

/* Create an Image, (in XAML, or c#, then set source)*/

Image img = new Image();
img.Source = player.CurrentVideoImage;

/*
This should work rather well. Please note that I modified
WPFMediaKit's D3DRenderer to expose the D3DImage as [CurrentVideoImage], and removed the Image control from it to prevent unnecessary rendering.
*/