Sign in to follow this  

slimdx, directshow.net and vmr9 problems

This topic is 3114 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey all, I'm progressing well on my current project but am looking to integrate VMR9 with my project. I ended up sticking with vb.net rather than porting everything I had over to C#.. thanks to you guys my project is getting much bigger than I anticipated (because the possibilities seem much less bounded). So here's the problem.. which I'm hoping is a simple one to deal with. I'm porting the bitmap mixer sample in directshow.net to use vb.net and slimdx. When I start the graph I get an error that one or more of the arguments is invalid IF I run the mixersettings method. If I leave it out then I can display the video at least within my form. My thoughts are that it is related to the "unmanagedsurface"? Am I doing this wrong? Related statements from mixersettings..
        D3D = New Direct3D
        device = New Device(D3D, 0, DeviceType.Hardware, Me.Handle, CreateFlags.HardwareVertexProcessing, presentParams)

Surface.FromFile(_surface, "c:\users\tanczos\desktop\rider.png", Filter.None, 0)
unmanagedSurface = _surface.ComPointer
...
        alphaBmp = New VMR9AlphaBitmap()
        alphaBmp.dwFlags = VMR9AlphaBitmapFlags.EntireDDS
        alphaBmp.pDDS = unmanagedSurface
        alphaBmp.rDest = GetDestRectangle()
        alphaBmp.fAlpha = 1.0F

        ' Set Alpha Bitmap Parameters
        hr = mixerBitmap.SetAlphaBitmap(alphaBmp)
        DsError.ThrowExceptionForHR(hr)

Full source:

Imports System
Imports System.Drawing
Imports System.Collections
Imports System.ComponentModel
Imports System.Windows.Forms
Imports System.Runtime.InteropServices

Imports DirectShowLib
Imports SlimDX.Direct3D9

Imports Microsoft.Win32


