C# 编解码器问题

发布于 2024-08-07 15:40:31 字数 7672 浏览 2 评论 0原文

我正在将工作 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 次,这是我安装的编解码器的数量。

更新:

抱歉造成混乱。 我稍微重新表述了我的问题 - 下面是不起作用的麻烦制造者代码。 我希望创建一个视频编解码器信息列表,但该列表具有预期的项目数量,但项目数据并不符合我的预期。

这是来自一键式 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;
        }


    }
}

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.

Update:

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


    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

完美的未来在梦里 2024-08-14 15:40:31

该行:

ICBase.ICGetInfo(hic, ci, 0);

应该是

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

另外,由于 hic 是一个句柄,因此您应该在任何地方将其声明为 IntPtr 而不是 int。

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.

流心雨 2024-08-14 15:40:31

尝试使用此代码

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)编解码器

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

轻许诺言 2024-08-14 15:40:31

我终于通过将 ICINFO 设为一个结构并使用 ref 关键字传递它来使其工作(某种程度上),如下所示:

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

不过字符串字段还不能工作。如果我弄清楚了,我会发帖。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文