// 再生、停止


        /// <summary>
        ///     指定した時刻からデコードを開始する。
        /// </summary>
        /// <param name="再生開始時刻sec">再生開始時刻[秒]。再生速度を考慮済みであること。</param>
        public void Start(double 再生開始時刻sec)
        {
            using var _ = new LogBlock(Log.現在のメソッド名);

            if (再生開始時刻sec >= this.総演奏時間sec)
            {
                return;
            }

            this._デコード起動完了通知.Reset();
            this._一時停止解除通知.Set();

            // (1) デコードタスク起動、デコード開始。
            this._デコードタスク = Task.Factory.StartNew(  // Task.Factory.StartNew は常に MTAThread
                this._デコードタスクエントリ,
                再生開始時刻sec,
                this._デコードキャンセル.Token);

            // (2) デコードから起動完了通知がくるまでブロック。
            this._デコード起動完了通知.Wait();
        }
Beispiel #2
0
        /// <summary>
        ///     世代を1つ加算する。
        /// </summary>
        public void 世代を進める()
        {
            using var _ = new LogBlock(Log.現在のメソッド名);

            // 今回の世代では貸与されなかった(=最終貸与世代が現時点の世代ではない)キャッシュデータをすべて破棄する。

            var 削除対象リスト = this._キャッシュデータリスト
                          .Where((kvp) => kvp.Value.最終貸与世代 < this.現世代)
                          .Select((kvp) => kvp.Key)
                          .ToArray();

            foreach (var key in 削除対象リスト)
            {
                this._キャッシュデータリスト[key].Dispose();
                this._キャッシュデータリスト.Remove(key);
            }

            Log.Info($"{this._キャッシュデータリスト.Count} 個のサウンドのうち、{削除対象リスト.Length} 個を削除しました。");

            // 世代番号を1つ加算する。

            this.現世代++;
        }
        /// <summary>
        ///     デコードを終了する。
        /// </summary>
        public void Stop()
        {
            using var _ = new LogBlock(Log.現在のメソッド名);

            if ((null != this._デコードタスク) && !(this._デコードタスク.IsCompleted))        // デコードタスク起動中?
            {
                // (1) デコードタスクにキャンセルを通知。
                this._デコードキャンセル.Cancel();

                // (2) デコードタスクがキューでブロックしてたら解除する。
                this._FrameQueue.Cancel();

                // (3) デコードタスクが一時停止中でブロックしてたら解除する。
                this._一時停止解除通知.Set();

                // (4) デコードタスクが終了するまで待つ。
                if (!(this._デコードタスク.Wait(5000)))        // 最大5秒
                {
                    Log.ERROR($"デコードタスクの終了がタイムアウトしました。");
                }

                this._デコードタスク = null;
            }
        }
Beispiel #4
0
        public virtual void Dispose()
        {
            using var _ = new LogBlock(Log.現在のメソッド名);

            this._SoundTimer = null !;
        }
