2010-04-15 6 views
1

Я использую последнюю версию WPFMediaKit. То, что я пытаюсь сделать, это написать пример приложения, которое будет использовать Samplegrabber для захвата видеокадров видеофайлов, чтобы я мог использовать их как отдельные растровые изображения.Samplegrabber отлично работает с файлами AVI/MPEG, но изменчив с WMV

До сих пор у меня была удача в следующем коде при построении и рендеринге моего графика. Однако, когда я использую этот код для воспроизведения видеофайла .wmv, когда приложение samplegrabber подключено, оно будет воспроизводиться нерешительно или прерывисто. Если я прокомментирую строку, где я добавляю фильтр samplegrabber, он отлично работает. Опять же, он работает с samplegrabber правильно с AVI/MPEG и т.д.

protected virtual void OpenSource() 
    { 
     FrameCount = 0; 
     /* Make sure we clean up any remaining mess */ 
     FreeResources(); 

     if (m_sourceUri == null) 
      return; 

     string fileSource = m_sourceUri.OriginalString; 

     if (string.IsNullOrEmpty(fileSource)) 
      return; 

     try 
     { 
      /* Creates the GraphBuilder COM object */ 
      m_graph = new FilterGraphNoThread() as IGraphBuilder; 

      if (m_graph == null) 
       throw new Exception("Could not create a graph"); 


      /* Add our prefered audio renderer */ 
      InsertAudioRenderer(AudioRenderer); 

      var filterGraph = m_graph as IFilterGraph2; 

      if (filterGraph == null) 
       throw new Exception("Could not QueryInterface for the IFilterGraph2"); 

      IBaseFilter renderer = CreateVideoMixingRenderer9(m_graph, 1);         

      IBaseFilter sourceFilter; 

      /* Have DirectShow find the correct source filter for the Uri */ 
      var hr = filterGraph.AddSourceFilter(fileSource, fileSource, out sourceFilter); 
      DsError.ThrowExceptionForHR(hr); 

      /* We will want to enum all the pins on the source filter */ 
      IEnumPins pinEnum; 

      hr = sourceFilter.EnumPins(out pinEnum); 
      DsError.ThrowExceptionForHR(hr); 

      IntPtr fetched = IntPtr.Zero; 
      IPin[] pins = { null }; 

      /* Counter for how many pins successfully rendered */ 
      int pinsRendered = 0;     

      m_sampleGrabber = (ISampleGrabber)new SampleGrabber(); 
      SetupSampleGrabber(m_sampleGrabber); 
      hr = m_graph.AddFilter(m_sampleGrabber as IBaseFilter, "SampleGrabber"); 
      DsError.ThrowExceptionForHR(hr); 

      /* Loop over each pin of the source filter */ 
      while (pinEnum.Next(pins.Length, pins, fetched) == 0) 
      { 
       if (filterGraph.RenderEx(pins[0], 
             AMRenderExFlags.RenderToExistingRenderers, 
             IntPtr.Zero) >= 0) 
       pinsRendered++; 

       Marshal.ReleaseComObject(pins[0]); 
      } 

      Marshal.ReleaseComObject(pinEnum); 
      Marshal.ReleaseComObject(sourceFilter); 

      if (pinsRendered == 0) 
       throw new Exception("Could not render any streams from the source Uri"); 

      /* Configure the graph in the base class */ 
      SetupFilterGraph(m_graph); 

      HasVideo = true; 
      /* Sets the NaturalVideoWidth/Height */ 
      //SetNativePixelSizes(renderer); 
     } 
     catch (Exception ex) 
     { 
      /* This exection will happen usually if the media does 
      * not exist or could not open due to not having the 
      * proper filters installed */ 
      FreeResources(); 

      /* Fire our failed event */ 
      InvokeMediaFailed(new MediaFailedEventArgs(ex.Message, ex)); 
     } 

     InvokeMediaOpened(); 
    } 

И:

private void SetupSampleGrabber(ISampleGrabber sampleGrabber) 
    { 
     FrameCount = 0; 
     var mediaType = new AMMediaType 
     { 
      majorType = MediaType.Video, 
      subType = MediaSubType.RGB24, 
      formatType = FormatType.VideoInfo 
     }; 

     int hr = sampleGrabber.SetMediaType(mediaType); 

     DsUtils.FreeAMMediaType(mediaType); 
     DsError.ThrowExceptionForHR(hr); 

     hr = sampleGrabber.SetCallback(this, 0); 
     DsError.ThrowExceptionForHR(hr); 
    } 

Я прочитал несколько вещей, произнося в .wmv или .asf форматы являются асинхронными или что-то , Я попытался вставить WMAsfReader для декодирования, который работает, но как только он переходит к VMR9, он дает такое же поведение. Кроме того, я получил правильную работу, когда я прокомментировал строку IBaseFilter renderer = CreateVideoMixingRenderer9(m_graph, 1); и получил filterGraph.Render(pins[0]); - единственный недостаток заключается в том, что теперь он отображает собственную вдову Activemovie вместо моего контроля, однако samplegrabber работает правильно и без каких-либо пропусков , Поэтому я думаю, что ошибка находится в VMR9/samplegrabbing где-то.

Любая помощь? Я новичок в этом.

ответ

1

Некоторые декодеры будут использовать аппаратное ускорение с использованием DXVA. Это реализуется путем согласования частично декодированного формата и передачи этих частично декодированных данных в средство визуализации для завершения декодирования и рендеринга. Если вы вставляете образец grabber, настроенный на RGB24 между декодером и рендерером, вы отключите аппаратное ускорение.

Это, я уверен, является основной проблемой. Я думаю, что детали все еще немного расплывчаты, например, почему это работает, когда вы используете VMR-7 по умолчанию, но сбой при использовании VMR-9. Я предполагаю, что декодер пытается использовать dxva и терпеть неудачу в случае vmr-9, но имеет разумную резервную копию программного обеспечения, которая хорошо работает в vmr-7.

Я не знаком с WPFMediaKit, но я думаю, что самым простым решением является замена явного создания vmr-9 явным созданием vmr-7. То есть, если декодер работает с программным обеспечением, только с vmr-7, используйте его и сосредоточьтесь на исправлении проблемы с обновлением окна.

+0

Спасибо, я сделаю некоторое исследование, чтобы узнать, можно ли использовать VMR7 вместо этого в WPFMediakit или перевернуть мой собственный на основе аналогичного кода на способ реализации VMR9. Что-то, что я обнаружил с этой проблемой, это то, что я получаю разные результаты на разных компьютерах (т. Е. Я привел этот дом для работы прошлой ночью и без прерывистого воспроизведения для WMV). Я собираюсь расследовать с graphedit, если график выходит одинаково или что на каждом. Или вы можете столкнуться с чем-то с аппаратным ускорением. –

0

В конце концов, код, который я опубликовал (который сам по себе был довольно бесстыдно слегка изменен мной из исходного кода Джефрии Моррилла WPFMediakit), был фактически достаточным для рендеринга .WMV-файлов и отбора образцов.

Кажется, что choppiness имеет какое-то отношение к запуску VS-отладчика или VS2008. После некоторого взаимодействия с XAML в визуальном редакторе, после запуска приложения, у меня появится это изменчивое поведение. Выключение VS2008, похоже, исправить. : P

Так что не так много ответа, но по крайней мере (раздражающий - перезапуск VS2008) исправить, когда он появляется.