2012-04-14 26 views
1

カメラからのライブビデオを表示するためのDirectShowビデオコントロールを使用すると、すべて動作しますが、モーションの歪みは本当に悪いです。それはビデオの端にジャグのようなのこぎり歯を作成します。 usbからPCIキャプチャカードに変更され、改善されていません。カメラベンダーのアプリは美しいフルモーションビデオを表示するので、h/wは大丈夫です。何か案は?DirectShowビデオ品質の問題

using System; 
using System.Diagnostics; 
using System.Drawing; 
using System.Runtime.InteropServices; 
using System.Windows.Forms; 
using DirectShowLib; 
using System.Runtime.InteropServices.ComTypes; 

namespace VideoDisplayControl 
{ 
// [Guid("43878F19-1E0E-42d2-B72B-88A94418A302"), ComVisible(true)] 
    public partial class VideoDisplayControl : UserControl 
    { 
     public enum PlayState : int 
     { 
      Stopped, 
      Paused, 
      Running, 
      Error, 
      Init 
     } 

     private static int WM_GRAPHNOTIFY = Convert.ToInt32("0X8000", 16) + 1; 

     private PlayState _currentState = PlayState.Stopped; 
     private IVideoWindow _videoWindow = null; 
     private IMediaControl _mediaControl = null; 
     private IMediaEventEx _mediaEventEx = null; 
     private IGraphBuilder _graphBuilder = null; 
     private ICaptureGraphBuilder2 _captureGraphBuilder = null; 
     private float _imageAspectRatio = 0f; 
     private System.Windows.Forms.Label labelError; 

     public PlayState State 
     { 
      get { return _currentState; } 
     } 

     public VideoDisplayControl() 
     { 
      components = new System.ComponentModel.Container(); 

      this.labelError = new System.Windows.Forms.Label(); 
      this.SuspendLayout(); 

      // Error label 
      this.labelError.BorderStyle = System.Windows.Forms.BorderStyle.None; 
      this.labelError.ForeColor = Color.DimGray; 
      this.labelError.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 
      this.labelError.Location = new System.Drawing.Point(0, 0); 
      this.labelError.Name = "labelError"; 
      this.labelError.Size = new System.Drawing.Size(50, 50); 
      this.labelError.TabIndex = 1; 
      this.labelError.Text = "Video Source Not Available"; 
      this.labelError.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; 
      this.labelError.Visible = false; 

      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 
//   System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(VideoDisplayControl)); 
      this.Controls.Add(this.labelError); 
      this.ResumeLayout(false); 
      this.PerformLayout(); 

      this.Load += new System.EventHandler(VideoDisplayControl_Load); 
     } 

     private void VideoDisplayControl_Load(object sender, System.EventArgs e) 
     { 
      this.Resize += new System.EventHandler(VideoDisplayControl_Resize); 
      CaptureVideo(); 
     } 

     private void VideoDisplayControl_Resize(object sender, System.EventArgs e) 
     { 
      if (this._videoWindow == null) 
       return; 

      // Attempt to keep aspect ratio of source 
      if (_imageAspectRatio > 0) 
      { 
       int width = Math.Min(this.Width, (int)(this.ClientSize.Height * _imageAspectRatio)); 
       int height = Math.Min(this.ClientSize.Height, (int)(this.Width/_imageAspectRatio)); 
       int posX = (this.Width - width)/2; // Center within control 
       int posY = (this.ClientSize.Height - height)/2; 
       this._videoWindow.SetWindowPosition(posX, posY, width, height); 
      } 
      else // resize to size of control 
       this._videoWindow.SetWindowPosition(0, 0, this.Width, this.ClientSize.Height); 

      this.labelError.Size = new System.Drawing.Size(this.Width, this.ClientSize.Height); 
     } 

     private void CaptureVideo() 
     { 
      int hr = 0; 
      IBaseFilter sourceFilter = null; 
      try 
      { 
       GetInterfaces(); // Interface with DirectShow 

       hr = _captureGraphBuilder.SetFiltergraph(_graphBuilder); 
       DsError.ThrowExceptionForHR(hr); 

       sourceFilter = FindCaptureDevice(); 

       hr = _graphBuilder.AddFilter(sourceFilter, "VideoDisplay Filter"); 
       DsError.ThrowExceptionForHR(hr); 

       hr = _captureGraphBuilder.RenderStream(PinCategory.Preview, MediaType.Video, sourceFilter, null, null); 
       Debug.WriteLine(DsError.GetErrorText(hr)); 
       DsError.ThrowExceptionForHR(hr); 

       Marshal.ReleaseComObject(sourceFilter); 

       SetupVideoWindow(); 

       hr = _mediaControl.Run(); 
       DsError.ThrowExceptionForHR(hr); 

       int width, height; 
       hr = _videoWindow.GetMaxIdealImageSize(out width, out height); 
       if ((hr == 0) && (width > 0) && (height > 0)) 
       { 
        _imageAspectRatio = (float)width/(float)height; 
        VideoDisplayControl_Resize(this, null); 
       } 

       _currentState = PlayState.Running; 
      } 
      catch (Exception) 
      { 
       _currentState = PlayState.Error; // Set error state 
       this.labelError.Visible = true; // Display the "video not available" label 
       VideoDisplayControl_Resize(this, null); // resize control to center label 
      } 
     } 