Beispiel #5
0
        public CacheStore()
        {
            using var _ = new LogBlock(Log.現在のメソッド名);

            this._キャッシュデータリスト = new Dictionary <string, キャッシュ情報 <T> >();
        }
        // 生成と終了


        public MediaFoundationFileVideoSource(DXGIDeviceManager deviceManager, DeviceContext d2dDeviceContext, VariablePath ファイルパス, double 再生速度 = 1.0)
        {
            using var _ = new LogBlock(Log.現在のメソッド名);

            this._D2DDeviceContext = d2dDeviceContext;

            this.再生速度 = Math.Clamp(再生速度, min: 0.01, max: 10.0);

            #region " フレームキューを生成。"
            //----------------
            // キューサイズは3フレームとする。
            this._FrameQueue = new BlockingQueue <VideoFrame>(3);
            //----------------
            #endregion

            #region " ファイルから SourceReaderEx を生成する。"
            //----------------
            using (var ビデオ属性 = new MediaAttributes())
            {
                // DXVAに対応しているGPUの場合には、それをデコードに利用するよう指定する。
                ビデオ属性.Set(SourceReaderAttributeKeys.D3DManager, deviceManager);

                // 追加のビデオプロセッシングを有効にする。
                ビデオ属性.Set(SourceReaderAttributeKeys.EnableAdvancedVideoProcessing, true);    // 真偽値が bool だったり

                // 追加のビデオプロセッシングを有効にしたら、こちらは無効に。
                ビデオ属性.Set(SinkWriterAttributeKeys.ReadwriteDisableConverters, 0);             // int だったり

                // 属性を使って、SourceReaderEx を生成。
                using var sourceReader = new SourceReader(ファイルパス.数なしパス, ビデオ属性);       // パスは URI 扱い
                this._SourceReaderEx   = sourceReader.QueryInterface <SourceReaderEx>();
            }

            // 最初のビデオストリームだけを選択。
            this._SourceReaderEx.SetStreamSelection(SourceReaderIndex.AllStreams, false);
            this._SourceReaderEx.SetStreamSelection(SourceReaderIndex.FirstVideoStream, true);
            //----------------
            #endregion

            #region " ビデオの長さ(総演奏時間)を取得する。"
            //----------------
            {
                var mediaSourceDuration = this._SourceReaderEx.GetPresentationAttribute(SourceReaderIndex.MediaSource, PresentationDescriptionAttributeKeys.Duration);
                this.総演奏時間sec = (long)(mediaSourceDuration / this.再生速度 / 10_000_000.0);
            }
            //----------------
            #endregion

            #region " デコーダを選択し、完全メディアタイプを取得する。"
            //----------------
            // 部分メディアタイプを設定する。
            using (var 部分MediaType = new MediaType())
            {
                // フォーマットは ARGB32 で固定とする。(SourceReaderEx を使わない場合、H264 では ARGB32 が選べないので注意。)
                部分MediaType.Set(MediaTypeAttributeKeys.MajorType, MediaTypeGuids.Video);
                部分MediaType.Set(MediaTypeAttributeKeys.Subtype, VideoFormatGuids.Argb32);

                // 部分メディアタイプを SourceReaderEx にセットする。SourceReaderEx は、必要なデコーダをロードするだろう。
                this._SourceReaderEx.SetCurrentMediaType(SourceReaderIndex.FirstVideoStream, 部分MediaType);
            }

            // 完成されたメディアタイプを取得する。
            this._MediaType = this._SourceReaderEx.GetCurrentMediaType(SourceReaderIndex.FirstVideoStream);
            //----------------
            #endregion

            #region " ビデオのフレームサイズを取得する。(動画の途中でのサイズ変更は考慮しない。)"
            //----------------
            long packedFrameSize = this._MediaType.Get(MediaTypeAttributeKeys.FrameSize);
            this.フレームサイズ = new Size2F((packedFrameSize >> 32) & 0xFFFFFFFF, (packedFrameSize) & 0xFFFFFFFF);
            //----------------
            #endregion

            this._デコードキャンセル  = new CancellationTokenSource();
            this._デコード起動完了通知 = new ManualResetEventSlim(false);
            this._一時停止解除通知   = new ManualResetEventSlim(true);
        }
        /// <summary>
        ///     デコードを再開する。
        ///     <see cref="Pause"/>で停止しているときのみ有効。
        /// </summary>
        public void Resume()
        {
            using var _ = new LogBlock(Log.現在のメソッド名);

            this._一時停止解除通知.Set();   // 解除
        }
        /// <summary>
        ///     デコードを一時停止する。
        /// </summary>
        public void Pause()
        {
            using var _ = new LogBlock(Log.現在のメソッド名);

            this._一時停止解除通知.Reset();
        }
Beispiel #9
0
 public void Dispose()
 {
     using var _ = new LogBlock(Log.現在のメソッド名);
 }
