我正在将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;
}
}
}
答案 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
);
字符串字段不起作用。如果我弄明白的话,我会发帖。