     private IBaseFilter FindCaptureDevice() 
     { 
      IEnumMoniker classEnum = null; 
      IMoniker[] moniker = new IMoniker[1]; 
      object source = null; 

      ICreateDevEnum devEnum = (ICreateDevEnum)(new CreateDevEnum()); 
      int hr = devEnum.CreateClassEnumerator(FilterCategory.VideoInputDevice, out classEnum, CDef.None); 
      DsError.ThrowExceptionForHR(hr); 
      Marshal.ReleaseComObject(devEnum); 

      if (classEnum == null) 
      { 
       throw new ApplicationException("No video capture device was detected.\\r\\n\\r\\n" + "This sample requires a video capture device, such as a USB WebCam,\\r\\nto be installed and working properly. The sample will now close."); 
      } 

      System.IntPtr none = System.IntPtr.Zero; 

      if (classEnum.Next(moniker.Length, moniker, none) == 0) 
      { 
       Guid iid = typeof(IBaseFilter).GUID; 
       moniker[0].BindToObject(null, null, ref iid, out source); 
      } 
      else 
      { 
       throw new ApplicationException("Unable to access video capture device!"); 
      } 

      Marshal.ReleaseComObject(moniker[0]); 
      Marshal.ReleaseComObject(classEnum); 

      return (IBaseFilter)source; 
     } 

     private void GetInterfaces() 
     { 
      _graphBuilder = (IGraphBuilder)(new FilterGraph()); 
      _captureGraphBuilder = (ICaptureGraphBuilder2)(new CaptureGraphBuilder2()); 
      _mediaControl = (IMediaControl)_graphBuilder; 
      _videoWindow = (IVideoWindow)_graphBuilder; 
      _mediaEventEx = (IMediaEventEx)_graphBuilder; 

      // send notification messages to the control window 
      int hr = _mediaEventEx.SetNotifyWindow(this.Handle, WM_GRAPHNOTIFY, IntPtr.Zero); 

      DsError.ThrowExceptionForHR(hr); 
     } 

     private void HandleGraphEvent() 
     { 
      int hr = 0; 
      EventCode evCode = 0; 
      IntPtr evParam1; 
      IntPtr evParam2; 

      while (this._mediaEventEx != null && _mediaEventEx.GetEvent(out evCode, out evParam1, out evParam2, 0) == 0) 
      { 
       // Free event parameters to prevent memory leaks associated with 
       // event parameter data. While this application is not interested 
       // in the received events, applications should always process them. 
       hr = _mediaEventEx.FreeEventParams(evCode, evParam1, evParam2); 
       DsError.ThrowExceptionForHR(hr); 

       // Insert event processing code here, if desired (see http://msdn2.microsoft.com/en-us/library/ms783649.aspx) 
      } 
     } 

     private void ReleaseInterfaces() 
     { 
      if (this._mediaControl != null) 
       this._mediaControl.StopWhenReady(); 

      this._currentState = PlayState.Stopped; 

      // stop notifications of events 
      if (this._mediaEventEx != null) 
       this._mediaEventEx.SetNotifyWindow(IntPtr.Zero, WM_GRAPHNOTIFY, IntPtr.Zero); 

      //// Relinquish ownership (IMPORTANT!) of the video window. 
      //// Failing to call put_Owner can lead to assert failures within 
      //// the video renderer, as it still assumes that it has a valid 
      //// parent window. 
      if (this._videoWindow != null) 
      { 
       this._videoWindow.put_Visible(OABool.False); 
       this._videoWindow.put_Owner(IntPtr.Zero); 
      } 

      // Release DirectShow interfaces 
      Marshal.ReleaseComObject(this._mediaControl); 
      this._mediaControl = null; 

      Marshal.ReleaseComObject(this._mediaEventEx); 
      this._mediaEventEx = null; 

      Marshal.ReleaseComObject(this._videoWindow); 
      this._videoWindow = null; 

      Marshal.ReleaseComObject(this._graphBuilder); 
      this._graphBuilder = null; 

      Marshal.ReleaseComObject(this._captureGraphBuilder); 
      this._captureGraphBuilder = null; 
     } 

     private void SetupVideoWindow() 
     { 
      int hr = 0; 

      //set the video window to be a child of the main window 
      //putowner : Sets the owning parent window for the video playback window. 
      hr = _videoWindow.put_Owner(this.Handle); 
      DsError.ThrowExceptionForHR(hr); 

      hr = _videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipChildren); 
      DsError.ThrowExceptionForHR(hr); 

      //Use helper function to position video window in client rect of main application window 
      VideoDisplayControl_Resize(this, null); 

      //Make the video window visible, now that it is properly positioned 
      //put_visible : This method changes the visibility of the video window. 
      hr = _videoWindow.put_Visible(OABool.True); 
      DsError.ThrowExceptionForHR(hr); 
     } 

     protected override void WndProc(ref Message m) 
     { 
      if (m.Msg == WM_GRAPHNOTIFY) 
      { 
       HandleGraphEvent(); 
      } 
      if (_videoWindow != null) 
      { 
       _videoWindow.NotifyOwnerMessage(m.HWnd, m.Msg, m.WParam, m.LParam); 
      } 
      base.WndProc(ref m); 
     } 
    } 
} 
+0

Screenshot?重要なのはグラフトポロジーであり、それはコードからはっきりと分かりません。 –

+0

私はあなたが探しているものを理解していません。スクリーンショットはビデオが入った正方形のボックスになります。モーションに問題があるだけなので、キャプチャするのは難しいでしょう。この文脈でグラフのトポロジを説明することができますか? –

+0

接続されたフィルタのセットであるパイプラインを構築しています。どのように接続されているか、どのフィルタが参加しているかを調べる必要があります。それらをベンダーのアプリと比較すると、アプリがあまりうまくいかない理由がすぐにあなたの質問に答えるかもしれません。 –

答えて

1

これは、インターレースの問題であることが判明しました。カメラはインターレースビデオを出力していましたが、キャプチャカードはインターレース解除されていませんでした。私はvid capカードドライバのde-interlacingを有効にして、すべてうまくいきます。これはキャプチャカードのメーカー、Osprey(Viewcast)によって提案されました。

関連する問題