Niels
Niels

Reputation: 11

CODEC C# question

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


    }
}

Upvotes: 1

Views: 6307

Answers (3)

Scott Reece
Scott Reece

Reputation: 1

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.

Upvotes: 0

piranha
piranha

Reputation: 11

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

Upvotes: 1

logicnp
logicnp

Reputation: 5836

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.

Upvotes: 1

Related Questions