Pergunta

Eu tenho usado a versão mais recente do Wpfmediakit. O que estou tentando fazer é escrever um aplicativo de amostra que usará o Samplegrabber para capturar os quadros de vídeo dos arquivos de vídeo para que eu possa tê -los como bitmaps individuais.

Até agora, tive boa sorte com o código a seguir ao construir e renderizar meu gráfico. No entanto, quando eu uso esse código para reproduzir um arquivo de vídeo .wmv, quando o Samplegrabber estiver conectado, ele reproduz backpy ou agitado. Se eu comentar a linha em que adiciono o filtro Samplegrabber, ele funciona bem. Novamente, funciona com o Samplegrabber corretamente com 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();
    }

E:

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

Eu li algumas coisas dizendo que os formatos .wmv ou .asf são assíncronos ou algo assim. Eu tentei inserir um WMASFReader para decodificar o que funciona, mas uma vez que ele vai para o VMR9, ele oferece o mesmo comportamento. Além disso, consegui funcionar corretamente quando comentar o IBaseFilter renderer = CreateVideoMixingRenderer9(m_graph, 1); linha e tem filterGraph.Render(pins[0]); - A única desvantagem é que agora ela se torna uma viúva ActiveMovie, em vez de meu controle, no entanto, o Samplegrabber funciona corretamente e sem pular. Então, acho que o bug está no VMR9 / SampleGrabbing em algum lugar.

Qualquer ajuda? Eu sou novo nisso.

Foi útil?

Solução

Alguns decodificadores usarão a aceleração de hardware usando o DXVA. Isso é implementado negociando um formato parcialmente decodificado e passando esses dados parcialmente decodificados ao renderizador para concluir a decodificação e a renderização. Se você inserir um amostra de grabber configurado para RGB24 entre o decodificador e o renderizador, você desativará a aceleração do hardware.

Tenho certeza de que é o cerne do problema. Os detalhes ainda são um pouco vagos, receio, como por que funciona quando você usa o VMR-7 padrão, mas falha quando você usa o VMR-9. Eu acho que o decodificador está tentando usar o DXVA e falhar, no caso VMR-9, mas possui um backup de software razoável que funciona bem no VMR-7.

Não estou familiarizado com o WPFMediaKit, mas acho que a solução mais simples é substituir a criação explícita do VMR-9 por uma criação explícita do VMR-7. Ou seja, se o decodificador funcionar apenas com software com o VMR-7, use-o e concentre-se em corrigir o problema de repartição de janelas.

Outras dicas

Acabou com o código que publiquei (que por si só foi descaradamente modificado por mim do código -fonte WPFMediaKit de Jeremiah Morrill) foi de fato adequado para tornar os arquivos .wmv e ser amostral.

Parece que o toque tem algo a ver com o depurador do VS, ou o próprio VS2008. Depois de mexer com o XAML por um tempo no editor visual e, em seguida, executando o aplicativo, terei esse comportamento agitado introduzido. Desligar o VS2008 parece remedi -lo. : P

Portanto, não há muita resposta, mas pelo menos uma correção (irritante - reiniciando vs2008) quando ele surge.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top