OSDN Git Service

動画のループ再生できなかった不具合を修正。
authorくまかみ工房 <kumakamikoubou@gmail.com>
Wed, 26 Oct 2016 06:19:59 +0000 (15:19 +0900)
committerくまかみ工房 <kumakamikoubou@gmail.com>
Wed, 26 Oct 2016 06:19:59 +0000 (15:19 +0900)
FDK24/メディア/動画.cs
FDK24/メディア/動画デコーダ.cs

index 1e006e4..cc82e95 100644 (file)
@@ -35,15 +35,12 @@ namespace FDK.メディア
                        {
                                this.動画の生成に成功した = false;
 
-                               #region " デコーダを生成する。"
-                               //----------------
+                               // デコーダを生成する。
                                this.デコーダ = new 動画デコーダ( dr, this.動画ファイルパス, this.ループ再生する, this.キューのサイズ );
                                this.デコーダ.現在の再生時刻100ns = () => {
                                        return this.タイマ.Value.現在のリアルタイムカウント100ns単位;
                                };
                                this.デコーダ.デコードキャッシング();
-                               //----------------
-                               #endregion
 
                                this.動画の生成に成功した = true;
                                Log.Info( $"{Utilities.現在のメソッド名}: 動画を生成しました。[{変数付きファイルパス}]" );
@@ -103,8 +100,9 @@ namespace FDK.メディア
                                        {
                                                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();
index ffa165f..45346fe 100644 (file)
@@ -14,7 +14,7 @@ namespace FDK.メディア
        public class 動画デコーダ : FDK.同期.RWLockAction, IDisposable
        {
                // 外部依存Action。
-               public Func<double> 現在の再生時刻100ns = null;
+               public Func<long> 現在の再生時刻100ns = null;
 
                public SharpDX.Size2 サイズdpx
                {
@@ -33,23 +33,6 @@ namespace FDK.メディア
                                } );
                        }
                }
-               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 キューのサイズ )
                {
@@ -268,6 +251,8 @@ namespace FDK.メディア
                }
                public void デコードを開始する()
                {
+                       this.前フレームの再生時刻100ns = 0;
+                       this.先頭時刻100ns = 0;
                        this.デコードタスク = Task.Factory.StartNew( this.デコードタスクエントリ );
                }
                /// <remarks>
@@ -282,28 +267,29 @@ namespace FDK.メディア
                                再生時刻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
@@ -320,7 +306,8 @@ namespace FDK.メディア
                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 );
@@ -378,7 +365,8 @@ namespace FDK.メディア
                                        {
                                                // (A) ループ再生する場合
                                                FDK.Log.Info( "動画をループ再生します。" );
-                                               this.ループした際の先頭時刻sec = this.前フレームの時刻sec; // EndOfStream フラグがセットされたときは、ReadSample() で返されるサンプル時刻は無効(0 になっている)。
+                                               this.先頭時刻100ns += this.前フレームの再生時刻100ns;
+                                               this.前フレームの再生時刻100ns = 0;
                                                this.SourceReaderEx.SetCurrentPosition( 0 );            // ストリーム再生位置を先頭へ。
                                                return this.サンプルをひとつ取得してキューへ格納する(); // 再帰で先頭サンプルを取得して返す。
                                        }
@@ -418,15 +406,17 @@ namespace FDK.メディア
                                //---------------------------------------------------
                                #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 )
@@ -621,7 +611,6 @@ namespace FDK.メディア
 
                #region " バックストア。"
                //----------------
-               private double bs_ループした際の先頭時刻sec = 0.0;
                private SharpDX.Size2 bs_サイズdpx = new SharpDX.Size2( 1, 1 );
                //----------------
                #endregion