none
由C#寫的類別庫,建置成DLL讓VB引用會出問題 RRS feed

  • 問題

  • 最近我在尋找處理AVI的API,我在http://www.codeproject.com/KB/audio-video/avifilewrapper.aspx這個網站找到以C#編寫的類別庫以及使用範例。(原始碼可從該網站下載)

    但是我將AviFile這個類別庫建置成DLL檔後,由VB引用,再仿照範例中部份的寫法以VB的語法去使用這個類別庫,卻會出現問題...


    以下是以VB.NET使用AviFile類別庫的部分程式碼
        Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    
    
    
            Dim aviMang = New AviManager(Label1.Text, True)
    
            Dim stream As VideoStream = aviMang.GetVideoStream
    
            stream.GetFrameOpen()   <<執行到此會出現 "Exception in VideoStreamGetFrameOpen!"
    
            PictureBox1.Image = Avi.GetFrame(Label1.Text, Val(TextBox1.Text))
    
            stream.GetFrameClose()
    
            aviMang.Close()
    
    
    
        End Sub
    
    

    以下為原本C#的範例程式碼,在C#中執行正常
            private void ShowFrame() {
    
                if (System.IO.File.Exists(txtAviFileName.Text)) {
    
                    try {
    
                        AviManager aviManager = new AviManager(txtAviFileName.Text, true);
    
                        VideoStream aviStream = aviManager.GetVideoStream();
    
                        aviStream.GetFrameOpen();
    
    
    
                        Bitmap bmp = aviStream.GetBitmap(Convert.ToInt32(numPosition.Value));
    
                        picFrame.Image = bmp;
    
                        aviStream.GetFrameClose();
    
                        aviManager.Close();
    
                    } catch (Exception ex) {
    
                        MessageBox.Show(ex.ToString());
    
                    }
    
                }
    
            }
    
    

    追蹤錯誤後發現:
    public void GetFrameOpen(){
    
                Avi.AVISTREAMINFO streamInfo = GetStreamInfo(StreamPointer);
    
    
    
                //Open frames
    
    
    
    			Avi.BITMAPINFOHEADER bih = new Avi.BITMAPINFOHEADER();
    
    			bih.biBitCount = countBitsPerPixel;
    
    			bih.biClrImportant = 0;
    
    			bih.biClrUsed = 0;
    
    			bih.biCompression = 0;
    
    			bih.biPlanes = 1;
    
    			bih.biSize = Marshal.SizeOf(bih);
    
    			bih.biXPelsPerMeter = 0;
    
    			bih.biYPelsPerMeter = 0;
    
    
    
    			// Corrections by M. Covington:
    
    			// If these are pre-set, interlaced video is not handled correctly.
    
    			// Better to give zeroes and let Windows fill them in.
    
    			bih.biHeight = 0; // was (Int32)streamInfo.rcFrame.bottom;
    
    			bih.biWidth = 0; // was (Int32)streamInfo.rcFrame.right;
    
    
    
    			// Corrections by M. Covington:
    
    			// Validate the bit count, because some AVI files give a bit count
    
    			// that is not one of the allowed values in a BitmapInfoHeader.
    
    			// Here 0 means for Windows to figure it out from other information.
    
    			if (bih.biBitCount > 24)
    
    			{
    
    				bih.biBitCount = 32;
    
    			}
    
    			else if (bih.biBitCount > 16)
    
    			{
    
    				bih.biBitCount = 24;
    
    			}
    
    			else if (bih.biBitCount > 8)
    
    			{
    
    				bih.biBitCount = 16;
    
    			}
    
    			else if (bih.biBitCount > 4)
    
    			{
    
    				bih.biBitCount = 8;
    
    			}
    
    			else if (bih.biBitCount > 0)
    
    			{
    
    				bih.biBitCount = 4;
    
    			}
    
            
    
               getFrameObject = Avi.AVIStreamGetFrameOpen(StreamPointer, ref bih); //由VB引用時,會導致此行結果為0,但C#不會
    
    
    
                if(getFrameObject == 0){ throw new Exception("Exception in VideoStreamGetFrameOpen!"); }
    
    		}
    
    


    再更進一步追蹤後得到這是引用Windows的API,錯誤源頭在這裡
    		[DllImport("avifil32.dll")]
    
    		public static extern int AVIStreamGetFrameOpen(
    
    			IntPtr pAVIStream,
    
    			ref BITMAPINFOHEADER bih);
    
    


    不知這個問題要如何解決呢?

    我只要一個API,能從指定的AVI檔案中取出任意BMP格式的畫格這樣的功能就好。


    無拘無束的程式設計師
    2009年4月28日 上午 06:33

解答

  • avi / mpeg 都是允許多重格式編碼的檔案,所以表示你現在用的 avi 檔可能經過其他方式編碼,例如 Divx / Xvid。
    api 只能撥放直接由微軟支援的標準格式,其他格式要用 Video Compression Manager 系列 API 將編碼解回 Windows 標準編碼。

    嫌麻煩的話可以用 DirectShow 去播放,自動呼叫 vcm 解碼已經包裝在裡面,若不能播放的,可用 Windows Media Player 撥看看,Media Player 不能播的就要找該檔的解碼器來安裝。

    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    • 已標示為解答 Lolota Lee 2009年5月4日 上午 07:02
    2009年5月2日 上午 06:24

所有回覆

  • 試試  VB  直接呼叫   Win32 API


    <DllImport("avifil32.dll")> _ 
    Public Shared Function AVIStreamGetFrameOpen(ByVal pAVIStream As IntPtr, ByRef bih As BITMAPINFOHEADER) As Integer 
    End Function

    Cmf.Net (C) 2009
    2009年4月28日 上午 08:09
  • cmf您好:


    我將那支程式全部改用VB.NET編寫,但結果還是一樣,在同樣的地方出錯。 

    這看起來似乎是.NET Framework與Windows API之間的問題?

    不知您有何看法?


    若需要改寫後的程式碼,我會再貼上來!


    無拘無束的程式設計師
    2009年4月29日 上午 11:18
  • 經過我多日來的測試,發現原因似乎是出在「輸入的檔案」。有些檔案可以,有些卻不行

    都是AVI檔,但不知為何有差別?


    無拘無束的程式設計師
    2009年5月1日 上午 08:07
  • avi / mpeg 都是允許多重格式編碼的檔案,所以表示你現在用的 avi 檔可能經過其他方式編碼,例如 Divx / Xvid。
    api 只能撥放直接由微軟支援的標準格式,其他格式要用 Video Compression Manager 系列 API 將編碼解回 Windows 標準編碼。

    嫌麻煩的話可以用 DirectShow 去播放,自動呼叫 vcm 解碼已經包裝在裡面,若不能播放的,可用 Windows Media Player 撥看看,Media Player 不能播的就要找該檔的解碼器來安裝。

    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    • 已標示為解答 Lolota Lee 2009年5月4日 上午 07:02
    2009年5月2日 上午 06:24