2010-04-15 2 views
1

WPFMediaKit의 최신 버전을 사용하고 있습니다. 내가 뭘 하려는지 Samplegrabber 비디오 파일의 비디오 프레임을 캡처 할 수 있도록 샘플 비트 맵으로 가질 수있는 샘플 응용 프로그램을 작성하는 것입니다.Samplegrabber는 AVI/MPEG 파일에서는 정상적으로 작동하지만 WMV에서는 고르지 않습니다

지금까지 그래프를 구성하고 렌더링 할 때 다음 코드를 사용해 보았습니다. 그러나이 코드를 사용하여 .wmv 비디오 파일을 재생할 때 samplegrabber가 연결되면 불안정하거나 고르지 않게 재생됩니다. samplegrabber 필터를 추가하는 행을 주석 처리하면 정상적으로 작동합니다. 나는이 (가) .WMV 또는 ASF는 형식 비동기 또는 뭔가있는 말을 몇 가지를 읽고

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); 
    } 

: 다시, 등 AVI/MPEG로 올바르게 samplegrabber와

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(); 
    } 

및 작동 . 디코딩 할 WMAsfReader를 삽입하려고 시도했지만 일단 VMR9로 이동하면 동일한 동작이 발생합니다. 또한 IBaseFilter renderer = CreateVideoMixingRenderer9(m_graph, 1); 라인을 주석 처리하고 filterGraph.Render(pins[0]);을 가지고있을 때 제대로 작동하도록했습니다. 유일한 단점은 이제 내 컨트롤 대신 자체 Activemovie widow에서 렌더링되지만, samplegrabber는 올바르게 건너 뛰고 건너 뛰지 않고 렌더링된다는 것입니다. . 그래서 버그가 VMR9/samplegrabbing 어딘가에 있다고 생각합니다.

어떤 도움이 필요합니까? 나는 이것에 초보적이다.

답변

1

일부 디코더는 DXVA를 사용하여 하드웨어 가속을 사용합니다. 이는 부분적으로 디코딩 된 형식을 협상하고이 부분적으로 디코딩 된 데이터를 렌더러에 전달하여 디코딩 및 렌더링을 완료함으로써 구현됩니다. 디코더와 렌더러 사이에 RGB24로 구성된 샘플 그래버를 삽입하면 하드웨어 가속을 사용할 수 없게됩니다.

그건 분명, 문제의 핵심입니다. 세부 사항은 여전히 ​​다소 모호 합니다만, 기본 VMR-7을 사용할 때 왜 작동하는지 등 VMR-9를 사용할 때 실패합니다. 나는 디코더가 dxva를 사용하려고 시도하고 vmr-9의 경우에는 실패했지만 vmr-7에서 잘 작동하는 합당한 소프트웨어 전용 백업을 가지고 있다고 생각합니다.

저는 WPFMediaKit에 익숙하지 않지만, 가장 간단한 해결책은 명백한 vmr-9 생성을 명시적인 vmr-7 생성으로 대체하는 것입니다. 즉, 디코더가 vmr-7 만 사용하여 소프트웨어로 작동하는 경우이를 사용하고 창 - 보 충 문제를 해결하는 데 집중하십시오.

+0

감사합니다. 대신 WPFMediakit에서 VMR7을 사용할 수 있는지 또는 VMR9가 구현되는 방식과 유사한 코드를 기반으로 자체적으로 롤업 할 수 있는지 조사 할 것입니다. 이 문제점으로 발견 한 점은 다른 컴퓨터에서 다른 결과를 얻는다는 것입니다. 즉, 어젯밤에이 집을 가져 왔고 WMV는 고르지 않게 재생했습니다. 그래프가 똑같이 나오는 지 아니면 각각 그래프가 나오는지를 graphedit으로 조사하려고합니다. 또는 하드웨어 가속 기능을 사용할 수도 있습니다. –

0

실제로 게시 된 코드는 Jeremiah Morrill의 WPFMediakit 소스 코드에서 약간 뻔뻔스럽게 수정되었습니다. 실제로는 .WMV 파일을 렌더링하고 샘플링하기에 충분했습니다.

choppiness는 VS 디버거 또는 VS2008 자체를 실행하는 것과 관련이있는 것 같습니다. 시각적 편집기에서 XAML을 잠시 둘러보고 나서 앱을 실행하면이 고르지 못한 동작이 도입됩니다. VS2008을 종료하는 것은 그것을 해결하는 것 같습니다. : P

답변이 많지는 않지만 적어도 짜증나는 (다시 짜증나는 VS2008) 픽스가 수정되었습니다.

관련 문제