最近做的一个课程设计,需要拆分视频。
从网上下载了一个程序,但是调试之后,发现出现“未将对象的引用设置到对象的实例”的错误。跟踪了一下,发现是getFrameObject = AVIStreamGetFrameOpen(aviStream, ref bih);这一句有问题,getFrameObject的值始终为0,导致后面的 int pDib = AVIStreamGetFrame(getFrameObject, firstFrame + i);  pDib的值也为0,而aviStream与 bih都不为Null。执行到 bih = (BITMAPINFOHEADER)Marshal.PtrToStructure(new IntPtr(pDib), bih.GetType());
语句之后,便没有执行后面的处理得到BMP文件的代码,直接跳到了报错,未将对象的引用设置到对象的实例。又查阅了MSDN中对于AVIStreamGetFrameOpen function的解释,返回值的阐述如下:
Return value
Returns a GetFrame object that can be used with the AVIStreamGetFrame function. If the system cannot find a decompressor that can decompress the stream to the given format, or to any RGB format, the function returns NULL.
其中的If the system cannot find a decompressor(如果系统无法找到解压器),怎么理解啊,还望大神指点,十分感谢
附上代码using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Globalization;
using System.IO;
 
namespace GetAVIFrames
{
    public partial class Form1 : Form
    {
        public const int BMP_MAGIC_COOKIE = 19778;
        [DllImport("avifil32.dll")] public static extern void AVIFileInit();
        [DllImport("avifil32.dll")] public static extern int AVIFileOpen(ref int ppFile, String szFile, int Mode, int pclsidHandler);
        [DllImport("avifil32.dll")] public static extern int AVIFileGetStream(int pFile, out IntPtr ppAvi, int fccType, int lParam);
 
        [DllImport("avifil32.dll")] public static extern int AVIStreamStart(int pavi);
        [DllImport("avifil32.dll")] public static extern int AVIStreamLength(int pavi);
        [DllImport("avifil32.dll")] public static extern int AVIStreamInfo(int pAVIStream, ref AVI_STREAM_INFO pStrInfo, int Size);
 
        [DllImport("avifil32.dll")] static extern int AVIFileInfo(int pFile, ref AVI_FILE_INFO aviInfo, int Size);
        [DllImport("avifil32.dll")] static extern int AVIStreamGetFrameOpen(IntPtr pAvi, ref BITMAPINFOHEADER bih);
        [DllImport("avifil32.dll")] public static extern int AVIStreamGetFrame(int pGetFrame, int Pos);
        [DllImport("avifil32.dll")] public static extern int AVIStreamGetFrameClose(int pGetFrame);
 
        public struct AVI_RECT
        {
            public UInt32 left;
            public UInt32 top;
            public UInt32 right;
            public UInt32 bottom;
        };
 
        public struct AVI_STREAM_INFO
        {
            public UInt32 fccType;
            public UInt32 fccHandler;
            public UInt32 dwFlags;
            public UInt32 dwCaps;
            public UInt16 wPriority;
            public UInt16 wLanguage;
            public UInt32 dwScale;
            public UInt32 dwRate;
            public UInt32 dwStart;
            public UInt32 dwLength;
            public UInt32 dwInitialFrames;
            public UInt32 dwSuggestedBufferSize;
            public UInt32 dwQuality;
            public UInt32 dwSampleSize;
            public AVI_RECT rcFrame;
            public UInt32 dwEditCount;
            public UInt32 dwFormatChangeCount;
            public string szName;
        } ;
 
 
        public struct AVI_FILE_INFO
        {
            long dwMaxBytesPerSecond;
            long dwFlags;
            long dwCaps;
            long dwStreams;
            long dwSuggestedBufferSize;
            long dwWidth;
            long dwHeight;
            long dwScale;
            long dwRate;
            long dwLength;
            long dwEditCount;
            long szFileType;
        }
 
        [StructLayout(LayoutKind.Sequential, Pack=1)]
        public struct BITMAPINFOHEADER
        {
            public UInt32 biSize;
            public Int32 biWidth;
            public Int32 biHeight;
            public Int16 biPlanes;
            public Int16 biBitCount;
            public UInt32 biCompression;
            public UInt32 biSizeImage;
            public Int32 biXPelsPerMeter;
            public Int32 biYPelsPerMeter;
            public UInt32 biClrUsed;
            public UInt32 biClrImportant;
        }
 
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public struct BITMAPFILEHEADER
        {
            public Int16 bfType;
            public Int32 bfSize;
            public Int16 bfReserved1;
            public Int16 bfReserved2;
            public Int32 bfOffBits;
        }
 
        int writeDenied = 0x20;
        BITMAPINFOHEADER bih = new BITMAPINFOHEADER();
 
