2016-09-20 22 views
3

Я использую DirectShow.NET для создания управления веб-камерой для WPF. Я успешно создал график и могу получить видео с камеры для отображения на моем экране. Тем не менее, видеовыход полностью не зависит от элемента управления WPF, в котором он создается.Приложить видео-окно DirectShow к управлению WPF

Я устанавливаю владельца видеоокна, вызывая videoWindow.put_owner(hWnd), где hWnd - это дескриптор окна в текущее окно WPF. Я получаю эту ручку окна с помощью WindowInteropHelper.

Вот основная процедура:

public void CaptureVideo() 
     { 
      int hr = 0; 
      IBaseFilter sourceFilter = null; 

      try 
      { 
       hr = this.captureGraphBuilder.SetFiltergraph(this.graphBuilder); 
       DsError.ThrowExceptionForHR(hr); 

       sourceFilter = FindCaptureDevice(); 

       hr = this.graphBuilder.AddFilter(sourceFilter, "Video Capture"); 
       DsError.ThrowExceptionForHR(hr); 

       hr = this.captureGraphBuilder.RenderStream(PinCategory.Preview, MediaType.Video, sourceFilter, null, null); 
       DsError.ThrowExceptionForHR(hr); 

       Marshal.ReleaseComObject(sourceFilter); 

       SetupVideoWindow(); 

       hr = this.mediaControl.Run(); 
       DsError.ThrowExceptionForHR(hr); 
      } 
      catch 
      { 
       Console.WriteLine("An unrecoverable DirectShow error has occurred."); 
      } 
     } 

И код SetupVideoWindow():

public void SetupVideoWindow() 
     { 
      int hr = 0; 

      Window window = Window.GetWindow(this); 
      var wih = new WindowInteropHelper(window); 
      IntPtr hWnd = wih.Handle; 

      hr = this.videoWindow.put_Owner(hWnd); 
      DsError.ThrowExceptionForHR(hr); 

      hr = this.videoWindow.put_WindowStyle(DirectShowLib.WindowStyle.Child | DirectShowLib.WindowStyle.ClipChildren); 
      DsError.ThrowExceptionForHR(hr); 

      this.videoWindow.SetWindowPosition(0, 0, (int)this.Width, (int)this.Height); 

      hr = this.videoWindow.put_Visible(OABool.True); 
      DsError.ThrowExceptionForHR(hr); 
     } 

Вот изображение того, что происходит: DirectShow.NET Video Window and WPF MainWindow Control

+0

Последний аргумент вызова 'RenderStream' не имеет смысла. Кроме того, может случиться так, что ваш 'hWnd' равен нулю/null, что объясняет поведение. –

+0

@RomanR. Ах, да, я просто пытался кое-что изложить, и кажется, что я скопировал неправильный код. Я отредактировал его, чтобы отразить фактический код, который я использую, для получения вышеуказанных результатов. Возможно ли, что hWnd равно нулю/null, потому что я использую WPF? Это единственный ответ, который, похоже, я вижу в Интернете. –

+0

Итак, можете ли вы отладить и убедиться, что 'hWnd' отличен от нуля? Для нуля поведение вполне ожидаемо (тем не менее не тот, который вы хотите). Возможно, вы настраиваете его слишком рано, пока ручка даже не существует (выделена). –

ответ

2

Видеообъекты, работающие в оконном режиме (то же самое относится к без окон), требуют, чтобы вы предоставили действительный дескриптор окна HWND, чтобы видео можно было точно интегрировать со стандартным интерфейсом. Ваш фрагмент кода SetupVideoWindow выполняет точно инициализацию видео «в качестве дочернего элемента управления».

WPF - это своего рода новый интерфейс пользовательского интерфейса, который не требует создания дескриптора окна для каждого элемента управления пользовательского интерфейса, и нет четкого и прямого свойства для запроса дескриптора, чтобы перейти к инициализации VMR. Следовательно, WindowInteropHelper, который вы используете правильно, за исключением того, что действительный дескриптор доступен, как только он фактически назначен, что не является конструктором формы.

Использование нулевого дескриптора указывает, что видеообъектив отправляет видео на окно рабочего стола, и поведение, которое вы видите, ожидается и понятно.

Вам нужно проверить значение дескриптора с помощью отладчика, а если оно равно нулю, переместите код конфигурации на более поздний этап построения формы. Необязательный дескриптор окна во время установки должен помещать видео на место.

0

Насколько Я помню, DirectShow использует прямой доступ к видеопамяти, чтобы представить контент на экране для лучшей производительности, поэтому, скорее всего, this.videoWindow.SetWindowPosition(0, 0, (int)this.Width, (int)this.Height); должен находиться в координатах экрана.

I.e. вам нужно получить положение окна WPF для размещения на экране и его размер (используя WinApi) и перейти к методу SetWindowPosition. И делайте это каждый раз, когда ваше окно перемещается/изменяется.

Извините за неполный ответ (для решения проблемы не требуется точный код), потому что я много лет назад сделал это на C++ с помощью WinApi.