OSDN Git Service

Merge branch 'feature/37178_プロジェクトとソリューションファイルの英語化' into develop
[dtxmania/dtxmania.git] / FDK / コード / 04.グラフィック / CAviDS.cs
diff --git a/FDK/コード/04.グラフィック/CAviDS.cs b/FDK/コード/04.グラフィック/CAviDS.cs
new file mode 100644 (file)
index 0000000..ead2215
--- /dev/null
@@ -0,0 +1,252 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Runtime.InteropServices;
+using DirectShowLib;
+using DirectShowLib.DES;
+using SharpDX;
+
+namespace FDK
+{
+       public class CAviDS : IDisposable
+       {
+               const int timeOutMs = 1000; // グラフ state の遷移完了を待つタイムアウト期間 
+
+               public uint nフレーム高さ
+               {
+                       get
+                       {
+                               return (uint)nHeight;
+                       }
+               }
+
+               public uint nフレーム幅
+               {
+                       get
+                       {
+                               return (uint)nWidth;
+                       }
+               }
+               public bool b再生中
+               {
+                       get
+                       {
+                               return bPlaying;
+                       }
+               }
+               public bool b一時停止中
+               {
+                       get
+                       {
+                               return bPause;
+                       }
+               }
+
+               int nWidth;
+               int nHeight;
+               long nMediaLength; // [ms]
+               bool bPlaying;
+               bool bPause;
+
+               public int GetDuration()
+               {
+                       return (int)(nMediaLength / 10000);
+               }
+
+               IGraphBuilder builder;
+               VideoInfoHeader videoInfo;
+               ISampleGrabber grabber;
+               IMediaControl control;
+               IMediaSeeking seeker;
+               IMediaFilter filter;
+               FilterState state;
+               AMMediaType mediaType;
+               IntPtr samplePtr = IntPtr.Zero;
+               
+               public CAviDS(string filename, double playSpeed)
+               {
+                       int hr = 0x0;
+
+                       builder = (IGraphBuilder)new FilterGraph();
+
+                       #region [Sample Grabber]
+                       {
+                               grabber = new SampleGrabber() as ISampleGrabber;
+                               mediaType = new AMMediaType();
+                               mediaType.majorType = MediaType.Video;
+                               mediaType.subType = MediaSubType.RGB32;
+                               mediaType.formatType = FormatType.VideoInfo;
+                               hr = grabber.SetMediaType(mediaType);
+                               DsError.ThrowExceptionForHR(hr);
+
+                               hr = builder.AddFilter((IBaseFilter)grabber, "Sample Grabber");
+                               DsError.ThrowExceptionForHR(hr);
+                       }
+                       #endregion
+
+                       hr = builder.RenderFile(filename, null);
+                       DsError.ThrowExceptionForHR(hr);
+
+                       // Null レンダラに接続しないとウィンドウが表示される。
+                       // また、レンダリングを行わないため処理速度を向上できる。
+                       CDirectShow.ConnectNullRendererFromSampleGrabber(builder, grabber as IBaseFilter);
+                       CDirectShow.tグラフを解析しデバッグ出力する(builder);
+
+                       IVideoWindow videoWindow = builder as IVideoWindow;
+                       if (videoWindow != null)
+                       {
+                               videoWindow.put_AutoShow(OABool.False);
+                       }
+
+                       #region [Video Info]
+                       {
+                               hr = grabber.GetConnectedMediaType(mediaType);
+                               DsError.ThrowExceptionForHR(hr);
+
+                               videoInfo = (VideoInfoHeader)Marshal.PtrToStructure(mediaType.formatPtr, typeof(VideoInfoHeader));
+                               nWidth = videoInfo.BmiHeader.Width;
+                               nHeight = videoInfo.BmiHeader.Height;
+                       }
+                       #endregion
+
+                       #region[ Seeker ]
+                       {
+                               seeker = builder as IMediaSeeking;
+                               hr = seeker.GetDuration(out nMediaLength);
+                               DsError.ThrowExceptionForHR(hr);
+                               hr = seeker.SetRate(playSpeed / 20);
+                               DsError.ThrowExceptionForHR(hr);
+                       }
+                       #endregion
+
+                       #region [Control]
+                       {
+                               control = builder as IMediaControl;
+                       }
+                       #endregion
+
+                       #region [Filter]
+                       {
+                               filter = builder as IMediaFilter;
+                       }
+                       #endregion
+
+                       grabber.SetBufferSamples(true);
+                       this.Run();
+                       this.Pause();
+
+                       bPlaying = false;
+                       bPause = false;         // 外見えには演奏停止している。PAUSE中として外に見せないこと。
+               }
+
+               public void Seek(int timeInMs)
+               {
+                       int hr = seeker.SetPositions(new DsLong(timeInMs * 10000), AMSeekingSeekingFlags.AbsolutePositioning, null, AMSeekingSeekingFlags.NoPositioning);
+                       DsError.ThrowExceptionForHR(hr);
+                       hr = control.GetState(timeOutMs, out state); // state is Running
+                       DsError.ThrowExceptionForHR(hr);
+               }
+
+               public void Run()
+               {
+                       int hr = control.Run();
+                       DsError.ThrowExceptionForHR(hr);
+                       hr = control.GetState(timeOutMs, out state);
+                       DsError.ThrowExceptionForHR(hr);
+                       bPlaying = true;
+                       bPause = false;
+               }
+
+               public void Stop()
+               {
+                       int hr = control.Stop();
+                       DsError.ThrowExceptionForHR(hr);
+                       hr = control.GetState(timeOutMs, out state);
+                       DsError.ThrowExceptionForHR(hr);
+                       bPlaying = false;
+                       bPause = false;
+               }
+
+               public void Pause()
+               {
+                       int hr = control.Pause();
+                       DsError.ThrowExceptionForHR(hr);
+                       hr = control.GetState(timeOutMs, out state);
+                       DsError.ThrowExceptionForHR(hr);
+                       bPause = true;
+               }
+
+               public void ToggleRun()
+               {
+                       int hr = control.GetState(timeOutMs, out state);
+                       DsError.ThrowExceptionForHR(hr);
+                       if( state == FilterState.Paused )
+                       {
+                               Run();
+                       }
+                       else if( state == FilterState.Running )
+                       {
+                               Pause();
+                       }
+               }
+
+               public unsafe void tGetBitmap(SharpDX.Direct3D9.Device device, CTexture ctex, int timeMs)
+               {
+                       int bufferSize = 0;
+                       int hr = 0x0;
+                       
+                       hr = grabber.GetCurrentBuffer(ref bufferSize, IntPtr.Zero);
+                       DsError.ThrowExceptionForHR(hr);
+
+                       if ( samplePtr == IntPtr.Zero )
+                       {
+                               samplePtr = Marshal.AllocHGlobal(bufferSize);
+                       }
+
+                       DataRectangle rectangle3 = ctex.texture.LockRectangle(0, SharpDX.Direct3D9.LockFlags.None);
+                       hr = grabber.GetCurrentBuffer(ref bufferSize, rectangle3.DataPointer);
+                       DsError.ThrowExceptionForHR(hr);
+                       ctex.texture.UnlockRectangle(0);
+               }
+
+               #region [ Dispose-Finalize パターン実装 ]
+               public void Dispose()
+               {
+                       if (!this.bDisposed)
+                       {
+                               if (null != builder)
+                               {
+                                       Marshal.ReleaseComObject(builder);
+                                       builder = null;
+                               }
+                               if( null != grabber )
+                               {
+                                       Marshal.ReleaseComObject(grabber);
+                                       grabber = null;
+                               }
+                               if (null != mediaType)
+                               {
+                                       DsUtils.FreeAMMediaType(mediaType);
+                                       mediaType = null;
+                               }
+                               if (samplePtr != IntPtr.Zero)
+                               {
+                                       Marshal.FreeHGlobal(samplePtr);
+                               }
+
+                               GC.SuppressFinalize(this);
+                               this.bDisposed = true;
+                       }
+               }
+
+               ~CAviDS()
+               {
+                       this.Dispose();
+               }
+               #endregion
+
+               private bool bDisposed = false;
+       }
+}