AVI video from WPF using AviFile

Sometimes, things are so easy in WPF, you don't even remember the struggle that went on before in the old days of .Net2.0. Then, on the other hand, you hope for a little backward compatibility, and hope disappears faster than a chocolate bar from a cupboard.

The case in point is video. It's so easy to control a video. Stick in a Media Element, and point it at a file, and you're off. This piece is about creating the video in the first place, and uses Corrina John's AviFile, as posted on CodeProject many moons ago. http://www.codeproject.com/KB/audio-video/avifilewrapper.aspx

The old way

This is how it was done in .Net 2.0, although this is written for wpf and uses a MediaElement named "player"

   // set up the avimanager
    AviManager aviManager = null;
    VideoStream aviStream = null;
    aviManager = new AviManager("c:\\temp\\test.avi", false);

    // create a bitmap
    System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(320, 200);
    DrawBitmap(ref bitmap, 0);
    aviStream = aviManager.AddVideoStream(true, 15, bitmap);
    bitmap.Dispose();

    for (int i = 0; i < 30; i++)
    {
        bitmap = new System.Drawing.Bitmap(320, 200);
        DrawBitmap(ref bitmap, i);
        aviStream.AddFrame(bitmap);
    }

    // close aviManager
    aviManager.Close();

    // play
    player.Source = new Uri("c://temp//test.avi");
    player.Play();

    ...

    private void DrawBitmap(ref System.Drawing.Bitmap bitmap, int offset)
    {
        Graphics g = Graphics.FromImage(bitmap);
        SolidBrush brush = new SolidBrush(System.Drawing.Color.Yellow);
        RectangleF rect = new RectangleF(20+offset,20+offset,100,100);
        g.FillRectangle(brush, rect);
    }

Point of note:

The new way

In WPF, System.Drawing.Bitmap is the old GDI+ way. We want the new way (I think), so

    // setup avimanager
    AviManager aviManager = null;
    VideoStream aviStream = null;
    aviManager = new AviManager("c:\\temp\\test.avi", false);

    // create a bitmap

    System.Drawing.Bitmap bitmap= GetBitmap(0);
    aviStream = aviManager.AddVideoStream(true, 15, bitmap);
    bitmap.Dispose();

    for (int i = 0; i < 30; i++)
    {
        bitmap = GetBitmap(i);
        aviStream.AddFrame(bitmap);
    }
    // close aviManager
    aviManager.Close();

    // play
    player.Source = new Uri("c://temp//test.avi");
    player.Play();

    ...

    private System.Drawing.Bitmap GetBitmap(int offset)
    {
        DrawingVisual drawingVisual = new DrawingVisual();
        DrawingContext drawingContext = drawingVisual.RenderOpen();
        drawingContext.DrawRectangle(System.Windows.Media.Brushes.Orange, null, new Rect(50+offset, 50+offset, 100, 80));
        drawingContext.Close();

        RenderTargetBitmap bmp = new RenderTargetBitmap(320, 200, 96, 96, PixelFormats.Pbgra32);
        bmp.Render(drawingVisual);

        MemoryStream outStream = new MemoryStream();
        BitmapEncoder enc = new BmpBitmapEncoder();
        enc.Frames.Add(BitmapFrame.Create(bmp));
        enc.Save(outStream);
        System.Drawing.Bitmap sdbitmap = new System.Drawing.Bitmap(outStream);
        return sdbitmap;
    }

Points of note:

So is that it?

Of course not. The real task is to allow aviFile to create video frames directly from BitmapSource (or whichever derivation you choose). I doubt this is too onerous, but one step at a time is better than a leap too far.

Where's the code?

I am sorry to inform you that the reality of the media element is not that simple. Please read on before downloading and trying to get the code to run.

Click here for the project files