Кодек 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 раз, что является моим количеством установленных кодеков.
Обновить:
Извините за путаницу. Я немного переформулировал свой вопрос - ниже приведен нерабочий кодекс нарушителя спокойствия. Я надеялся создать список информации о кодеках 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 ответа
Линия:
ICBase.ICGetInfo(hic, ci, 0);
должно быть
ICBase.ICGetInfo(hic, ci, Marshal.SizeOf(ci));
Кроме того, поскольку hic является дескриптором, вы должны объявлять его везде как IntPtr вместо int.
Попробуйте использовать этот код
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) кодека
Я наконец заставил его работать (вроде), сделав ICINFO структурой и передав ее с помощью ключевого слова ref, например:
public unsafe static extern bool ICInfo(
uint fccType,
uint fccHandler,
ref ICINFO lpicinfo
);
Строковые поля пока не работают. Я отправлю, если я пойму это.