Example #1
0
        public static void tオーディオレンダラをNullレンダラに変えてフォーマットを取得する(IGraphBuilder graphBuilder, out WaveFormat wfx, out byte[] wfx拡張データ)
        {
            int hr = 0;

            IBaseFilter audioRenderer              = null;
            IPin        rendererInputPin           = null;
            IPin        rendererConnectedOutputPin = null;
            IBaseFilter nullRenderer         = null;
            IPin        nullRendererInputPin = null;

            wfx      = null;
            wfx拡張データ = new byte[0];

            try
            {
                // audioRenderer を探す。

                audioRenderer = CDirectShow.tオーディオレンダラを探して返す(graphBuilder);
                if (audioRenderer == null)
                {
                    return;                             // なかった
                }
                #region [ 音量ゼロで一度再生する。(オーディオレンダラの入力ピンMediaTypeが、接続時とは異なる「正しいもの」に変わる可能性があるため。)]
                //-----------------
                {
                    // ここに来た時点で、グラフのビデオレンダラは無効化(NullRendererへの置換や除去など)しておくこと。
                    // さもないと、StopWhenReady() 時に一瞬だけ Activeウィンドウが表示されてしまう。

                    var mediaCtrl  = (IMediaControl)graphBuilder;
                    var basicAudio = (IBasicAudio)graphBuilder;

                    basicAudio.put_Volume(-10000);                              // 最小音量


                    // グラフを再生してすぐ止める。(Paused → Stopped へ遷移する)

                    mediaCtrl.StopWhenReady();


                    // グラフが Stopped に遷移完了するまで待つ。(StopWhenReady() はグラフが Stopped になるのを待たずに帰ってくる。)

                    FilterState fs = FilterState.Paused;
                    hr = CWin32.S_FALSE;
                    while (fs != FilterState.Stopped || hr != CWin32.S_OK)
                    {
                        hr = mediaCtrl.GetState(10, out fs);
                    }


                    // 終了処理。

                    basicAudio.put_Volume(0);                                           // 最大音量

                    basicAudio = null;
                    mediaCtrl  = null;
                }
                //-----------------
                #endregion

                // audioRenderer の入力ピンを探す。

                rendererInputPin = t最初の入力ピンを探して返す(audioRenderer);
                if (rendererInputPin == null)
                {
                    return;
                }


                // WAVEフォーマットを取得し、wfx 引数へ格納する。

                var type = new AMMediaType();
                hr = rendererInputPin.ConnectionMediaType(type);
                DsError.ThrowExceptionForHR(hr);
                try
                {
                    wfx = new WaveFormat();

                    #region [ type.formatPtr から wfx に、拡張領域を除くデータをコピーする。]
                    //-----------------
                    var wfxTemp = new WaveFormatEx();                           // SharpDX.Multimedia.WaveFormat は Marshal.PtrToStructure() で使えないので、それが使える DirectShowLib.WaveFormatEx を介して取得する。(面倒…)
                    Marshal.PtrToStructure(type.formatPtr, (object)wfxTemp);

                    wfx = WaveFormat.CreateCustomFormat((WaveFormatEncoding)wfxTemp.wFormatTag, wfxTemp.nSamplesPerSec, wfxTemp.nChannels, wfxTemp.nAvgBytesPerSec, wfxTemp.nBlockAlign, wfxTemp.wBitsPerSample);
                    //-----------------
                    #endregion
                    #region [ 拡張領域が存在するならそれを wfx拡張データ に格納する。 ]
                    //-----------------
                    int nWaveFormatEx本体サイズ = 16 + 2;                     // sizeof( WAVEFORMAT ) + sizof( WAVEFORMATEX.cbSize )
                    int nはみ出しサイズbyte       = type.formatSize - nWaveFormatEx本体サイズ;

                    if (nはみ出しサイズbyte > 0)
                    {
                        wfx拡張データ = new byte[nはみ出しサイズbyte];
                        var hGC = GCHandle.Alloc(wfx拡張データ, GCHandleType.Pinned);                                // 動くなよー
                        unsafe
                        {
                            byte *src = (byte *)type.formatPtr.ToPointer();
                            byte *dst = (byte *)hGC.AddrOfPinnedObject().ToPointer();
                            CWin32.CopyMemory(dst, src + nWaveFormatEx本体サイズ, (uint)nはみ出しサイズbyte);
                        }
                        hGC.Free();
                    }
                    //-----------------
                    #endregion
                }
                finally
                {
                    if (type != null)
                    {
                        DsUtils.FreeAMMediaType(type);
                    }
                }


                // audioRenderer につながる出力ピンを探す。

                hr = rendererInputPin.ConnectedTo(out rendererConnectedOutputPin);
                DsError.ThrowExceptionForHR(hr);


                // audioRenderer をグラフから切断する。

                rendererInputPin.Disconnect();
                rendererConnectedOutputPin.Disconnect();


                // audioRenderer をグラフから除去する。

                hr = graphBuilder.RemoveFilter(audioRenderer);
                DsError.ThrowExceptionForHR(hr);


                // nullRenderer を作成し、グラフに追加する。

                nullRenderer = (IBaseFilter) new NullRenderer();
                hr           = graphBuilder.AddFilter(nullRenderer, "Audio Null Renderer");
                DsError.ThrowExceptionForHR(hr);


                // nullRenderer の入力ピンを探す。

                hr = nullRenderer.FindPin("In", out nullRendererInputPin);
                DsError.ThrowExceptionForHR(hr);


                // nullRenderer をグラフに接続する。

                hr = rendererConnectedOutputPin.Connect(nullRendererInputPin, null);
                DsError.ThrowExceptionForHR(hr);
            }
            finally
            {
                CCommon.tReleaseComObject(ref nullRendererInputPin);
                CCommon.tReleaseComObject(ref nullRenderer);
                CCommon.tReleaseComObject(ref rendererConnectedOutputPin);
                CCommon.tReleaseComObject(ref rendererInputPin);
                CCommon.tReleaseComObject(ref audioRenderer);
            }
        }