// 再生、停止 /// <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(); }
/// <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; } }
public virtual void Dispose() { using var _ = new LogBlock(Log.現在のメソッド名); this._SoundTimer = null !; }
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(); }
public void Dispose() { using var _ = new LogBlock(Log.現在のメソッド名); }
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 }