Accessing .AVI As Embedded Resource

I've got a project in VS2003 where I've added a number of images and a video clip as an embedded resource on 'Build Action'. I can access the images easy enough by using the following code:

System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(GetType(), "sampleImage.jpg"); this.pictureBox1.Image = bitmap;

The problem is accessing the embedded .AVI; both the ActiveX Windows Media Player and the DirectX AudioVideoPlayback require a string pointing to a file

Accessing Video File Thru ActiveX Windows Media Player Control:

private AxWMPLib.AxWindowsMediaPlayer axWindowsMediaPlayer1;

this.axWindowsMediaPlayer1.URL = "sampleVideo.avi";

Accessing Video File Thru DirectX 9:

using Microsoft.DirectX.AudioVideoPlayback;

Video vid = new Video("sampleVideo.avi", false);

Any help would be greatly appreciated.



Answer this question

Accessing .AVI As Embedded Resource

  • Arvind Agarwal - Skelta

    The best workaround that I can think of is to simply deserialize the video into a separate avi file that you then pass to WMP. Or if that is not acceptable, you could create a custom ActiveX control using DirectShow that could accept input directly from the resource, deserialize it if necessary, and then play it.

    Michael Blome Visual C# Documentation Team


  • Mr Pro Tools

    How about this...

    DirectShow and Windows Media Player allow a URL instead of a filename to play a video. You could create a thread in your app that listens on a dynamic socket for HTTP requests on the loopback adapter (127.0.0.1) and only takes requests from your app (look in the header or put something in the url that identifies the request). Then you could read the resource into memory and feed it back through the web request.

    Bill



  • Bo Persson

    namespace Tools
    {
    /// <summary>
    /// how to grab resources, look them up and use them to pull out embedded icons or.......
    /// </summary>
    public class Resource_Graber
    {
    static System.Collections.ArrayList theResources;

    /// <summary>
    /// this gets a list of resources, this will make it ez to know what to pass grabStram
    /// </summary>
    /// <returns>the strings of resources</returns>
    public static string [] getResourceList()
    {
    if(theResources == null)
    theResources = new System.Collections.ArrayList();
    string[] names = System.Reflection.Assembly.GetAssembly((new Resource_Graber()).GetType()).GetManifestResourceNames();
    foreach (string s in names)
    {
    theResources.Add(s);
    }
    // ok y (new Resource_Graber()).GetType()
    // well it can be all most anything!!! from your namespace

    return names;
    }

    /// <summary>
    /// this will return a stream, send it into a new System.Drawing.Icon(X) or something
    /// this can even just be a unique part of the string like myIcon.ico
    /// </summary>
    /// <param name="nameToGrab">string of stream to grab</param>
    /// <returns>the stream</returns>
    public static System.IO.Stream grabStream(string nameToGrab)
    {
    if(theResources == null)
    getResourceList();
    System.Reflection.Assembly A = System.Reflection.Assembly.GetExecutingAssembly();
    foreach (string aResource in theResources)
    {
    if(aResource.IndexOf(nameToGrab) != -1)
    {
    return A.GetManifestResourceStream(aResource);
    }
    }
    return null;
    }
    #region example
    /// <summary>
    /// an example of using the embedded icon
    /// </summary>
    /// <returns>a icon</returns>
    public static System.Drawing.Icon icon()
    {
    System.Drawing.Icon ico = new System.Drawing.Icon( Noj.Tools.Resource_Graber.grabStream(
    // change this
    "ColorOverlay.Noj.Tools.Reminder.Reminder.ico"
    // <-

    ));
    return ico;
    }

    /// <summary>
    /// make dynamic icon from text
    /// </summary>
    /// <returns>a icon</returns>
    // for use below
    [System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint="DestroyIcon")]
    static extern bool DestroyIcon(System.IntPtr hIcon);

    public static System.Drawing.Icon makeIcon()
    {
    // Create a graphics instance that draws to a bitmap
    System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(16, 16);
    System.Drawing.SolidBrush brush = new System.Drawing.SolidBrush(System.Drawing.Color.DarkRed);
    System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(bitmap);

    // Draw the temperature and the degrees symbol to the bitmap using the user selected font
    string temperatureOnlyStr = "Sex";
    System.Drawing.Font f = new System.Drawing.Font("Lucida Sans Typewriter", 5F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
    graphics.DrawString(temperatureOnlyStr, f, brush, 0, 0);

    // Convert the bitmap into an icon and use it for the system tray icon
    System.IntPtr hIcon = bitmap.GetHicon();
    System.Drawing.Icon icon = System.Drawing.Icon.FromHandle(hIcon);

    // unfortunately, GetHicon creates an unmanaged handle which must be manually destroyed
    DestroyIcon(hIcon);

    return icon;
    }
    #endregion ---example---
    }
    }


    my email: jon.use@charter.net
    let me know if it helped

  • daxwhit

    This is an interesting problem, which is not always the kind of problem one would prefer to have. ;-) However I think it is solvable without too much headache.

    If the video will always be in AVI format and always small enough to fit on the clipboard all at once, then I would first investigate the possibility of using Video For Windows instead of DirecdtShow. VfW has the GetAVIFromClipboard http://msdn.microsoft.com/library/default.asp url=/library/en-us/multimed/htm/_win32_avigetfromclipboard.asp function and you could just make VfW calls using P/Invoke. But VfW is very old technology and one potential issue is whether it be supported on Vista. It's also much less efficient than DShow in terms of memory usage and performance.

    If VfW doesn't appeal to you, then you will need to create a custom DirectShow "source filter". This is fairly straightforward and there are some good samples out there--in fact there is probably a sample in the SDK for an "in-memory source filter" which you might be able to use out of the box without any need for modification. A source filter is a COM object that will accept blocks of data in real time as you marshall them across from your C# app and then passes them, using a well-defined protocol, to the DShow AVI parsers, which pass the data to the decoders, renderers etc. See the DirectShow docs on MSDN for more info. I know that many people have used DShow from C# successfully so it can be done. You can ask questions on the DirectShow discussion forum at: http://DISCUSS.MICROSOFT.COM/archives/DIRECTXAV.html or the foum at http://forums.microsoft.com/msdn/showforum.aspx forumid=129&siteid=1 .

    Good luck!


  • Roger Rombooth

    Hi, I've been doing a little research and I came across an article in another forum that demonstrated viewing a file using DirectShow and the Interop.QuartzTypeLib which I've added as a reference to the project. I am able to play the file but I don't know if I'm going in the right direction to access this same media as an embedded resource Any help would be greatly appreciated.

    Code Snippet ==============================================

    using System;

    using System.Drawing;

    using System.Collections;

    using System.ComponentModel;

    using System.Windows.Forms;

    using System.Data;

    using QuartzTypeLib;

    namespace VideoDirectShow

    {

    /// <summary>

    /// Summary description for Form1.

    /// </summary>

    public class Form1 : System.Windows.Forms.Form

    {

    private System.Windows.Forms.Panel panel1;

    /// <summary>

    /// Required designer variable.

    /// </summary>

    private System.ComponentModel.Container components = null;

    private const int WM_APP = 0x8000;

    private const int WM_GRAPHNOTIFY = WM_APP + 1;

    private const int EC_COMPLETE = 0x01;

    private const int WS_CHILD = 0x40000000;

    private const int WS_CLIPCHILDREN = 0x2000000;

    private FilgraphManager m_objFilterGraph = null;

    private IBasicAudio m_objBasicAudio = null;

    private IVideoWindow m_objVideoWindow = null;

    private IMediaEvent m_objMediaEvent = null;

    private IMediaEventEx m_objMediaEventEx = null;

    private IMediaPosition m_objMediaPosition = null;

    private IMediaControl m_objMediaControl = null;

    public Form1()

    {

    //

    // Required for Windows Form Designer support

    //

    InitializeComponent();

    //

    // TODO: Add any constructor code after InitializeComponent call

    //

    m_objFilterGraph = new FilgraphManager();

    m_objFilterGraph.RenderFile("Sample.avi");

    m_objBasicAudio = m_objFilterGraph as IBasicAudio;

    try

    {

    m_objVideoWindow = m_objFilterGraph as IVideoWindow;

    m_objVideoWindow.Owner = (int) panel1.Handle;

    m_objVideoWindow.WindowStyle = WS_CHILD | WS_CLIPCHILDREN;

    m_objVideoWindow.SetWindowPosition(panel1.ClientRectangle.Left,

    panel1.ClientRectangle.Top,

    panel1.ClientRectangle.Width,

    panel1.ClientRectangle.Height);

    }

    catch (Exception)

    {

    m_objVideoWindow = null;

    }

    m_objMediaEvent = m_objFilterGraph as IMediaEvent;

    m_objMediaEventEx = m_objFilterGraph as IMediaEventEx;

    m_objMediaEventEx.SetNotifyWindow((int) this.Handle,WM_GRAPHNOTIFY, 0);

    m_objMediaPosition = m_objFilterGraph as IMediaPosition;

    m_objMediaControl = m_objFilterGraph as IMediaControl;

    m_objMediaControl.Run();

    }


  • vbrada

    The DirectShow "source filter" sounds like the right approach. I have no experience in using DirectShow and looking over the link you sent me. I've installed DirectX SDK (December 2005), and am trying to gleen MSDN to school up.
  • me_someone

    Hi, and thanks for your interest. I would rather not deserialize the video if possible. Do you know of any online resources that might point me in the right direction toward the ActiveX control
  • Alan Brewer

    Rich:

    You might be able to use this code later, but what you have created is basically a Media Player with the same problem--e.g. it only knows how to read certain kinds of files from disk. Once you have created your custom source filter, you might be able to use the code above to specify an .resx file and then auto-magically choose your filter to read the bytes. It's all in the DShow docs, also Pesce's book on DirectShow is good for what you are trying to do.


  • Accessing .AVI As Embedded Resource