Beispiel #10
0
        public static void 全インスタンスで共有するリソースを作成する(Device1 d3dDevice1, VariablePath 頂点シェーダCSOパス, VariablePath ピクセルシェーダCSOパス)
        {
            using var _ = new LogBlock(Log.現在のメソッド名);

            #region " 頂点シェーダを生成する。"
            //----------------
            {
                var byteCode = File.ReadAllBytes(頂点シェーダCSOパス.数なしパス);
                _VertexShader = new VertexShader(d3dDevice1, byteCode);
            }
            //----------------
            #endregion

            #region " ピクセルシェーダを生成する。"
            //----------------
            {
                var byteCode = File.ReadAllBytes(ピクセルシェーダCSOパス.数なしパス);
                _PixelShader = new PixelShader(d3dDevice1, byteCode);
            }
            //----------------
            #endregion

            #region " ブレンドステート通常版を生成する。"
            //----------------
            {
                var BlendStateNorm = new BlendStateDescription()
                {
                    AlphaToCoverageEnable  = false,                                             // アルファマスクで透過する(するならZバッファ必須)
                    IndependentBlendEnable = false,                                             // 個別設定。false なら BendStateDescription.RenderTarget[0] だけが有効で、[1~7] は無視される。
                };
                BlendStateNorm.RenderTarget[0].IsBlendEnabled        = true;                    // true ならブレンディングが有効。
                BlendStateNorm.RenderTarget[0].RenderTargetWriteMask = ColorWriteMaskFlags.All; // RGBA の書き込みマスク。

                // アルファ値のブレンディング設定 ... 特になし
                BlendStateNorm.RenderTarget[0].SourceAlphaBlend      = BlendOption.One;
                BlendStateNorm.RenderTarget[0].DestinationAlphaBlend = BlendOption.Zero;
                BlendStateNorm.RenderTarget[0].AlphaBlendOperation   = BlendOperation.Add;

                // 色値のブレンディング設定 ... アルファ強度に応じた透明合成(テクスチャのアルファ値は、テクスチャのアルファ×ピクセルシェーダでの全体アルファとする(HLSL参照))
                BlendStateNorm.RenderTarget[0].SourceBlend      = BlendOption.SourceAlpha;
                BlendStateNorm.RenderTarget[0].DestinationBlend = BlendOption.InverseSourceAlpha;
                BlendStateNorm.RenderTarget[0].BlendOperation   = BlendOperation.Add;

                // ブレンドステートを作成する。
                _BlendState通常合成 = new BlendState(d3dDevice1, BlendStateNorm);
            }
            //----------------
            #endregion

            #region " ブレンドステート加算合成版を生成する。"
            //----------------
            {
                var BlendStateAdd = new BlendStateDescription()
                {
                    AlphaToCoverageEnable  = false,                                            // アルファマスクで透過する(するならZバッファ必須)
                    IndependentBlendEnable = false,                                            // 個別設定。false なら BendStateDescription.RenderTarget[0] だけが有効で、[1~7] は無視される。
                };
                BlendStateAdd.RenderTarget[0].IsBlendEnabled        = true;                    // true ならブレンディングが有効。
                BlendStateAdd.RenderTarget[0].RenderTargetWriteMask = ColorWriteMaskFlags.All; // RGBA の書き込みマスク。

                // アルファ値のブレンディング設定 ... 特になし
                BlendStateAdd.RenderTarget[0].SourceAlphaBlend      = BlendOption.One;
                BlendStateAdd.RenderTarget[0].DestinationAlphaBlend = BlendOption.Zero;
                BlendStateAdd.RenderTarget[0].AlphaBlendOperation   = BlendOperation.Add;

                // 色値のブレンディング設定 ... 加算合成
                BlendStateAdd.RenderTarget[0].SourceBlend      = BlendOption.SourceAlpha;
                BlendStateAdd.RenderTarget[0].DestinationBlend = BlendOption.One;
                BlendStateAdd.RenderTarget[0].BlendOperation   = BlendOperation.Add;

                // ブレンドステートを作成する。
                _BlendState加算合成 = new BlendState(d3dDevice1, BlendStateAdd);
            }
            //----------------
            #endregion

            #region " ラスタライザステートを生成する。"
            //----------------
            _RasterizerState = new RasterizerState(d3dDevice1, new RasterizerStateDescription()
            {
                FillMode = FillMode.Solid,       // 普通に描画する
                CullMode = CullMode.None,        // 両面を描画する
                IsFrontCounterClockwise = false, // 時計回りが表面
                DepthBias                = 0,
                DepthBiasClamp           = 0,
                SlopeScaledDepthBias     = 0,
                IsDepthClipEnabled       = true,
                IsScissorEnabled         = false,
                IsMultisampleEnabled     = false,
                IsAntialiasedLineEnabled = false,
            });
            //----------------
            #endregion

            #region " サンプラーステートを生成する。"
            //----------------
            _SamplerState = new SamplerState(d3dDevice1, new SamplerStateDescription()
            {
                Filter             = Filter.Anisotropic,
                AddressU           = TextureAddressMode.Border,
                AddressV           = TextureAddressMode.Border,
                AddressW           = TextureAddressMode.Border,
                MipLodBias         = 0.0f,
                MaximumAnisotropy  = 2,
                ComparisonFunction = Comparison.Never,
                BorderColor        = new RawColor4(0f, 0f, 0f, 0f),
                MinimumLod         = float.MinValue,
                MaximumLod         = float.MaxValue,
            });
            //----------------
            #endregion

            #region " 定数バッファを作成する。"
            //----------------
            _ConstantBuffer = new SharpDX.Direct3D11.Buffer(d3dDevice1, new BufferDescription()
            {
                Usage               = ResourceUsage.Dynamic,                        // 動的使用法
                BindFlags           = BindFlags.ConstantBuffer,                     // 定数バッファ
                CpuAccessFlags      = CpuAccessFlags.Write,                         // CPUから書き込む
                OptionFlags         = ResourceOptionFlags.None,
                SizeInBytes         = SharpDX.Utilities.SizeOf <ST定数バッファの転送元データ>(), // バッファサイズ
                StructureByteStride = 0,
            });
            //----------------
            #endregion
        }