C# 编解码器问题
我正在将工作 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
该行:
应该是
另外,由于 hic 是一个句柄,因此您应该在任何地方将其声明为 IntPtr 而不是 int。
The line:
should be
Also, since hic is a handle, you should declare it everywhere as IntPtr instead of int.
尝试使用此代码
获取视频编解码器或使用此代码
获取特定(DIVX)编解码器
Try to use this code
for get video codecs or this
for get specific(DIVX) codec
我终于通过将 ICINFO 设为一个结构并使用 ref 关键字传递它来使其工作(某种程度上),如下所示:
不过字符串字段还不能工作。如果我弄清楚了,我会发帖。
I finally got it to work (sort of) by making ICINFO a struct and passing it using the ref keyword like so:
The string fields don't work yet though. I'll post if I figure that out.