Public Class Form1

    Private colorKey As Color = Color.Violet

    ' Managed Direct3D magic number to retrieve unmanaged Direct3D interfaces
    Private Const DxMagicNumber As Integer = -759872593

    Private device As Device = Nothing
    Public D3D As Direct3D
    ' A Managed Direct3D device

    Private presentParams As PresentParameters

    Private _surface As Surface
    ' A Direct3D suface filled with alphaBitmap

    Private unmanagedSurface As IntPtr
    ' A pointer on the unmanaged surface

    Private graphBuilder As IFilterGraph2
    Private mediaControl As IMediaControl
    Private vmr9 As IBaseFilter
    Private mixerBitmap As IVMRMixerBitmap9
    Private windowlessCtrl As IVMRWindowlessControl9

    Private handlersAdded As Boolean = False

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    End Sub

    Private Sub InitializeDirect3D()
        ' Basic Presentation Parameters...
        presentParams = New PresentParameters()
        presentParams.Windowed = True
        presentParams.SwapEffect = SwapEffect.Discard

        ' Assume a hardware Direct3D device is available
        ' Add MultiThreaded to be safe. Each DirectShow filter runs in a separate thread...
        D3D = New Direct3D
        device = New Device(D3D, 0, DeviceType.Hardware, Me.Handle, CreateFlags.HardwareVertexProcessing, presentParams)

        ' Create a surface from our alpha bitmap
        Surface.FromFile(_surface, "c:\users\tanczos\desktop\rider.png", Filter.None, 0)

        ' Get the unmanaged pointer
        unmanagedSurface = _surface.ComPointer   ' ??  Surface.GetObjectByValue(DxMagicNumber)

    End Sub

    Protected Overloads Sub Dispose()
        If disposing Then
            If components IsNot Nothing Then
                components.Dispose()
            End If
        End If

        ' Clean-up DirectShow interfaces
        CloseInterfaces()

        ' Dispose Managed Direct3D objects
        _surface.Dispose()
        device.Dispose()

        MyBase.Dispose()
    End Sub

    Private Sub CloseInterfaces()
        If mediaControl IsNot Nothing Then
            mediaControl.[Stop]()
        End If

        If handlersAdded Then
            'RemoveHandlers()
        End If

        If vmr9 IsNot Nothing Then
            Marshal.ReleaseComObject(vmr9)
            vmr9 = Nothing
            windowlessCtrl = Nothing
            mixerBitmap = Nothing
        End If

        If graphBuilder IsNot Nothing Then
            Marshal.ReleaseComObject(graphBuilder)
            graphBuilder = Nothing
            mediaControl = Nothing
        End If

        'menuMixer.Enabled = False
    End Sub

    Private Sub BuildGraph(ByVal fileName As String)
        Dim hr As Integer = 0

        Try
            graphBuilder = DirectCast(New FilterGraph(), IFilterGraph2)
            mediaControl = DirectCast(graphBuilder, IMediaControl)

            vmr9 = DirectCast(New VideoMixingRenderer9(), IBaseFilter)
            ConfigureVMR9InWindowlessMode()

            hr = graphBuilder.AddFilter(vmr9, "Video Mixing Renderer 9")
            DsError.ThrowExceptionForHR(hr)

            hr = graphBuilder.RenderFile(fileName, Nothing)
            DsError.ThrowExceptionForHR(hr)

            mixerBitmap = DirectCast(vmr9, IVMRMixerBitmap9)

            SetMixerSettings()

        Catch e As Exception
            CloseInterfaces()
            MessageBox.Show("An error occured during the graph building : " & vbCr & vbLf & vbCr & vbLf & e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.[Error])
        End Try
    End Sub

    Private Sub ConfigureVMR9InWindowlessMode()
        Dim hr As Integer = 0

        Dim filterConfig As IVMRFilterConfig9 = DirectCast(vmr9, IVMRFilterConfig9)

        ' Not really needed for VMR9 but don't forget calling it with VMR7
        hr = filterConfig.SetNumberOfStreams(1)
        DsError.ThrowExceptionForHR(hr)

        ' Change VMR9 mode to Windowless
        hr = filterConfig.SetRenderingMode(VMR9Mode.Windowless)
        DsError.ThrowExceptionForHR(hr)

        windowlessCtrl = DirectCast(vmr9, IVMRWindowlessControl9)

        ' Set "Parent" window
        hr = windowlessCtrl.SetVideoClippingWindow(Me.Handle)
        DsError.ThrowExceptionForHR(hr)

        ' Set Aspect-Ratio
        hr = windowlessCtrl.SetAspectRatioMode(VMR9AspectRatioMode.LetterBox)
        DsError.ThrowExceptionForHR(hr)

        ' Add delegates for Windowless operations
        AddHandlers()

        ' Call the resize handler to configure the output size
        MainForm_ResizeMove(Nothing, Nothing)
    End Sub

    Private Sub SetMixerSettings()
        Dim hr As Integer = 0
        Dim alphaBmp As VMR9AlphaBitmap

        ' Set Alpha Bitmap Parameters for using a Direct3D surface
        alphaBmp = New VMR9AlphaBitmap()
        alphaBmp.dwFlags = VMR9AlphaBitmapFlags.EntireDDS
        alphaBmp.pDDS = unmanagedSurface
        alphaBmp.rDest = GetDestRectangle()
        alphaBmp.fAlpha = 1.0F
        ' Note : Alpha values from the bitmap are cumulative with the fAlpha parameter.
        ' Example : texel alpha = 128 (50%) & fAlpha = 0.5f (50%) = effective alpha : 64 (25%)

        ' Set Alpha Bitmap Parameters
        hr = mixerBitmap.SetAlphaBitmap(alphaBmp)
        DsError.ThrowExceptionForHR(hr)
    End Sub

    Private Function GetDestRectangle() As NormalizedRect
        Dim hr As Integer = 0
        Dim width As Integer, height As Integer, arW As Integer, arH As Integer
        Dim rect As New NormalizedRect()

        hr = windowlessCtrl.GetNativeVideoSize(width, height, arW, arH)
        DsError.ThrowExceptionForHR(hr)

        ' Position the bitmap in the middle of the video stream.
        If width >= height Then
            rect.top = 0.0F
            rect.left = (1.0F - (CSng(height) / CSng(width))) / 2
            rect.bottom = 1.0F
            rect.right = rect.left + CSng(height) / CSng(width)
        Else
            rect.top = (1.0F - (CSng(width) / CSng(height))) / 2
            rect.left = 0.0F
            rect.right = rect.top + CSng(width) / CSng(height)
            rect.bottom = 1.0F
        End If

        Return rect
    End Function

    Private Sub AddHandlers()
        ' Add handlers for VMR purpose
        AddHandler Me.Paint, AddressOf MainForm_Paint
        ' for WM_PAINT
        AddHandler Me.Resize, AddressOf MainForm_ResizeMove
        ' for WM_SIZE
        AddHandler Me.Move, AddressOf MainForm_ResizeMove
        ' for WM_MOVE
        'AddHandler SystemEvents.DisplaySettingsChanged, AddressOf SystemEvents_DisplaySettingsChanged
        ' for WM_DISPLAYCHANGE
        handlersAdded = True
    End Sub

    Private Sub RemoveHandlers()
        ' remove handlers when they are no more needed
        handlersAdded = False
        RemoveHandler Me.Paint, AddressOf MainForm_Paint
        RemoveHandler Me.Resize, AddressOf MainForm_ResizeMove
        RemoveHandler Me.Move, AddressOf MainForm_ResizeMove
        RemoveHandler SystemEvents.DisplaySettingsChanged, AddressOf SystemEvents_DisplaySettingsChanged
    End Sub

    Private Sub RunGraph()
        If mediaControl IsNot Nothing Then
            Dim hr As Integer = mediaControl.Run()
            DsError.ThrowExceptionForHR(hr)
        End If
    End Sub

    Private Sub StopGraph()
        If mediaControl IsNot Nothing Then
            Dim hr As Integer = mediaControl.[Stop]()
            DsError.ThrowExceptionForHR(hr)
        End If
    End Sub

    Private Sub MainForm_Paint(ByVal sender As Object, ByVal e As PaintEventArgs)

        If windowlessCtrl IsNot Nothing Then
            Dim hdc As IntPtr = e.Graphics.GetHdc()
            Dim hr As Integer = windowlessCtrl.RepaintVideo(Me.Handle, hdc)
            e.Graphics.ReleaseHdc(hdc)
        End If
    End Sub

    Private Sub MainForm_ResizeMove(ByVal sender As Object, ByVal e As EventArgs)
        If windowlessCtrl IsNot Nothing Then
            Dim hr As Integer = windowlessCtrl.SetVideoPosition(Nothing, DsRect.FromRectangle(Me.ClientRectangle))
        End If
    End Sub

    Private Sub SystemEvents_DisplaySettingsChanged(ByVal sender As Object, ByVal e As EventArgs)
        If windowlessCtrl IsNot Nothing Then
            Dim hr As Integer = windowlessCtrl.DisplayModeChanged()
        End If
    End Sub


    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        BuildGraph("C:\Users\Tanczos\Desktop\My Productions\door_scene_final_3.avi")
        RunGraph()
    End Sub
