OSDN Git Service

#34198 DirectShow による動画の再生を行うクラス CAviDS を追加し、これを利用するように変更した。
[dtxmania/dtxmania.git] / FDK17プロジェクト / コード / 04.グラフィック / CAviDS.cs
1 using System;\r
2 using System.Collections.Generic;\r
3 using System.Linq;\r
4 using System.Text;\r
5 using System.Threading.Tasks;\r
6 using System.Runtime.InteropServices;\r
7 using DirectShowLib;\r
8 using DirectShowLib.DES;\r
9 using SlimDX;\r
10 \r
11 namespace FDK\r
12 {\r
13         public class CAviDS : IDisposable\r
14         {\r
15                 public uint nフレーム高さ\r
16                 {\r
17                         get\r
18                         {\r
19                                 return (uint)nHeight;\r
20                         }\r
21                 }\r
22 \r
23                 public uint nフレーム幅\r
24                 {\r
25                         get\r
26                         {\r
27                                 return (uint)nWidth;\r
28                         }\r
29                 }\r
30 \r
31                 IMediaDet mediaDet;\r
32                 int nWidth;\r
33                 int nHeight;\r
34                 double mediaLength; // in second\r
35                 VideoInfoHeader videoInfo;\r
36                 IntPtr bufferPtr;\r
37 \r
38                 public int GetDuration()\r
39                 {\r
40                         return (int)(1000 * mediaLength);\r
41                 }\r
42 \r
43                 // コンストラクタ\r
44                 public CAviDS(string filename)\r
45                 {\r
46                         // DirectShow による AVI 再生\r
47                         mediaDet = (IMediaDet)new MediaDet();\r
48                         AMMediaType mediaType = null;\r
49                         bufferPtr = IntPtr.Zero;\r
50 \r
51                         try\r
52                         {\r
53                                 int nStreams;\r
54                                 Guid type = Guid.Empty;\r
55 \r
56                                 mediaType = new AMMediaType();\r
57 \r
58                                 // Set media filename\r
59                                 mediaDet.put_Filename(filename);\r
60 \r
61                                 // Get the number of streams in that media\r
62                                 mediaDet.get_OutputStreams(out nStreams);\r
63                                 for (int nIndexStream = 0; nIndexStream < nStreams; ++nIndexStream)\r
64                                 {\r
65                                         mediaDet.put_CurrentStream(nIndexStream);\r
66                                         mediaDet.get_StreamType(out type);\r
67                                         if (type == MediaType.Video)\r
68                                         {\r
69                                                 // This stream is video\r
70                                                 break;\r
71                                         }\r
72                                 }\r
73 \r
74                                 if (type == MediaType.Video)\r
75                                 {\r
76                                         // Get video info ( width, height, media length (in second)\r
77                                         mediaDet.get_StreamMediaType(mediaType);\r
78                                         videoInfo = (VideoInfoHeader)Marshal.PtrToStructure(mediaType.formatPtr, typeof(VideoInfoHeader));\r
79                                         DsUtils.FreeAMMediaType(mediaType);\r
80                                         mediaType = null;\r
81 \r
82                                         nWidth = videoInfo.BmiHeader.Width;\r
83                                         nHeight = videoInfo.BmiHeader.Height;\r
84                                         mediaDet.get_StreamLength(out mediaLength);\r
85 \r
86                                         // あらかじめテクスチャ用のメモリを確保\r
87                                         int bufferSize;\r
88                                         mediaDet.GetBitmapBits(1, out bufferSize, IntPtr.Zero, nWidth, nHeight);\r
89                                         bufferPtr = Marshal.AllocHGlobal(bufferSize);\r
90                                 }\r
91                         }\r
92                         catch (Exception e)\r
93                         {\r
94                                 if (mediaType != null)\r
95                                 {\r
96                                         // free unmanaged resource if the exception is occured while obtaining videoinfo\r
97                                         DsUtils.FreeAMMediaType(mediaType);\r
98                                 }\r
99                                 throw new ArgumentException(String.Format("ファイルを正常に開けませんでした。\"{0}\", DirectShow による例外メッセージ: {1}", filename, e.Message));\r
100                         }\r
101                 }\r
102 \r
103                 public unsafe void tGetBitmap(SlimDX.Direct3D9.Device device, CTexture ctex, int timeInMs)\r
104                 {\r
105                         int bufferSize;\r
106                         mediaDet.GetBitmapBits(timeInMs / 1000f, out bufferSize, IntPtr.Zero, nWidth, nHeight);\r
107                         // データは R8G8B8\r
108                         mediaDet.GetBitmapBits(timeInMs / 1000f, out bufferSize, bufferPtr, nWidth, nHeight);\r
109                         byte* sourcePtr = (byte*)bufferPtr.ToPointer() + Marshal.SizeOf(videoInfo.BmiHeader);\r
110                         int nBmpLineByte = (nWidth * 3) + ((4 - ((nWidth * 3) % 4)) % 4);\r
111 \r
112                         DataRectangle rectangle3 = ctex.texture.LockRectangle(0, SlimDX.Direct3D9.LockFlags.None);\r
113                         rectangle3.Data.Seek(0, System.IO.SeekOrigin.Begin);\r
114                         uint* outPtr = (uint*)rectangle3.Data.DataPointer.ToPointer();\r
115                         for (int i = 0; i < nHeight; ++i)\r
116                         {\r
117                                 for (int j = 0; j < nWidth; ++j)\r
118                                 {\r
119                                         byte B = *((sourcePtr + (((nHeight - i) - 1) * nBmpLineByte)) + (j * 3) + 0);\r
120                                         byte G = *((sourcePtr + (((nHeight - i) - 1) * nBmpLineByte)) + (j * 3) + 1);\r
121                                         byte R = *((sourcePtr + (((nHeight - i) - 1) * nBmpLineByte)) + (j * 3) + 2);\r
122                                         *(outPtr + (i * nWidth + j)) = ((uint)R << 16) | ((uint)G << 8) | B;\r
123                                 }\r
124                         }\r
125                         ctex.texture.UnlockRectangle(0);\r
126                 }\r
127 \r
128                 #region [ Dispose-Finalize パターン実装 ]\r
129                 //-----------------\r
130                 public void Dispose()\r
131                 {\r
132                         if (!this.bDisposed)\r
133                         {\r
134                                 if (bufferPtr != IntPtr.Zero)\r
135                                 {\r
136                                         Marshal.FreeHGlobal(bufferPtr);\r
137                                         bufferPtr = IntPtr.Zero;\r
138                                 }\r
139                                 GC.SuppressFinalize(this);    // 2011.8.19 from: 忘れてた。\r
140                                 this.bDisposed = true;\r
141                         }\r
142                 }\r
143 \r
144                 ~CAviDS()\r
145                 {\r
146                         this.Dispose();\r
147                 }\r
148                 //-----------------\r
149                 #endregion\r
150 \r
151                 private bool bDisposed = false;\r
152         }\r
153 }\r