Menu

Desperate to Overlay Moving Text over Video

guivetemp
2006-01-18
2012-10-29
  • guivetemp

    guivetemp - 2006-01-18

    I have spent MONTHS working on this problem.
    I am trying to create a program that will overlay a static text/image AND a moving text (like a ticker) on top of an existing video

    I am using DirectshowNet with VMR-9

    The issue is that the bitmap mixer of VMR9 requires a pointer to

    alphaBitmap = New Bitmap(720, 256)
    g= Graphics.FromImage(alphaBitmap)

    Then I have a timer that executes several time per second and which scrolls the text as:

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
    Static Dim hr As Integer = 0
    Static Dim vez = 0

        Static Dim pos As Double
    
    
    
        Dim b As Brush
        b = New SolidBrush(Color.FromArgb(255, 100, 100, 240))
    
    
        Dim f As New Font("Arial", 24, FontStyle.Bold, GraphicsUnit.Pixel)
    
    
        Dim NativeMethodes As bmpMixerVB.DirectShowLib.Sample.NativeMethodes
        Dim r As New Rectangle(0, 0, 720, 576)
       g.Clear(Color.FromArgb(50, 255, 100, 100))
        g.DrawString("HELLO BABES", f, Brushes.Tomato, 0, 0)
    
    
        surface = New Surface(device, alphaBitmap, Pool.SystemMemory)
    
        unmanagedSurface = surface.GetObjectByValue(DxMagicNumber)
    
    
        pos = pos + 0.02
        Dim alphaBmp As VMR9AlphaBitmap
        alphaBmp = New VMR9AlphaBitmap
        alphaBmp.dwFilterMode = VMRMixerPrefs.PointFiltering
        alphaBmp.dwFlags = VMR9AlphaBitmapFlags.EntireDDS
        alphaBmp.pDDS = unmanagedSurface
        alphaBmp.rDest = GetDestRectangle()
        alphaBmp.rDest.top = 0
        alphaBmp.rDest.bottom = 1
        alphaBmp.rDest.right = pos + 3
        alphaBmp.rDest.left = pos
          alphaBmp.fAlpha = 1.0F
    
        hr = mixerBitmap.SetAlphaBitmap(alphaBmp)
    
        surface.Dispose()
    
    
        If pos > 1 Then pos = 0
    
    
    
    End Sub
    

    The big issue is that each time the timer is called I am doing

    surface = New Surface(device, alphaBitmap, Pool.SystemMemory)

    and this is a huge overkill. If I leave the surface as global variable and do not make the above call , even if I update unmanagedSurface = surface.GetObjectByValue(DxMagicNumber) , Then there is no update of the image.

    My question: is there a way to push by updated bitmap to the VMR9 mixer without requiring to create a new Direct3D everytime.

    Note that only a small portion of the surface is modified everytime so I could replace only part of the surface…

    So many thanks for anybody who could help

    Guive
    guivetemp@yahoo.com

     
    • guivetemp

      guivetemp - 2006-01-20

      Zoltan,

      I could make good progress. But now I am facing the following issue:
      When I try to overlay the text WITH LARGE FONTS ( I am writing a TV Application) on top of the window, the text quality is poor. I tried to play with texthintering and graph smooting parameter. but nothing makes. The perimeter of the text is always kind "dirty": sometimes even there is a connection between two adjacent letters.

      any idea what could be going wrong?

       
      • Zoltan Lorincz

        Zoltan Lorincz - 2006-01-23

        Hello Guive,

        unfortunatly i don't know what may be the problem.

        Best regards,
        Zoltan.

         
      • Eric

        Eric - 2006-01-21

        Which technology do you use to write your text (GDI or Direct3D) ?

        GDI bitmaps don't support alpha values so colorkey is the only solution to do tansparency and this generaly produce very dirty things (especially with texts). Direct3D surfaces with alpha values & anti-aliased test generally produce better results.

         
    • Zoltan Lorincz

      Zoltan Lorincz - 2006-01-19

      Hello Guivetemp,

      i am a DirectShow newbie, so maybe my advice won't help. However i consider that you shouldn't create a new bitmap at each time the timer is called, only to change the destination rectangle of the VMR9AlphaBitmap. New bitmap should be created every time when the text is changing.

      Hope it helps.

      Regards,
      Zollor.

       
    • Zoltan Lorincz

      Zoltan Lorincz - 2006-01-19

      Hello Guive,

      i found a method to modify the bitmap without recreating the device. Please note that my example is in C#, but you can easily convert to VB.


      private void _Timer_Tick(object sender, EventArgs e)
      {
      long startTicks = DateTime.Now.Ticks;
      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))
                      {
                          gr.Clear(Color.Transparent);
                          //gr.DrawString("Test", new Font("Arial", 12), Brushes.Black,  );
                          gr.FillEllipse(Brushes.Blue, this.xCoord, 0, 100, 100);
                          xCoord +=1;
                          if(xCoord > 400) xCoord = 0;
                      }
                  }
                  finally
                  {
                      surface.UnlockRectangle();
      
                  }
      
                  // Set Alpha Bitmap Parameters for using a Direct3D surface
                  VMR9AlphaBitmap alphaBmp = new VMR9AlphaBitmap();
                  alphaBmp.dwFlags = VMR9AlphaBitmapFlags.EntireDDS;
                  alphaBmp.pDDS = unmanagedSurface;
                  alphaBmp.rDest = new NormalizedRect(0,0.8f, 1.0f, 1.0f);//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
                  int hr = mixerBitmap.SetAlphaBitmap(ref alphaBmp);
                  DsError.ThrowExceptionForHR(hr);
              }
              catch(Exception exc)
              {
                  Console.WriteLine(exc);
              }
              Console.WriteLine("Ellapsed ticks: " + (long)(DateTime.Now.Ticks - startTicks));
          }
      

      The performance looks good.

      Let me know if this helped...

       
    • guivetemp

      guivetemp - 2006-01-19

      Hi Zollor,

      So many thanks ! I translated the code in VB and managed to get it to work. I had to add however in the code

      Static surface = New Surface(device, alphaBitmap, Pool.SystemMemory)
      unmanagedSurface = surface.GetObjectByValue(DxMagicNumber)

      You help was really really great. Without it, I would still be stuck !

      Private Sub Timer4_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer4.Tick
      Dim startTicks As Long = DateTime.Now.Ticks
      Static Dim xcoord As Integer

          Static surface = New Surface(device, alphaBitmap, Pool.SystemMemory)
      
      
          Try
              Dim stream As GraphicsStream = surface.LockRectangle(LockFlags.Discard)
              Try
                  Dim stride As Integer = alphaBitmap.Width * 4
                  Dim bmp As Bitmap = New Bitmap(alphaBitmap.Width, alphaBitmap.Height, stride, alphaBitmap.PixelFormat, stream.InternalData)
                  ' Using 
                  Dim gr As Graphics = Graphics.FromImage(bmp)
                  Dim sb As SolidBrush
                  sb = New SolidBrush(Color.FromArgb(50, 200, 200, 40))
      
                  Try
                      gr.Clear(Color.Transparent)
                      gr.FillEllipse(sb, xcoord, 0, 400, 400)
                      xcoord += 3
                      If xcoord > 400 Then
                          xcoord = 0
                      End If
                  Finally
                      CType(gr, IDisposable).Dispose()
                  End Try
              Finally
                  surface.UnlockRectangle()
              End Try
      
      
              unmanagedSurface = surface.GetObjectByValue(DxMagicNumber)
      
              Dim alphaBmp As VMR9AlphaBitmap = New VMR9AlphaBitmap
               alphaBmp.rDest = New NormalizedRect(0, 0.8F, 1.0F, 1.0F)
              alphaBmp.dwFilterMode = VMRMixerPrefs.PointFiltering
              alphaBmp.dwFlags = VMR9AlphaBitmapFlags.EntireDDS
              alphaBmp.pDDS = unmanagedSurface
              alphaBmp.rDest.top = 0
              alphaBmp.rDest.bottom = 1
              alphaBmp.rDest.right = 3
              alphaBmp.rDest.left = 0
              alphaBmp.fAlpha = 1.0F
      
              Dim hr As Integer = mixerBitmap.SetAlphaBitmap(alphaBmp)
      
      
      
              DsError.ThrowExceptionForHR(hr)
          Catch exc As Exception
              Console.WriteLine(exc)
          End Try
          Console.WriteLine("Ellapsed ticks: ", CType((DateTime.Now.Ticks - startTicks), Long))
      
      End Sub
      
       
      • Zoltan Lorincz

        Zoltan Lorincz - 2006-01-19

        Hello Guive,

        i am happy that i could help ;).

        However, don't forget that if you will resize the player window, you will have to reset the device and recreate the surface, at least this is how i could solve the device lost issue.

        Regards,
        Zollor.

         
    • guivetemp

      guivetemp - 2006-01-19

      Aha !

      This may explain why I get sometimes nullexceptions...

       

Log in to post a comment.

MongoDB Logo MongoDB