        int streamtypeVIDEO = 1935960438; // 'equivalent to: mmioStringToFOURCC("vids", 0&)
 
        int AVIFile = 0;
        IntPtr aviStream;
       
 
        public Form1()
        {
            InitializeComponent();
        }
 
        private IntPtr IntPtr(int pDib)
        {
            throw new Exception("The method or operation is not implemented.");
        }
 
        private void Form1_Load(object sender, EventArgs e)
        {
            AVIFileInit();
        }
 
        private void cmdGetBitmaps_Click(object sender, EventArgs e)
        {
            int result;
            String fileName;
            int pointerAVI = 0;
            int pointerAVIStream = 0;
            int numberFrames = 0;
            int firstFrame = 0;
 
            AVI_FILE_INFO fileInfo = new AVI_FILE_INFO();
            AVI_STREAM_INFO streamInfo = new AVI_STREAM_INFO();
 
            fileName = "D:\\highway.avi";
 
            try
            {
                result = AVIFileOpen(ref pointerAVI, fileName, writeDenied, 0);
                result = AVIFileGetStream(pointerAVI, out aviStream, streamtypeVIDEO, 0);
                firstFrame = AVIStreamStart(aviStream.ToInt32());
                numberFrames = AVIStreamLength(aviStream.ToInt32());
              
                result = AVIFileInfo(pointerAVI, ref fileInfo, System.Runtime.InteropServices.Marshal.SizeOf(fileInfo));
                result = AVIStreamInfo(aviStream.ToInt32(), ref streamInfo, Marshal.SizeOf(streamInfo));
 
                bih.biBitCount = 24;
                bih.biClrImportant = 0;
                bih.biClrUsed = 0;
                bih.biCompression = 0;
                bih.biHeight = (Int32)(streamInfo.rcFrame.bottom);
                bih.biWidth = (Int32)streamInfo.rcFrame.right;
                bih.biPlanes = 1;
                bih.biSize = (UInt32)Marshal.SizeOf(bih);
                bih.biXPelsPerMeter = 0;
                bih.biYPelsPerMeter = 0;
 
                int getFrameObject = 0;
 
                String dstFileName = "D:\\bitmap";
 
                getFrameObject = AVIStreamGetFrameOpen(aviStream, ref bih);
 
 
 
                for (int i = firstFrame; i < numberFrames - 1; i++)
                {
                    int pDib = AVIStreamGetFrame(getFrameObject, firstFrame + i);
                   
                  
                    bih = (BITMAPINFOHEADER)Marshal.PtrToStructure(new IntPtr(pDib), bih.GetType());
 
                    //Copy the image
                    byte[] bitmapData = new byte[bih.biSizeImage];
                    int address = pDib + Marshal.SizeOf(bih);
                    for (int offset = 0; offset < bitmapData.Length; offset++)
                    {
                        bitmapData[offset] = Marshal.ReadByte(new IntPtr(address));
                        address++;
                    }
 
 
                    //Copy bitmap info
                    byte[] bitmapInfo = new byte[Marshal.SizeOf(bih)];
                    IntPtr ptr;
                    ptr = Marshal.AllocHGlobal(bitmapInfo.Length);
                    Marshal.StructureToPtr(bih, ptr, false);
                    address = ptr.ToInt32();
                    for (int offset = 0; offset < bitmapInfo.Length; offset++)
                    {
                        bitmapInfo[offset] = Marshal.ReadByte(new IntPtr(address));
                        address++;
                    }
 
                    //Create file header
                    BITMAPFILEHEADER bfh = new BITMAPFILEHEADER();
                    bfh.bfType = BMP_MAGIC_COOKIE;
                    bfh.bfSize = (Int32)(55 + bih.biSizeImage); //size of file as written to disk
                    bfh.bfReserved1 = 0;
                    bfh.bfReserved2 = 0;
                    bfh.bfOffBits = Marshal.SizeOf(bih) + Marshal.SizeOf(bfh);
 
 
 
                    //Create or overwrite the destination file
                    FileStream fs = new FileStream(dstFileName + i.ToString() + ".bmp", System.IO.FileMode.Create);
                    BinaryWriter bw = new BinaryWriter(fs);
 
                    //Write header
                    bw.Write(bfh.bfType);
                    bw.Write(bfh.bfSize);
                    bw.Write(bfh.bfReserved1);
                    bw.Write(bfh.bfReserved2);
                    bw.Write(bfh.bfOffBits);
                    //Write bitmap info
                    bw.Write(bitmapInfo);
                    //Write bitmap data
                    bw.Write(bitmapData);
                    bw.Close();
                    fs.Close();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
 
    }
}