1

私は最新バージョンのWPFMediaKitを使用しています。私がやろうとしているのは、Samplegrabberを使用してビデオファイルのビデオフレームをキャプチャし、それらを個別のビットマップとして使用できるサンプルアプリケーションを作成することです。

これまでのところ、グラフを作成してレンダリングするときに、次のコードで幸運を祈っています。ただし、このコードを使用して.wmvビデオファイルを再生すると、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/サンプルグラブのどこかにあると思います。

何か助けはありますか?私はこれに不慣れです。

4

2 に答える 2

1

一部のデコーダーは、DXVAを使用したハードウェアアクセラレーションを使用します。これは、部分的にデコードされた形式をネゴシエートし、この部分的にデコードされたデータをレンダラーに渡して、デコードとレンダリングを完了することによって実装されます。RGB24に構成されたサンプルグラバーをデコーダーとレンダラーの間に挿入すると、ハードウェアアクセラレーションが無効になります。

それが問題の核心だと私は確信しています。デフォルトのVMR-7を使用すると機能するのに、VMR-9を使用すると失敗する理由など、詳細はまだ少しあいまいです。vmr-9の場合、デコーダーはdxvaを使用しようとして失敗していると思いますが、vmr-7でうまく機能する妥当なソフトウェアのみのバックアップがあります。

私はWPFMediaKitに精通していませんが、最も簡単な解決策は、明示的なvmr-9の作成を明示的なvmr-7の作成に置き換えることだと思います。つまり、デコーダーがvmr-7でソフトウェアのみで動作する場合は、それを使用して、ウィンドウのリペアレンティングの問題の修正に集中してください。

于 2010-04-16T09:07:12.983 に答える
0

結局、私が投稿したコード(Jeremiah MorrillのWPFMediakitソースコードから私がかなり恥知らずにわずかに変更したもの)は、実際には.WMVファイルをレンダリングしてサンプルを取得するのに十分でした。

途切れ途切れは、VSデバッガーまたはVS2008自体を実行することと関係があるようです。ビジュアルエディターでしばらくXAMLをいじってからアプリを実行すると、この不安定な動作が導入されます。VS2008をシャットダウンすると、問題が解決するようです。:P

答えはそれほど多くありませんが、少なくとも(VS2008を再起動するのは面倒です)問題が発生したときに修正されます。

于 2010-04-16T13:28:54.660 に答える