--- /dev/null
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+using System.Runtime.InteropServices;\r
+using DirectShowLib;\r
+using DirectShowLib.DES;\r
+using SlimDX;\r
+\r
+namespace FDK\r
+{\r
+ public class CAviDS : IDisposable\r
+ {\r
+ public uint nフレーム高さ\r
+ {\r
+ get\r
+ {\r
+ return (uint)nHeight;\r
+ }\r
+ }\r
+\r
+ public uint nフレーム幅\r
+ {\r
+ get\r
+ {\r
+ return (uint)nWidth;\r
+ }\r
+ }\r
+\r
+ int nWidth;\r
+ int nHeight;\r
+ long mediaLength; // [ms]\r
+ VideoInfoHeader videoInfo;\r
+ const int timeOutMs = 1000;\r
+\r
+ public int GetDuration()\r
+ {\r
+ return (int)(mediaLength / 10000);\r
+ }\r
+\r
+ IGraphBuilder builder;\r
+ ISampleGrabber grabber;\r
+ IMediaControl control;\r
+ IMediaSeeking seeker;\r
+ FilterState state;\r
+ AMMediaType mediaType;\r
+\r
+ public CAviDS(string filename, double playSpeed)\r
+ {\r
+ int hr = 0x0;\r
+\r
+ builder = (IGraphBuilder)new FilterGraphNoThread();\r
+\r
+ #region [Sample Grabber]\r
+ {\r
+ grabber = new SampleGrabber() as ISampleGrabber;\r
+ mediaType = new AMMediaType();\r
+ mediaType.majorType = MediaType.Video;\r
+ mediaType.subType = MediaSubType.RGB24;\r
+ mediaType.formatType = FormatType.VideoInfo;\r
+ hr = grabber.SetMediaType(mediaType);\r
+ DsError.ThrowExceptionForHR(hr);\r
+ hr = builder.AddFilter((IBaseFilter)grabber, "Sample Grabber");\r
+ DsError.ThrowExceptionForHR(hr);\r
+ }\r
+ #endregion\r
+\r
+ hr = builder.RenderFile(filename, "");\r
+ DsError.ThrowExceptionForHR(hr);\r
+\r
+ // Null レンダラに接続しないとウィンドウが表示される。\r
+ // また、レンダリングを行わないため処理速度を向上できる。\r
+ CDirectShow.tビデオレンダラをグラフから除去してNullレンダラに接続する(builder);\r
+\r
+ #region [Video Info]\r
+ {\r
+ hr = grabber.GetConnectedMediaType(mediaType);\r
+ DsError.ThrowExceptionForHR(hr);\r
+\r
+ videoInfo = (VideoInfoHeader)Marshal.PtrToStructure(mediaType.formatPtr, typeof(VideoInfoHeader));\r
+ nWidth = videoInfo.BmiHeader.Width;\r
+ nHeight = videoInfo.BmiHeader.Height;\r
+ }\r
+ #endregion\r
+\r
+ #region[ Seeker ]\r
+ {\r
+ seeker = builder as IMediaSeeking;\r
+ hr = seeker.GetDuration(out mediaLength);\r
+ DsError.ThrowExceptionForHR(hr);\r
+ hr = seeker.SetRate(playSpeed / 20);\r
+ DsError.ThrowExceptionForHR(hr);\r
+ }\r
+ #endregion\r
+\r
+ #region [Control]\r
+ {\r
+ control = builder as IMediaControl;\r
+ }\r
+ #endregion\r
+\r
+ hr = grabber.SetBufferSamples(true);\r
+ DsError.ThrowExceptionForHR(hr);\r
+ }\r
+\r
+ public void Seek(int timeInMs)\r
+ {\r
+ int hr = seeker.SetPositions(new DsLong(timeInMs * 10000), AMSeekingSeekingFlags.AbsolutePositioning, null, AMSeekingSeekingFlags.NoPositioning);\r
+ DsError.ThrowExceptionForHR(hr);\r
+ hr = control.GetState(timeOutMs, out state); // state is Running\r
+ DsError.ThrowExceptionForHR(hr);\r
+ }\r
+\r
+ public void Run()\r
+ {\r
+ int hr = control.Run();\r
+ DsError.ThrowExceptionForHR(hr);\r
+ hr = control.GetState(timeOutMs, out state);\r
+ DsError.ThrowExceptionForHR(hr);\r
+ }\r
+\r
+ public unsafe void tGetBitmap(SlimDX.Direct3D9.Device device, CTexture ctex, int timeMs)\r
+ {\r
+ IntPtr bufferPtr = IntPtr.Zero;\r
+ try\r
+ {\r
+ int bufferSize = 0;\r
+ grabber.GetCurrentBuffer(ref bufferSize, IntPtr.Zero);\r
+\r
+ bufferPtr = Marshal.AllocHGlobal(bufferSize);\r
+ grabber.GetCurrentBuffer(ref bufferSize, bufferPtr);\r
+\r
+ byte* sourcePtr = (byte*)bufferPtr.ToPointer();\r
+ int stride = (nWidth * 3) + ((4 - ((nWidth * 3) % 4)) % 4); // BMP 1行ごとのバイト数 (4の倍数になるように調整)\r
+\r
+ DataRectangle rectangle3 = ctex.texture.LockRectangle(0, SlimDX.Direct3D9.LockFlags.None);\r
+ rectangle3.Data.Seek(0, System.IO.SeekOrigin.Begin);\r
+ uint* outPtr = (uint*)rectangle3.Data.DataPointer.ToPointer();\r
+ for (int i = 0; i < nHeight; ++i)\r
+ {\r
+ for (int j = 0; j < nWidth; ++j)\r
+ {\r
+ // 上下反転しつつコピー\r
+ byte B = *((sourcePtr + (((nHeight - i) - 1) * stride)) + (j * 3) + 0);\r
+ byte G = *((sourcePtr + (((nHeight - i) - 1) * stride)) + (j * 3) + 1);\r
+ byte R = *((sourcePtr + (((nHeight - i) - 1) * stride)) + (j * 3) + 2);\r
+ *(outPtr + (i * nWidth + j)) = ((uint)R << 16) | ((uint)G << 8) | B;\r
+ }\r
+ }\r
+ ctex.texture.UnlockRectangle(0);\r
+ }\r
+ finally\r
+ {\r
+ if (bufferPtr != IntPtr.Zero)\r
+ {\r
+ Marshal.FreeHGlobal(bufferPtr);\r
+ }\r
+ }\r
+ }\r
+\r
+ #region [ Dispose-Finalize パターン実装 ]\r
+ public void Dispose()\r
+ {\r
+ if (!this.bDisposed)\r
+ {\r
+ if (null != builder)\r
+ {\r
+ Marshal.ReleaseComObject(builder);\r
+ builder = null;\r
+ }\r
+ if (null != mediaType)\r
+ {\r
+ DsUtils.FreeAMMediaType(mediaType);\r
+ mediaType = null;\r
+ }\r
+\r
+ GC.SuppressFinalize(this);\r
+ this.bDisposed = true;\r
+ }\r
+ }\r
+\r
+ ~CAviDS()\r
+ {\r
+ this.Dispose();\r
+ }\r
+ #endregion\r
+\r
+ private bool bDisposed = false;\r
+ }\r
+}\r