tags:

views:

938

answers:

5

Hi,

I'm converting working Borland C++ Builder code to C# - interesting, but not always easy...

    void listCodecs(int Width, int Height) 
    {

        int iSelected = 0;

        ICINFO ci;
        BITMAPINFOHEADER bih;
        AnsiString asDesc;

        bih.biSize          = sizeof(BITMAPINFOHEADER);
        bih.biWidth         = Width;
        bih.biHeight        = Height;
        bih.biPlanes        = 1;
        bih.biBitCount      = 24;
        bih.biCompression   = BI_RGB;
        bih.biSizeImage     = 0;
        bih.biXPelsPerMeter = 1024;
        bih.biYPelsPerMeter = 1024;
        bih.biClrUsed       = 0;
        bih.biClrImportant  = 0;

        for (int c = 0, i = 0; ICInfo(ICTYPE_VIDEO, i, &ci); i++) 
        {

            // Query the compressor for information.
            HIC hic = ICOpen(ci.fccType, ci.fccHandler, ICMODE_QUERY);

            if (hic) 
            {
                if (ICERR_OK == ICCompressQuery( hic, &bih, NULL)) 
                {

                    ICGetInfo( hic, &ci, sizeof(ICINFO));
                    asDesc = ci.szDescription;

                    // ComboBoxCODEC->Items->Add(as);

                }
            c++;            
            ICClose(hic);

            }
        }
    }

I tried to convert to this slightly simplified code:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public class ICINFO
{
    public int dwSize;
    public int fccType;
    public int fccHandler;
    public int dwFlags;
    public int dwVersion;
    public int dwVersionICM;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
    public string szName;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
    public string szDescription;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
    public string szDriver;
}

public class FOURCC
{
    public static readonly int DIVX = FOURCC.mmioFOURCC('d', 'i', 'v', 'x');
    public static readonly int MP42 = FOURCC.mmioFOURCC('M', 'P', '4', '2');
    public static readonly int streamtypeVIDEO = mmioFOURCC('v', 'i', 'd', 's');
    public static readonly int streamtypeAUDIO = mmioFOURCC('a', 'u', 'd', 's');
    public static readonly int streamtypeMIDI = mmioFOURCC('m', 'i', 'd', 's');
    public static readonly int streamtypeTEXT = mmioFOURCC('t', 'x', 't', 's');
    public static readonly int ICTYPE_VIDEO = mmioFOURCC('v', 'i', 'd', 'c');
    public static readonly int ICTYPE_AUDIO = mmioFOURCC('a', 'u', 'd', 'c');
    public static readonly int ICM_FRAMERATE = mmioFOURCC('F', 'r', 'm', 'R');
    public static readonly int ICM_KEYFRAMERATE = mmioFOURCC('K', 'e', 'y', 'R');
    public static Int32 mmioFOURCC(char ch0, char ch1, char ch2, char ch3)
    {
        return ((Int32)(byte)(ch0) | ((byte)(ch1) << 8) |
            ((byte)(ch2) << 16) | ((byte)(ch3) << 24));
    }
}

    int ChangeCODEC() 
    {
        int cntCodec = 0;
        ICINFO ci = new ICINFO();
        for (int i = 0; ICBase.ICInfo(FOURCC.ICTYPE_VIDEO, i, ci); i++) 
        {
            cntCodec++;
        }
        return cntCodec;
    }

My problem is that ICInfo doesn't return any sane values in ci - but something is working because the loop runs 13 times, which is my number of installed codecs.

Any help is appreaciated - thanks, Niels

+1  A: 

The line:

ICBase.ICGetInfo(hic, ci, 0);

should be

ICBase.ICGetInfo(hic, ci, Marshal.SizeOf(ci));

Also, since hic is a handle, you should declare it everywhere as IntPtr instead of int.

logicnp
A: 

Sorry for the confusion. I have reformulated my question slightly - below is the non-working troublemaker code. I was hoping to create a list of vido codec information, but the list has the expected number of items, but the item data is not as I was expecting.

This is the code from a one-button C# 2008 test application.

