none
Drawing on top of DirectShow - desperate

    Question

  • Hi,

    I am working on a project in which I need to draw rectangles and points on top of a playing videoclip.

    First I did this with a DexterLib function library which exported frames to images. But because exporting images was too slow and because it did not support enough video formats I had to switch to DirectShow (which supports both AVI and MPG).

    DirectShow is new to me but I was able to make it run videoclips. However it slipped my mind that drawing on top of DirectShow is a nearly impossible task.

    Earlier I tried to draw on top of them with DirectDraw 7 but that gave me all kind of flickering when it was finally integrated. It made me lose several weeks.

    I read something about a video mixing renderer, is that what I need to use? I found NO documentation on how to draw even very simple things like Rectangles on top of it. The only documentation I found were references and examples of all other kind of tasks which are not really related.

    ( I've been working in C#.NET so far, but even documentation in C++ would be a nice start. )

    I am pretty desperate and to be honest I would cancel the project if I could. But this project is my final work as a student Industrial Engineer in the field of Electronics. So I can not afford a failure. It is true that they say that DirectShow is about the hardest there is. I never came in touch with something that overwhelms me as much as this.

    I really hope that somebody in this forum can help me. If you know at least something that could be relevant or helpful, please do not hesitate. I'm at the end of inspiration.

    Thank you in advance for all possible help.
    Saturday, January 27, 2007 6:01 PM

All replies

  • Are you familar with http://DirectShowNet.SourceForge.net?  It has some samples that might be useful.  In particular, you might check out Samples\VMR9\BitmapMixer:

    BitmapMixer is an example of how to draw things over a video using VMR9.

    This sample is mainly built around the IVMRMixerBitmap9 interface. This interface
    accept bitmaps as a GDI Device Context or as a Direct3D Surface. The main advantage
    of the Direct3D Surface is that it enables the use of true alpha transparency. GDI DC
    don't support alpha bitmap and transparency is accomplished by using color keying.

    Could be a place to start.

    ---

    Co-author DirectShowNet

    Saturday, January 27, 2007 6:35 PM
  • That really is great stuff :) I will look deeper into this.

    It looks like this will do the trick :)

    Thank you very much!
    Saturday, January 27, 2007 8:29 PM
  •  LGS wrote:

    Are you familar with http://DirectShowNet.SourceForge.net? It has some samples that might be useful. In particular, you might check out Samples\VMR9\BitmapMixer:

    BitmapMixer is an example of how to draw things over a video using VMR9.

    This sample is mainly built around the IVMRMixerBitmap9 interface. This interface
    accept bitmaps as a GDI Device Context or as a Direct3D Surface. The main advantage
    of the Direct3D Surface is that it enables the use of true alpha transparency. GDI DC
    don't support alpha bitmap and transparency is accomplished by using color keying.

    Could be a place to start.

    ---

    Co-author DirectShowNet


    Your advice was really great. I have been using the Direct 3D surfaces so far and it finally works :).

    However I am having one more problem, namely speed. At the moment I am using a new Surface every time I paint something new. (The function-code is listed below.)
    - Is this the correct way of working, or is there a better alternative?
    - It is a shame I have to create a new Surface every time cause it is very slow.
    - Do you think GDI would run faster?

    #### START CODE LISTING ####

    Surface surface;
    IntPtr unmanagedSurface;
    IVMRMixerBitmap9 mixerBitmap;

    public void setBitmap(Bitmap bmp)
    {
    surface = new Surface(device, bmp, Pool.SystemMemory);
    unmanagedSurface = surface.GetObjectByValue(DxMagicNumber);

    VMR9AlphaBitmap alphaBmp = new VMR9AlphaBitmap();
    alphaBmp.dwFlags = VMR9AlphaBitmapFlags.EntireDDS;
    alphaBmp.pDDS = unmanagedSurface;
    alphaBmp.rDest = GetDestRectangle();
    alphaBmp.fAlpha = 1.0f;

    int hr = 0;
    hr = mixerBitmap.SetAlphaBitmap(ref alphaBmp);
    DsError.ThrowExceptionForHR(hr);
    }

    #### END CODE LISTING ####
    Monday, January 29, 2007 2:29 PM
  • Sorry, this isn't something I've really worked with.

    You might be better off posting this in the DirectShowNet forum (http://sourceforge.net/forum/forum.php?forum_id=460697).  Or searching the messages there, as I believe there has been some discussion on this sample in the past.

    ---

    Co-Author DirectShowNet

    Monday, January 29, 2007 7:50 PM
  • BramGo,

    We are currently working on a generalized solution for this task. Can you send me a private email at <okunev (at) medialooks.com> - maybe we can help.

    Saturday, February 03, 2007 8:56 AM
  • I am also working on the same type of thing in C#. I'm attempting to get the DirectDrawSurface7 of an existing video application. I'm especially interested in the solution which produced the flickering. Most importantly, I'm having problems retrieving the surface. Currently I'm attempting to do so using GetEnumSurfaces, but the object return always contains zero surfaces.

    This is the code that I'm currently trying:

    //BEGIN CODE SAMPLE

    DDSURFACEDESC2 surfaceDesc = new DDSURFACEDESC2();

    surfaceDesc.ddsCaps.lCaps = CONST_DDSURFACECAPSFLAGS.DDSCAPS_PRIMARYSURFACE | CONST_DDSURFACECAPSFLAGS.DDSCAPS_COMPLEX | CONST_DDSURFACECAPSFLAGS.DDSCAPS_VIDEOMEMORY | CONST_DDSURFACECAPSFLAGS.DDSCAPS_SYSTEMMEMORY | CONST_DDSURFACECAPSFLAGS.DDSCAPS_OVERLAY | CONST_DDSURFACECAPSFLAGS.DDSCAPS_LIVEVIDEO | CONST_DDSURFACECAPSFLAGS.DDSCAPS_OPTIMIZED;

    DirectDrawEnumSurfaces surfacesEnum = m_DirectDraw.GetSurfacesEnum(CONST_DDENUMSURFACESFLAGS.DDENUMSURFACES_ALL | CONST_DDENUMSURFACESFLAGS.DDENUMSURFACES_DOESEXIST, ref surfaceDesc);

    //END CODE SAMPLE

    I'm wondering if I need to set something else in the DDSURFACEDESC2 structure?

    Thanks for your help

    Tuesday, March 06, 2007 11:54 PM
  • This is how i do it, you dont recreate the Surface each time you lock it and recreate the bitmap.  Works great for me. 

    this is C#:

    [CODE]

    try

    {

    GraphicsStream stream = surface.LockRectangle(LockFlags.Discard);

    try

    {

    int stride = alphaBitmap.Width * 4;

    Bitmap bmp = new Bitmap(alphaBitmap.Width, alphaBitmap.Height, stride, alphaBitmap.PixelFormat, stream.InternalData);

    using (Graphics gr = Graphics.FromImage(bmp))

    {

    int alpha50 = (int)(255 * 0.50f); /* 50% opacity */

    int alpha100 = 255;

    Brush blue50 = new SolidBrush(Color.FromArgb(alpha50, Color.Blue));

    Brush blue100 = new SolidBrush(Color.FromArgb(alpha100, Color.Blue));

    Font font = new Font("Tahoma", 24);

    Brush text100 = new SolidBrush(Color.FromArgb(255, Color.White));

    gr.SmoothingMode = SmoothingMode.AntiAlias;

    gr.TextRenderingHint = TextRenderingHint.AntiAlias;

    gr.Clear(Color.Transparent);

    if (colorChange)

    {

    gr.FillRectangle(blue50, 0, 0, 1024, 122);

    gr.DrawString("Set Traverse X", font, text100, 5, 5);

    gr.DrawString("Next", font, text100, 5, 70);

    gr.DrawString("0.123", font, text100, 900, 5);

    }

    else

    {

    gr.FillRectangle(blue100, 0, 0, 1024, 122);

    gr.DrawString("Gear Count", font, text100, 5, 5);

    gr.DrawString("Next", font, text100, 5, 70);

    gr.DrawString("40", font, text100, 900, 5);

    }

    font.Dispose();

    text100.Dispose();

    blue50.Dispose();

    blue100.Dispose();

    gr.Dispose();

    }

    }

    catch (Exception exc)

    {

    Console.WriteLine(exc);

    }

    finally

    {

    surface.UnlockRectangle();

    }

    SetMixerSettings();

    }

    catch (Exception ex)

    {

    Console.WriteLine(ex);

    }

    [CODE]

    Wednesday, March 07, 2007 8:32 PM
  • Oh forgot to add SetMixerSettings is called to update the VMR9, so its aware of the new bitmap. its just like the BitmapMixer example in Directshownet
    Wednesday, March 07, 2007 8:34 PM
  • I know this is years old, but tchiex's answer was extremely helpful to me.  It worked.
    Monday, September 19, 2011 9:22 PM