2010-04-15 24 views
1

J'ai utilisé la dernière version du WPFMediaKit. Ce que j'essaye de faire est d'écrire un exemple d'application qui utilisera le Samplegrabber pour capturer les images vidéo des fichiers vidéo afin que je puisse les avoir comme Bitmaps individuels.Samplegrabber fonctionne très bien sur les fichiers AVI/MPEG, mais saccadée avec WMV

Jusqu'ici, j'ai eu de la chance avec le code suivant lors de la construction et du rendu de mon graphe. Toutefois, lorsque j'utilise ce code pour lire un fichier vidéo .wmv, lorsque le samplegrabber est connecté, il lit jumpy ou hachy. Si je commente la ligne où j'ajoute le filtre samplegrabber, cela fonctionne très bien. Encore une fois, cela fonctionne avec le samplegrabber correctement avec AVI/MPEG, etc.

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

Et:

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

J'ai lu quelques petites choses en disant que les formats .wmv ou .asf sont asynchrones ou quelque chose . J'ai essayé d'insérer un WMAsfReader pour décoder ce qui fonctionne, mais une fois qu'il va à la VMR9, il donne le même comportement. En outre, je l'ai eu pour fonctionner correctement quand je commente la ligne IBaseFilter renderer = CreateVideoMixingRenderer9(m_graph, 1); et ai filterGraph.Render(pins[0]); - le seul inconvénient est que maintenant il rend dans une veuve d'Activemovie de son propre au lieu de mon contrôle, cependant le samplegrabber fonctionne correctement et sans aucun saut . Donc je pense que le bug est dans le VMR9/samplegrabbing quelque part.

Une aide? Je suis nouveau à cela.

Répondre

1

Certains décodeurs utilisent l'accélération matérielle à l'aide de DXVA. Ceci est implémenté en négociant un format partiellement décodé, et en passant ces données partiellement décodées au moteur de rendu pour achever le décodage et le rendu. Si vous insérez une carte d'acquisition configurée en RGB24 entre le décodeur et le moteur de rendu, vous allez désactiver l'accélération matérielle.

Cela, j'en suis sûr, est le noeud du problème. Les détails sont encore un peu vagues, je crains, comme pourquoi cela fonctionne quand vous utilisez le VMR-7 par défaut, mais échoue lorsque vous utilisez VMR-9. Je suppose que le décodeur essaie d'utiliser dxva et échoue, dans le cas vmr-9, mais a une sauvegarde logicielle raisonnable qui fonctionne bien dans vmr-7.

Je ne connais pas le WPFMediaKit, mais je pense que la solution la plus simple est de remplacer la création explicite de vmr-9 par une création explicite de vmr-7. C'est-à-dire que si le décodeur fonctionne uniquement avec vmr-7, utilisez-le et concentrez-vous sur la résolution du problème de réparation de la fenêtre.

+0

Merci, je vais faire quelques recherches pour voir s'il est possible d'utiliser le VMR7 à la place dans le WPFMediakit, ou bien lancer le mien en se basant sur un code similaire à la façon dont le VMR9 est implémenté. Quelque chose que j'ai découvert avec ce problème est que j'obtiens différents résultats sur différents ordinateurs (c.-à-d. Que j'ai apporté cette maison pour travailler la nuit dernière et aucune lecture agitée pour WMV). Je vais étudier graphedit si le graphique sort le même ou quoi sur chacun. Ou vous pouvez être sur quelque chose avec l'accélération matérielle. –

0

Il s'est avéré que le code que j'ai posté (qui était en lui-même légèrement modifié sans vergogne par le code source WPFMediakit de Jeremiah Morrill) était en fait suffisant pour rendre les fichiers .WMV et être échantillonné.

Il semble que le clapot ait quelque chose à voir avec l'exécution du débogueur VS, ou VS2008 lui-même. Après avoir joué un moment avec le XAML dans l'éditeur visuel, puis exécuté l'application, je vais avoir ce comportement instable introduit. Arrêter VS2008 semble y remédier. : P

Donc pas beaucoup d'une réponse, mais au moins un (ennuyeux - redémarrage VS2008) fixer quand il surgit.