Thanks a lot for looking into this!

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace vfwApp
{
    public partial class Form1 : Form
{

    public Form1()
    {
        InitializeComponent();
    }


    private void button1_Click(object sender, EventArgs e)
    {
        VideoCodecs myVideoCodecs = new VideoCodecs();
        List<VideoCodecs.ExtractedVideoCodecInformation> levci = myVideoCodecs.showThem();
    }
}

public class VideoCodecs
{
    public static unsafe class ICBase
    {
        [DllImport("MSVFW32.dll", CharSet = CharSet.Ansi)] 
        public static extern bool ICInfo(
            int fccType,
            int fccHandler,
            ICINFO lpicinfo
            );

        [DllImport("MSVFW32.dll"), PreserveSig]
        public static extern int ICOpen(int fccType, int fccHandler, ICMODE wMode);

        [DllImport("MSVFW32.dll")]
        public static extern int ICClose(int hic);

        [DllImport("MSVFW32.dll", CharSet = CharSet.Ansi)]
        public static extern int ICGetInfo(
            int hic,
            ICINFO lpicinfo,
            int cb
            );

    }

    public class FOURCC
    {

        public static readonly int ICTYPE_VIDEO = mmioFOURCC('v', 'i', 'd', 'c');
        public static readonly int ICTYPE_AUDIO = mmioFOURCC('a', 'u', 'd', 'c');

        public static Int32 mmioFOURCC(char ch0, char ch1, char ch2, char ch3)
        {
            return ((Int32)(byte)(ch0) | ((byte)(ch1) << 8) | ((byte)(ch2) << 16) | ((byte)(ch3) << 24));
        }
    }

    public enum ICMODE
    {
        ICMODE_COMPRESS = 1,
        ICMODE_DECOMPRESS = 2,
        ICMODE_FASTDECOMPRESS = 3,
        ICMODE_QUERY = 4,
        ICMODE_FASTCOMPRESS = 5,
        ICMODE_DRAW = 8
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public class ICINFO
    {
        public int dwSize;
        public int fccType;
        public int fccHandler;
        public int dwFlags;
        public int dwVersion;
        public int dwVersionICM;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
        public string szName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        public string szDescription;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        public string szDriver;
    }

    public struct ExtractedVideoCodecInformation {
        public int fccType;
        public int fccHandler;
        public int dwVersion;
        public string name;
        public string description;
        public string driver;
    }

    public List<ExtractedVideoCodecInformation> showThem() 
    {
        int cntCodec = 0;
        ICINFO ci = new ICINFO();

        ExtractedVideoCodecInformation evci = new ExtractedVideoCodecInformation();
        List<ExtractedVideoCodecInformation> levci = new List<ExtractedVideoCodecInformation>();


        for (int i = 0; ICBase.ICInfo(FOURCC.ICTYPE_VIDEO, i, ci); i++) 
        {
            int hic = ICBase.ICOpen(ci.fccType, ci.fccHandler, ICMODE.ICMODE_QUERY);

            if (hic != 0)
            {
                ICBase.ICGetInfo(hic, ci, 0);

                // None of these fields are valid/sane now >>>
                evci.fccType = ci.fccType;
                evci.fccHandler = ci.fccHandler;
                evci.dwVersion = ci.dwVersion;
                evci.name = ci.szName;
                evci.description = ci.szDescription;
                evci.driver = ci.szDriver;

                levci.Add(evci);

                // <<< None of these fields are valid/sane now

                ICBase.ICClose(hic);
            }

            cntCodec++;
        }
        return levci;
    }


}

}

Niels
A: 

Thanks for the reply - I made the modifications (like in the below code), but unfortuneately it didn't solve the problem?

using System;
using System.Collections.Generic;   
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace vfwApp
{
public partial class Form1 : Form
{

    public Form1()
    {
        InitializeComponent();
    }


    private void button1_Click(object sender, EventArgs e)
    {
        VideoCodecs myVideoCodecs = new VideoCodecs();
        List<VideoCodecs.ExtractedVideoCodecInformation> levci = myVideoCodecs.showThem();
    }
}

public class VideoCodecs
{
    public static unsafe class ICBase
    {
        [DllImport("MSVFW32.dll", CharSet = CharSet.Ansi)] 
        public static extern bool ICInfo(
            int fccType,
            int fccHandler,
            ICINFO lpicinfo
            );

        [DllImport("MSVFW32.dll"), PreserveSig]
        public static extern IntPtr ICOpen(int fccType, int fccHandler, ICMODE wMode);

        [DllImport("MSVFW32.dll")]
        public static extern int ICClose(IntPtr hic);

        [DllImport("MSVFW32.dll", CharSet = CharSet.Ansi)]
        public static extern int ICGetInfo(
            IntPtr hic,
            ICINFO lpicinfo,
            int cb
            );

    }

    public class FOURCC
    {

        public static readonly int ICTYPE_VIDEO = mmioFOURCC('v', 'i', 'd', 'c');
        public static readonly int ICTYPE_AUDIO = mmioFOURCC('a', 'u', 'd', 'c');

        public static Int32 mmioFOURCC(char ch0, char ch1, char ch2, char ch3)
        {
            return ((Int32)(byte)(ch0) | ((byte)(ch1) << 8) | ((byte)(ch2) << 16) | ((byte)(ch3) << 24));
        }
    }

    public enum ICMODE
    {
        ICMODE_COMPRESS = 1,
        ICMODE_DECOMPRESS = 2,
        ICMODE_FASTDECOMPRESS = 3,
        ICMODE_QUERY = 4,
        ICMODE_FASTCOMPRESS = 5,
        ICMODE_DRAW = 8
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public class ICINFO
    {
        public int dwSize;
        public int fccType;
        public int fccHandler;
        public int dwFlags;
        public int dwVersion;
        public int dwVersionICM;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
        public string szName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        public string szDescription;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        public string szDriver;
    }

    public struct ExtractedVideoCodecInformation {
        public int fccType;
        public int fccHandler;
        public int dwVersion;
        public string name;
        public string description;
        public string driver;
    }

    public List<ExtractedVideoCodecInformation> showThem() 
    {
        int cntCodec = 0;
        ICINFO ci = new ICINFO();

        ExtractedVideoCodecInformation evci = new ExtractedVideoCodecInformation();
        List<ExtractedVideoCodecInformation> levci = new List<ExtractedVideoCodecInformation>();


        for (int i = 0; ICBase.ICInfo(FOURCC.ICTYPE_VIDEO, i, ci); i++) 
        {
            IntPtr hic = ICBase.ICOpen(ci.fccType, ci.fccHandler, ICMODE.ICMODE_QUERY);

            if (hic != IntPtr.Zero)
            {
                // ICBase.ICGetInfo(hic, ci, 0);  // Was before...
                ICBase.ICGetInfo(hic, ci, Marshal.SizeOf(ci));

                // None of these fields are valid/sane now >>>
                evci.fccType = ci.fccType;
                evci.fccHandler = ci.fccHandler;
                evci.dwVersion = ci.dwVersion;
                evci.name = ci.szName;
                evci.description = ci.szDescription;
                evci.driver = ci.szDriver;

                levci.Add(evci);

                // <<< None of these fields are valid/sane now

                ICBase.ICClose(hic);
            }

            cntCodec++;
        }
        return levci;
    }


}

}

Niels
A: 

Try to use this code

public static readonly int ICTYPE_VIDEO = mmioFOURCC('v', 'i', 'd', 'c');
public static readonly int DIVX = mmioFOURCC('d', 'i', 'v', 'x');

(int)ICOpen(ICTYPE_VIDEO, ci.fccHandler, ICMODE.ICMODE_QUERY);

for get video codecs or this

(int)ICOpen(ICTYPE_VIDEO, DIVX, ICMODE.ICMODE_QUERY);

for get specific(DIVX) codec

piranha
A: 

I finally got it to work (sort of) by making ICINFO a struct and passing it using the ref keyword like so:

public unsafe static extern bool ICInfo(
             uint fccType,
             uint fccHandler,
             ref ICINFO lpicinfo
             );

The string fields don't work yet though. I'll post if I figure that out.

Scott Reece