End Class


Any ideas? - Michael Tanczos

Share this post


Link to post
Share on other sites
Unfortunately I know almost nothing about DirectShow, but from what I can see your use of SlimDX seems fine. You say this was working with MDX, but now it's not with SlimDX? If so, posting the working equivalent MDX code would probably help.

Also, are you getting an error from SlimDX or DirectShow.Net? Try enabling the debug runtimes as well to see if you can get a more detailed error (does DirectShow support the debug runtimes?).

Share this post


Link to post
Share on other sites
The line I'm getting an error on (after some modification) is within the SetMixerSettings() function:

If I leave the line as is:
alphaBmp.pDDS = unmanagedSurface

I get the error (when trying to run the graph):
An error occured during the graph building:
One or more arguments are invalid


If I change it to alphbaBmp.pDDS = _surface.ComPointer

I get the error (when trying to run the graph):
An error occured during the graph building:
Object reference not set to an instance of an object


The original code gets the unmanagedsurface through:
private const int DxMagicNumber = -759872593;
unmanagedSurface = surface.GetObjectByValue(DxMagicNumber);


Honestly, I'm not sure how to get the unmanaged surface pointer through the slimDX surface object.. my assumption is that it was ComPointer but I'm not entirely sure. Am I creating the surface from a file incorrectly using slimDX? If that isn't incorrect, then how do I get the unmanaged surface pointer?

- Michael Tanczos





Share this post


Link to post
Share on other sites
ComPointer is indeed the member you should use. I'm wondering though how _surface is getting initialized. Is that your entire program listing? If so, I would have expected a NullReferenceException on Surface.FromFile, because that method expects a previously constructed surface to which to load the image data.

I'd suggest calling Surface.CreateOffscreenPlain first to initialize a fresh surface, and then calling Surface.FromFile to load the image data onto that surface.

Share this post


Link to post
Share on other sites
Thanks for the help. I have it working now, but I'm going to post some issues with this so others may use the solution. I later added the surface.createoffscreenplain and that worked to create the surface.. e.g.:


_surface = Surface.CreateOffscreenPlain(device, 720, 480, Format.A8R8G8B8, Pool.SystemMemory)

Surface.FromFile(_surface, "lower_third_test.png", Filter.None, 0)

alphaBmp = New VMR9AlphaBitmap()
alphaBmp.dwFlags = VMR9AlphaBitmapFlags.EntireDDS
alphaBmp.pDDS = _surface.ComPointer
alphaBmp.hdc = Nothing
alphaBmp.rDest = GetDestRectangle()
alphaBmp.fAlpha = 1.0F

hr = mixerBitmap.SetAlphaBitmap(alphaBmp)
DsError.ThrowExceptionForHR(hr)




Here is some reference info I found regarding setalphabitmap problems:

Some of the reasons that SetAlphaBitmap can return E_INVALIDARG:


  • The Direct3D surface was not allocated from the D3DPOOL_SYSTEMMEM pool.
  • Invalid surface format. If a Direct3D surface is used, the surface format must be D3DFMT_X8R8G8B8 or D3DFMT_A8R8G8B8. If the surface format is D3DFMT_A8R8G8B8, the VMR9AlphaBitmap_SrcColorKey flag cannot be used.
  • The source rectangle (rSrc) exceeds the boundaries of the Direct3D surface.
  • The source rectangle is empty.
  • The dwFilterMode member contains an invalid combination of flags.
  • The bitmap (or source rectangle) exceeds the maximum texture size for the Direct3D device.



In this case, the problem was that I was creating a surface from pool.default rather than Pool.SystemMemory.

Once again, thanks for the help.

- Michael Tanczos

Share this post


Link to post
Share on other sites

This topic is 3114 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this