OSDN Git Service

#XXXXX 動画再生開始時のカクツキ軽減
[dtxmania/dtxmania.git] / DTXMania / コード / ステージ / 07.演奏 / CAct演奏AVI.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using System.Drawing;
5 using SharpDX;
6 using SharpDX.Direct3D9;
7 using FDK;
8 using System.Diagnostics;
9 using System.Threading.Tasks;
10
11 namespace DTXMania
12 {
13         internal class CAct演奏AVI : CActivity
14         {
15                 private long n移動開始時刻ms;
16                 private int n画像側開始位置X;
17                 private int n画像側開始位置Y;
18                 private int n画像側終了位置X;
19                 private int n画像側終了位置Y;
20                 private int n開始サイズH;
21                 private int n開始サイズW;
22                 private int n終了サイズH;
23                 private int n終了サイズW;
24                 private int n総移動時間ms;
25                 private int n表示側開始位置X;
26                 private int n表示側開始位置Y;
27                 private int n表示側終了位置X;
28                 private int n表示側終了位置Y;
29                 private CDTX.CAVI rAVI;
30                 private CTexture tx描画用;
31
32                 /// <summary>
33                 /// プレビュームービーかどうか
34                 /// </summary>
35                 /// <remarks>
36                 /// On活性化()の前にフラグ操作すること。(活性化中に、本フラグを見て動作を変える部分があるため)
37                 /// </remarks>
38                 public bool bIsPreviewMovie
39                 {
40                         get; set;
41                 }
42                 //public bool bIsPreviewMovie
43                 //{
44                 //      get
45                 //      {
46                 //              return _bIsPreviewMovie;
47                 //      }
48                 //      set
49                 //      {
50                 //              _bIsPreviewMovie = value;
51                 //              //if (value == true)
52                 //              //{
53                 //              //      this.bFullScreenMovieCentering = true;
54                 //              //}
55                 //      }
56                 //}
57                 //private bool _bIsPreviewMovie;
58
59
60                 public bool bHasBGA
61                 {
62                         get;
63                         set;
64                 }
65                 /// <summary>
66                 /// AVIをウインドウ全体に表示するかどうか
67                 /// </summary>
68                 public bool bFullScreenMovie
69                 {
70                         get;
71                         set;
72                 }
73                 /// <summary>
74                 /// ウインドウ全体で再生するAVIを、センタリング表示するかどうか
75                 /// </summary>
76                 //public bool bFullScreenMovieCentering
77                 //{
78                 //      get;
79                 //      set;
80                 //}
81
82                 public int X
83                 {
84                         get; set;
85                 }
86                 public int Y
87                 {
88                         get; set;
89                 }
90                 public int Width
91                 {
92                         get; set;
93                 }
94                 public int Height
95                 {
96                         get; set;
97                 }
98                 ///// <summary>
99                 ///// ウインドウ全体で再生するAVIを、センタリング表示しない場合の、表示X座標
100                 ///// </summary>
101                 //public int nFullScreenMovieX
102                 //{
103                 //      get;
104                 //      set;
105                 //}
106                 ///// <summary>
107                 ///// ウインドウ全体で再生するAVIを、センタリング表示しない場合の、表示Y座標
108                 ///// </summary>
109                 //public int nFullScreenMovieY
110                 //{
111                 //      get;
112                 //      set;
113                 //}
114
115
116                 public void PrepareProperSizeTexture(int width, int height)
117                 {
118                         try
119                         {
120                                 if (this.tx描画用 != null && (this.tx描画用.szテクスチャサイズ.Width != width || this.tx描画用.szテクスチャサイズ.Height != height))
121                                 {
122                                         this.tx描画用.Dispose();
123                                         this.tx描画用 = null;
124                                 }
125                                 if (this.tx描画用 == null)
126                                 {
127 #if TEST_Direct3D9Ex
128                                         if ( width % 32 != 0 )
129                                         {
130                                                 width /= 32;
131                                                 width++;
132                                                 width *= 32;
133                                         }
134                                         this.tx描画用 = new CTexture(
135                                                 CDTXMania.Instance.Device, width, height,
136                                                 CDTXMania.Instance.GraphicsDeviceManager.CurrentSettings.BackBufferFormat,
137                                                 Pool.Default, Usage.Dynamic );
138 #else
139                                         this.tx描画用 = new CTexture(
140                                                 CDTXMania.Instance.Device, width, height,
141                                                 CDTXMania.Instance.GraphicsDeviceManager.CurrentSettings.BackBufferFormat,
142                                                 Pool.Managed);
143 #endif
144                                 }
145                         }
146                         catch (CTextureCreateFailedException e)
147                         {
148                                 Trace.TraceError("CActAVI: OnManagedリソースの作成(): " + e.Message);
149                                 this.tx描画用 = null;
150                         }
151                 }
152
153
154                 public void Start(EChannel nチャンネル番号, CDTX.CAVI rAVI, int n開始サイズW, int n開始サイズH, int n終了サイズW, int n終了サイズH, int n画像側開始位置X, int n画像側開始位置Y, int n画像側終了位置X, int n画像側終了位置Y, int n表示側開始位置X, int n表示側開始位置Y, int n表示側終了位置X, int n表示側終了位置Y, int n総移動時間ms, int n移動開始時刻ms, bool bPlayFromBeginning = false)
155                 {
156                         if (nチャンネル番号 == EChannel.Movie || nチャンネル番号 == EChannel.MovieFull)
157                         {
158                                 this.rAVI = rAVI;
159                                 this.n開始サイズW = n開始サイズW;
160                                 this.n開始サイズH = n開始サイズH;
161                                 this.n終了サイズW = n終了サイズW;
162                                 this.n終了サイズH = n終了サイズH;
163                                 this.n画像側開始位置X = n画像側開始位置X;
164                                 this.n画像側開始位置Y = n画像側開始位置Y;
165                                 this.n画像側終了位置X = n画像側終了位置X;
166                                 this.n画像側終了位置Y = n画像側終了位置Y;
167                                 this.n表示側開始位置X = n表示側開始位置X * 2;
168                                 this.n表示側開始位置Y = n表示側開始位置Y * 2;
169                                 this.n表示側終了位置X = n表示側終了位置X * 2;
170                                 this.n表示側終了位置Y = n表示側終了位置Y * 2;
171                                 this.n総移動時間ms = n総移動時間ms;
172                                 this.PrepareProperSizeTexture((int)this.rAVI.avi.nフレーム幅, (int)this.rAVI.avi.nフレーム高さ);
173                                 this.n移動開始時刻ms = (n移動開始時刻ms != -1) ? n移動開始時刻ms : CSound管理.rc演奏用タイマ.n現在時刻;
174                                 Task.Run(() =>                                  // 再生開始時のカクツキ回避
175                                 {
176                                         if (bPlayFromBeginning)     // DTXCで途中から再生した後、最初から再生すると、動画が最初から再生されず最初の途中再生の続きから再生されてしまう問題の修正
177                                         {
178                                                 this.rAVI.avi.Seek(0);
179                                         }
180                                         this.rAVI.avi.Run();
181                                 });
182                         }
183                 }
184                 public void SkipStart(int n移動開始時刻ms)
185                 {
186 Trace.TraceInformation("Try to seek...{0}", n移動開始時刻ms);
187                         foreach (CChip chip in CDTXMania.Instance.DTX.listChip)
188                         {
189                                 if (chip.n発声時刻ms > n移動開始時刻ms)
190                                 {
191                                         break;
192                                 }
193                                 switch (chip.eAVI種別)
194                                 {
195                                         case EAVIType.AVI:
196                                                 {
197                                                         if (chip.rAVI != null)
198                                                         {
199                                                                 if (this.rAVI == null)
200                                                                 {
201                                                                         this.rAVI = chip.rAVI;    // DTXVモードで、最初に途中再生で起動したときに、ここに来る
202                                                                 }
203                                                                 {
204                                                                         this.bFullScreenMovie = (chip.eチャンネル番号 == EChannel.MovieFull);   // DTXVモードで、最初に途中再生で起動したときのために必要
205                                                                         SetXYWH();
206                                                                 }
207                                                                 this.rAVI.avi.Seek(n移動開始時刻ms - chip.n発声時刻ms);
208 Trace.TraceInformation("Seeked1: abs={0}, rel={1}", n移動開始時刻ms, n移動開始時刻ms - chip.n発声時刻ms);
209                                                                 //this.Start( chip.eチャンネル番号, chip.rAVI, SampleFramework.GameWindowSize.Width, SampleFramework.GameWindowSize.Height, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, chip.n発声時刻ms );
210                                                                 this.Start( chip.eチャンネル番号, chip.rAVI, (int)chip.rAVI.avi.nフレーム幅, (int)chip.rAVI.avi.nフレーム高さ, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, chip.n発声時刻ms );
211                                                         }
212                                                         continue;
213                                                 }
214                                         case EAVIType.AVIPAN:
215                                                 {
216                                                         if (chip.rAVIPan != null)
217                                                         {
218                                                                 if (this.rAVI == null)
219                                                                 {
220                                                                         this.rAVI = chip.rAVI;    // DTXVモードで、最初に途中再生で起動したときに、ここに来る
221                                                                 }
222                                                                 {
223                                                                         this.bFullScreenMovie = (chip.eチャンネル番号 == EChannel.MovieFull);  // DTXVモードで、最初に途中再生で起動したときのために必要
224                                                                         SetXYWH();
225                                                                 }
226                                                                 this.rAVI.avi.Seek(n移動開始時刻ms - chip.n発声時刻ms);
227 Trace.TraceInformation("Seeked2: abs={0}, rel={1}", n移動開始時刻ms, n移動開始時刻ms - chip.n発声時刻ms);
228                                                                 this.Start(chip.eチャンネル番号, chip.rAVI, chip.rAVIPan.sz開始サイズ.Width, chip.rAVIPan.sz開始サイズ.Height, chip.rAVIPan.sz終了サイズ.Width, chip.rAVIPan.sz終了サイズ.Height, chip.rAVIPan.pt動画側開始位置.X, chip.rAVIPan.pt動画側開始位置.Y, chip.rAVIPan.pt動画側終了位置.X, chip.rAVIPan.pt動画側終了位置.Y, chip.rAVIPan.pt表示側開始位置.X, chip.rAVIPan.pt表示側開始位置.Y, chip.rAVIPan.pt表示側終了位置.X, chip.rAVIPan.pt表示側終了位置.Y, chip.n総移動時間, chip.n発声時刻ms);
229                                                         }
230                                                         continue;
231                                                 }
232                                 }
233                         }
234                 }
235                 public void Stop()
236                 {
237                         if ((this.rAVI != null) && (this.rAVI.avi != null))
238                         {
239                                 this.n移動開始時刻ms = -1;
240                         }
241                 }
242
243                 public void Cont(int n再開時刻ms)
244                 {
245                         if ((this.rAVI != null) && (this.rAVI.avi != null))
246                         {
247                                 this.n移動開始時刻ms = n再開時刻ms;
248                         }
249                 }
250
251                 /// <summary>
252                 /// 動画描画領域の設定
253                 /// </summary>
254                 public void SetXYWH()
255                 {
256                         if (bFullScreenMovie)                                                                           // 新movie(Fullscreen movie)の場合
257                         {
258                                 X = 0;
259                                 Y = 0;
260                                 Width = SampleFramework.GameWindowSize.Width;
261                                 Height = SampleFramework.GameWindowSize.Height;
262 //Trace.TraceInformation("MovieFull:{0},{1},{2},{3}", this.actAVI.X, this.actAVI.Y, this.actAVI.Width, this.actAVI.Height);
263                         }
264                         else if (CDTXMania.Instance.ConfigIni.bForceScalingAVI)         // 旧AVIを拡大表示する場合
265                         {
266                                 X = CDTXMania.Instance.ConfigIni.cdForceScaledMovieX[CDTXMania.Instance.ConfigIni.eActiveInst];
267                                 Y = CDTXMania.Instance.ConfigIni.cdForceScaledMovieY[CDTXMania.Instance.ConfigIni.eActiveInst];
268                                 Width = CDTXMania.Instance.ConfigIni.cdForceScaledMovieW[CDTXMania.Instance.ConfigIni.eActiveInst];
269                                 Height = CDTXMania.Instance.ConfigIni.cdForceScaledMovieH[CDTXMania.Instance.ConfigIni.eActiveInst];
270 //Trace.TraceInformation("ScaledAVI:{0},{1},{2},{3}", this.actAVI.X, this.actAVI.Y, this.actAVI.Width, this.actAVI.Height);
271                         }
272                         else                                                        // 旧AVIをそのまま表示する場合
273                         {
274                                 X = CDTXMania.Instance.ConfigIni.cdLegacyAVIX[CDTXMania.Instance.ConfigIni.eActiveInst];
275                                 Y = CDTXMania.Instance.ConfigIni.cdLegacyAVIY[CDTXMania.Instance.ConfigIni.eActiveInst];
276                                 Width = CDTXMania.Instance.Coordinates.Movie.W;
277                                 Height = CDTXMania.Instance.Coordinates.Movie.H;
278 //Trace.TraceInformation("NormalAVI:{0},{1},{2},{3}", this.actAVI.X, this.actAVI.Y, this.actAVI.Width, this.actAVI.Height);
279                         }
280                 }
281
282
283
284                 /// <summary>
285                 /// この関数は AVI 再生のために使用できません。かわりに座標と大きさ指定可能な描画関数を使用してください。
286                 /// </summary>
287                 /// <returns></returns>
288                 public override int On進行描画()
289                 {
290                         return 0;
291                 }
292
293                 public int t進行描画(int x, int y, int w, int h)
294                 {
295                         this.X = x;
296                         this.Y = y;
297                         this.Width = w;
298                         this.Height = h;
299                         return t進行描画();
300                 }
301                 public int t進行描画()
302                 {
303                         int x = X, y = Y, w = Width, h = Height;
304
305                         if (b活性化してる &&
306                                 CDTXMania.Instance.ConfigIni.bAVI &&
307                                 !CDTXMania.Instance.ConfigIni.bStoicMode)
308                         {
309                                 if (((this.n移動開始時刻ms == -1) || (this.rAVI == null)) || (this.rAVI.avi == null))
310                                 {
311                                         return 0;
312                                 }
313                                 if (this.tx描画用 == null)
314                                 {
315                                         return 0;
316                                 }
317                                 int time = (int)((CSound管理.rc演奏用タイマ.n現在時刻 - this.n移動開始時刻ms) * (((double)CDTXMania.Instance.ConfigIni.nPlaySpeed) / 20.0));
318                                 if ((this.n総移動時間ms != 0) && (this.n総移動時間ms < time))
319                                 {
320                                         this.n総移動時間ms = 0;
321                                         this.n移動開始時刻ms = -1;
322                                         return 0;
323                                 }
324                                 if ((this.n総移動時間ms == 0) && time >= this.rAVI.avi.GetDuration())
325                                 {
326                                         if (!bIsPreviewMovie)
327                                         {
328                                                 this.n移動開始時刻ms = -1;
329                                                 return 0;
330                                         }
331                                         // PREVIEW時はループ再生する。移動開始時刻msを現時刻にして(=AVIを最初に巻き戻して)、ここまでに行った計算をやり直す。
332                                         this.n移動開始時刻ms = CSound管理.rc演奏用タイマ.n現在時刻;
333                                         time = (int)((CSound管理.rc演奏用タイマ.n現在時刻 - this.n移動開始時刻ms) * (((double)CDTXMania.Instance.ConfigIni.nPlaySpeed) / 20.0));
334                                         this.rAVI.avi.Seek(0);
335                                 }
336
337                                 if ((this.tx描画用 != null) && (this.n総移動時間ms != -1))
338                                 {
339                                         this.rAVI.avi.tGetBitmap(CDTXMania.Instance.Device, this.tx描画用, time);
340                                         // 旧動画 (278x355以下)の場合と、それ以上の場合とで、拡大/表示位置補正ロジックを変えること。
341                                         // 旧動画の場合は、「278x355の領域に表示される」ことを踏まえて扱う必要あり。
342                                         // 例: 上半分だけ動画表示するような場合は・・・「上半分だけ」という表示意図を維持すべきか?それとも無視して全画面拡大すべきか??
343                                         // chnmr0 : プレビューの場合表示領域いっぱいにアス比保持で拡縮します。
344                                         //          プレビューでない場合単純に縦横2倍、位置変更なしで表示します。
345                                         // yyagi: BGAの有無を見ないで、単純にFullScreenMovieならアス比保持で拡縮、そうでないなら縦横2倍+位置変更なし。
346                                         // chnmr0 : 従来の大きさ以上のプレビュー動画で不都合が起きますのでここは常にアス比保持でフィッティングします。
347
348                                         int xx = x, yy = y;
349                                         float magX = 2, magY = 2;
350                                         if ( CDTXMania.Instance.DTX != null && CDTXMania.Instance.DTX.bUse556x710BGAAVI )
351                                         {
352                                                 magX = magY = 1;
353                                         }
354
355                                         //if (bFullScreenMovie || bIsPreviewMovie)      // #37227 2017.5.29 yyagi: 動画表示の拡縮を、右横ウインドウ表示での動画再生にも適用
356                                         {
357                                                 CPreviewMagnifier.EPreviewType e = CPreviewMagnifier.EPreviewType.PlayingFrontScalable;
358                                                 if ( bFullScreenMovie ) e = CPreviewMagnifier.EPreviewType.PlayingBackground;
359                                                 if ( bIsPreviewMovie )  e = CPreviewMagnifier.EPreviewType.MusicSelect;
360
361 //Trace.TraceInformation("InMovie1:{0},{1},{2},{3} Type={4}", x, y, w, h, e);
362
363                                                 CPreviewMagnifier cmg = new CPreviewMagnifier( e, xx, yy, w, h );
364                                                 cmg.GetMagnifier(
365                                                         (int) this.rAVI.avi.nフレーム幅,
366                                                         (int) this.rAVI.avi.nフレーム高さ,
367                                                         1.0f,
368                                                         1.0f
369                                                 );
370                                                 magX = cmg.magX;
371                                                 magY = cmg.magY;
372                                                 //if (bFullScreenMovieCentering)
373                                                 {
374                                                         xx = cmg.px;
375                                                         yy = cmg.py;
376                                                 }
377                                                 ////else if (bFullScreenMovie)
378                                                 ////{
379                                                 ////    xx = nFullScreenMovieX;
380                                                 ////    yy = nFullScreenMovieY;
381                                                 ////}
382                                                 // fullscreenでないときはxx=x, yy=yだが、xx,yyの初期値がx,yのためここでわざわざ記載する必要なし
383                                                 //else
384                                                 //{
385                                                 //      xx = x;
386                                                 //      yy = y;
387                                                 //}
388 //Trace.TraceInformation("InMovie2:{0},{1},{2},{3}: {4}, {5}", xx, yy, w*magX, w*magY, magX, magY);
389                                         }
390
391                                         this.tx描画用.vc拡大縮小倍率.X = magX;
392                                         this.tx描画用.vc拡大縮小倍率.Y = magY;
393                                         this.tx描画用.vc拡大縮小倍率.Z = 1.0f;
394                                         this.tx描画用.bFlipY = true;
395                                         this.tx描画用.t2D描画(CDTXMania.Instance.Device, xx, yy);
396                                 }
397                         }
398                         return 0;
399                 }
400
401                 public override void On活性化()
402                 {
403                         if (b活性化してない)
404                         {
405                                 this.rAVI = null;
406                                 this.n移動開始時刻ms = -1;
407                                 this.bHasBGA = false;
408                                 //this.bFullScreenMovie = false;
409                                 base.On活性化();
410                         }
411                 }
412
413                 public override void OnManagedリソースの作成()
414                 {
415                         if (b活性化してる)
416                         {
417 #if TEST_Direct3D9Ex
418                                 this.PrepareProperSizeTexture(
419                                                 ( bIsPreviewMovie ) ? 204 : SampleFramework.GameWindowSize.Width,
420                                                 ( bIsPreviewMovie ) ? 269 : SampleFramework.GameWindowSize.Height
421                                                 );
422 #else
423                                 this.PrepareProperSizeTexture(
424                                                 (bIsPreviewMovie) ? 204 : SampleFramework.GameWindowSize.Width,
425                                                 (bIsPreviewMovie) ? 269 : SampleFramework.GameWindowSize.Height
426                                                 );
427 #endif
428                                 this.tx描画用.vc拡大縮小倍率 = new Vector3(Scale.X, Scale.Y, 1f);
429                                 base.OnManagedリソースの作成();
430                         }
431                 }
432                 public override void OnManagedリソースの解放()
433                 {
434                         if (b活性化してる)
435                         {
436                                 if (this.tx描画用 != null)
437                                 {
438                                         this.tx描画用.Dispose();
439                                         this.tx描画用 = null;
440                                 }
441                                 base.OnManagedリソースの解放();
442                         }
443                 }
444         }
445 }