예제 #1
0
        private void _デコードタスクエントリ(object obj引数)
        {
            Log.現在のスレッドに名前をつける("ビデオデコード");


            var 引数 = ((double 再生開始時刻sec, double 再生速度))obj引数;

            double 再生速度      = Math.Max(0.01, Math.Min(10.0, 引数.再生速度));
            double 再生開始時刻sec = Math.Max(0.0, 引数.再生開始時刻sec) / 再生速度;

            long 再生開始時刻100ns = FDKUtilities.換_sec単位から100ns単位へ(再生開始時刻sec);


            #region " 再生開始時刻までシーク(1)。"
            //----------------
            if (0.0 < 再生開始時刻sec)
            {
                if (this.総演奏時間sec <= 再生開始時刻sec)
                {
                    Log.Info($"再生開始時刻が総演奏時間を超えています。タスクを終了します。");
                    return;
                }

                // 再生開始時刻 が 0 なら、これを呼び出さないこと(ガタつきの原因になるため)。
                this._SourceReaderEx.SetCurrentPosition(再生開始時刻100ns);
            }
            //----------------
            #endregion

            // シーク(1)では、SetCurrentPosition() の仕様により、「指定された位置を超えない一番近いキーフレーム」までしか移動できない。
            // なので、残りのシーク(キーフレームから再生開始時刻まで)を、メインループ内で引き続き行う。
            // (残りのシークが終わって、ようやく デコード起動完了通知 がセットされる。)

            bool シーク中である = (0.0 < 再生開始時刻sec);

            if (!シーク中である)
            {
                this._デコード起動完了通知.Set(); // シークはしない
            }
            // メインループ。

            while (true)
            {
                if (this._デコードキャンセル.Token.IsCancellationRequested)
                {
                    Log.Info($"キャンセル通知を受信しました。");
                    break;
                }


                if (!this._サンプルをひとつデコードしてフレームをキューへ格納する(再生速度))
                {
                    break;  // エラーまたは再生終了
                }
                if (シーク中である)
                {
                    #region " 再生開始時刻までシーク(2)。"
                    //----------------
                    var frame = this._FrameQueue.Peek();    // 今格納されたフレームを覗く

                    if (frame.表示時刻100ns >= 再生開始時刻100ns)
                    {
                        // シーク終了;今回のフレームから再生の対象(なのでTakeしない)。
                        シーク中である = false;

                        // シークが終わったので、呼び出し元に起動完了を通知する。
                        this._デコード起動完了通知.Set();
                    }
                    else
                    {
                        // 取り出して、すぐに破棄。
                        frame = this._FrameQueue.Take();
                        frame.Dispose();
                        frame = null;
                    }
                    //----------------
                    #endregion
                }
            }

            Log.Info($"タスクを終了します。");
        }