CODEC C#问题

时间:2009-10-15 09:33:19

标签: c# codec vfw

我正在将Borland C ++ Builder代码转换为C# - 有趣,但并不总是很容易......

    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);

            }
        }
    }

我尝试转换为这个略微简化的代码:

[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;
    }

我的问题是ICInfo没有在ci中返回任何合理的值 - 但有些东西正在运行,因为循环运行了13次,这是我安装的编解码器的数量。

更新

很抱歉这个混乱。 我稍微重新提出了我的问题 - 下面是非工作的麻烦制造者代码。 我希望创建一个vido编解码器信息列表,但列表中有预期的项目数,但项目数据并不像我期望的那样。

这是一键式C#2008测试应用程序的代码。

非常感谢您对此进行调查!

    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;
        }


    }
}

3 个答案:

答案 0 :(得分:1)

该行:

ICBase.ICGetInfo(hic, ci, 0);

应该是

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

另外,由于hic是一个句柄,你应该把它声明为IntPtr而不是int。

答案 1 :(得分:1)

尝试使用此代码

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);

获取视频编解码器或此

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

获取特定(DIVX)编解码器

答案 2 :(得分:0)

我终于通过使ICINFO成为一个结构并使用ref关键字传递它来实现(某种程度):

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

字符串字段不起作用。如果我弄明白的话,我会发帖。