{
this.動画の生成に成功した = false;
- #region " デコーダを生成する。"
- //----------------
+ // デコーダを生成する。
this.デコーダ = new 動画デコーダ( dr, this.動画ファイルパス, this.ループ再生する, this.キューのサイズ );
this.デコーダ.現在の再生時刻100ns = () => {
return this.タイマ.Value.現在のリアルタイムカウント100ns単位;
};
this.デコーダ.デコードキャッシング();
- //----------------
- #endregion
this.動画の生成に成功した = true;
Log.Info( $"{Utilities.現在のメソッド名}: 動画を生成しました。[{変数付きファイルパス}]" );
{
var dummy = (SharpDX.Direct2D1.Bitmap) null;
var 再生時刻sec = 0.0;
- if( this.デコーダ.次のビットマップの有無を確認する( out dummy, out 再生時刻sec ) &&
- ( this.タイマ.Value.現在のリアルタイムカウント秒単位 >= 再生時刻sec + this.デコーダ.ループした際の先頭時刻sec ) )
+ bool 次がある = this.デコーダ.次のビットマップの有無を確認する( out dummy, out 再生時刻sec );
+ double 現在時刻sec = this.タイマ.Value.現在のリアルタイムカウント秒単位;
+ if( 次がある && ( 現在時刻sec >= 再生時刻sec ) )
{
// (C-a) 確認できて、かつ再生時刻になった場合 → サンプルをD2Dビットマップに転写し、描画する。
this.前回表示したD2Dビットマップ?.Dispose();
public class 動画デコーダ : FDK.同期.RWLockAction, IDisposable
{
// 外部依存Action。
- public Func<double> 現在の再生時刻100ns = null;
+ public Func<long> 現在の再生時刻100ns = null;
public SharpDX.Size2 サイズdpx
{
} );
}
}
- public double ループした際の先頭時刻sec
- {
- get
- {
- double sec = 0.0;
- this.ReadLock( () => {
- sec = this.bs_ループした際の先頭時刻sec;
- } );
- return sec;
- }
- set
- {
- this.WriteLock( () => {
- this.bs_ループした際の先頭時刻sec = value;
- } );
- }
- }
public 動画デコーダ( デバイスリソース dr, string 動画ファイルパス, bool ループ再生する, int キューのサイズ )
{
}
public void デコードを開始する()
{
+ this.前フレームの再生時刻100ns = 0;
+ this.先頭時刻100ns = 0;
this.デコードタスク = Task.Factory.StartNew( this.デコードタスクエントリ );
}
/// <remarks>
再生時刻sec = 0.0;
return false; // キューが空だったか、Dequeue が一歩遅かった?(ないはずだが
}
-
- D2Dビットマップ = item.D2Dビットマップ; // キューから出しても、代入しても、COMの参照カウントは変化しない。
- 再生時刻sec = item.再生時刻sec;
-
- this.前フレームの時刻sec = item.再生時刻sec;
- this.キューが空いた.Set(); // キューが空いたので、このイベントを set する。
-
- return true;
+ else
+ {
+ D2Dビットマップ = item.D2Dビットマップ; // キューから出しても、代入しても、COMの参照カウントは変化しない。
+ 再生時刻sec = item.再生時刻sec;
+ this.キューが空いた.Set(); // キューが空いたので、このイベントを set する。
+ return true;
+ }
}
public bool 次のビットマップの有無を確認する( out SharpDX.Direct2D1.Bitmap D2Dビットマップ, out double 再生時刻sec )
{
QueueItem item = null;
- if( ( 0 == this.SampleQueue.Count ) || ( false == this.SampleQueue.TryPeek( out item ) ) ) // キューから取り出さない。
+ if( ( 0 == this.SampleQueue.Count ) || ( false == this.SampleQueue.TryPeek( out item ) ) ) // キューから取り出さない。
{
D2Dビットマップ = null;
再生時刻sec = 0.0;
return false; // キューが空だったか、Peek が一歩遅かった?(ないはずだが
}
-
- D2Dビットマップ = item.D2Dビットマップ; // 代入しても、COMの参照カウントは変化しない。
- 再生時刻sec = item.再生時刻sec;
- return true;
+ else
+ {
+ D2Dビットマップ = item.D2Dビットマップ; // 代入しても、COMの参照カウントは変化しない。
+ 再生時刻sec = item.再生時刻sec;
+ return true;
+ }
}
protected class QueueItem : IDisposable
protected SharpDX.MediaFoundation.SourceReaderEx SourceReaderEx;
protected SharpDX.MediaFoundation.MediaType MediaType;
protected bool ループ再生する = false;
- protected double 前フレームの時刻sec = -1.0;
+ protected long 先頭時刻100ns = 0;
+ protected long 前フレームの再生時刻100ns = 0;
protected System.Threading.Tasks.Task デコードタスク = null;
protected ManualResetEvent キューが空いた = new ManualResetEvent( true );
protected AutoResetEvent タスクを終了せよ = new AutoResetEvent( false );
{
// (A) ループ再生する場合
FDK.Log.Info( "動画をループ再生します。" );
- this.ループした際の先頭時刻sec = this.前フレームの時刻sec; // EndOfStream フラグがセットされたときは、ReadSample() で返されるサンプル時刻は無効(0 になっている)。
+ this.先頭時刻100ns += this.前フレームの再生時刻100ns;
+ this.前フレームの再生時刻100ns = 0;
this.SourceReaderEx.SetCurrentPosition( 0 ); // ストリーム再生位置を先頭へ。
return this.サンプルをひとつ取得してキューへ格納する(); // 再帰で先頭サンプルを取得して返す。
}
//---------------------------------------------------
#endregion
- if( this.現在の再生時刻100ns() < 再生時刻100ns ) // 現時点でもう再生時刻を超えてるなら、スキップする。
+ if( this.現在の再生時刻100ns() < (this.先頭時刻100ns + 再生時刻100ns) ) // 現時点でもう再生時刻を超えてるなら、スキップする。
{
this.サンプルをD2Dビットマップに転送する( sample, out bitmap );
// ビットマップをキューへ格納する。
this.SampleQueue.Enqueue( new QueueItem() {
D2Dビットマップ = bitmap, // COM参照カウントは変化しない。
- 再生時刻sec = (double) ( 再生時刻100ns / ( 10.0 * 1000.0 * 1000.0 ) ), // 100ns単位 → 秒単位へ変換。
+ 再生時刻sec = (double) ( ( this.先頭時刻100ns + 再生時刻100ns ) / ( 10.0 * 1000.0 * 1000.0 ) ), // 100ns単位 → 秒単位へ変換。
} );
+
+ this.前フレームの再生時刻100ns = 再生時刻100ns;
}
}
catch( Exception e )
#region " バックストア。"
//----------------
- private double bs_ループした際の先頭時刻sec = 0.0;
private SharpDX.Size2 bs_サイズdpx = new SharpDX.Size2( 1, 1 );
//----------------
#endregion