videoimage.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. #include "pch.h"
  2. #include "mmstream.h"
  3. #include "amstream.h"
  4. #include "ddstream.h"
  5. //////////////////////////////////////////////////////////////////////////////
  6. //
  7. // VideoImage
  8. //
  9. //////////////////////////////////////////////////////////////////////////////
  10. class VideoImageImpl : public VideoImage {
  11. public:
  12. //////////////////////////////////////////////////////////////////////////////
  13. //
  14. // Data members
  15. //
  16. //////////////////////////////////////////////////////////////////////////////
  17. RectValue* GetRect() { return RectValue::Cast(GetChild(0)); }
  18. TRef<EventSourceImpl> m_peventSource;
  19. TRef<PrivateEngine> m_pengine;
  20. TRef<IAMMultiMediaStream> m_pAMStream;
  21. TRef<IDirectDrawStreamSample> m_psample;
  22. TRef<IDirectDrawSurfaceX> m_pddsSample;
  23. TRef<PrivateSurface> m_psurface;
  24. ZString m_strFile;
  25. bool m_bTriggered;
  26. bool m_bFirstFrame;
  27. bool m_bStarted;
  28. //////////////////////////////////////////////////////////////////////////////
  29. //
  30. // Constructor
  31. //
  32. //////////////////////////////////////////////////////////////////////////////
  33. VideoImageImpl(
  34. PrivateEngine* pengine,
  35. RectValue* prect,
  36. const ZString& str
  37. ) :
  38. VideoImage(prect),
  39. m_pengine(pengine),
  40. m_peventSource(new EventSourceImpl()),
  41. m_strFile(str),
  42. m_bStarted(false),
  43. m_bTriggered(false),
  44. m_bFirstFrame(true)
  45. {
  46. //
  47. // Create the Active Movie Multi Media Stream
  48. //
  49. HRESULT hr = CoCreateInstance(CLSID_AMMultiMediaStream, NULL, CLSCTX_INPROC_SERVER, IID_IAMMultiMediaStream, (void **)&m_pAMStream);
  50. if (FAILED(hr) || m_pAMStream == NULL) {
  51. m_pAMStream = NULL;
  52. return;
  53. }
  54. ZSucceeded(m_pAMStream->Initialize(STREAMTYPE_READ, 0, NULL));
  55. //
  56. // Add renders for sound and video
  57. //
  58. DDDevice* pdddevice = m_pengine->GetPrimaryDevice();
  59. ZSucceeded(m_pAMStream->AddMediaStream(pdddevice->GetDD(), &MSPID_PrimaryVideo, 0, NULL));
  60. //
  61. // Don't check the return value. If this fails there just won't be audio playback.
  62. //
  63. m_pAMStream->AddMediaStream(NULL, &MSPID_PrimaryAudio, AMMSF_ADDDEFAULTRENDERER, NULL);
  64. //
  65. // Open the AVI File
  66. //
  67. WCHAR wPath[MAX_PATH];
  68. MultiByteToWideChar(CP_ACP, 0, m_strFile, -1, wPath, ArrayCount(wPath));
  69. if (FAILED(m_pAMStream->OpenFile(wPath, 0))) {
  70. m_pAMStream = NULL;
  71. }
  72. }
  73. bool IsValid()
  74. {
  75. return m_pAMStream != NULL;
  76. }
  77. //////////////////////////////////////////////////////////////////////////////
  78. //
  79. // Implementation methods
  80. //
  81. //////////////////////////////////////////////////////////////////////////////
  82. void AllocateSample()
  83. {
  84. if (m_pAMStream) {
  85. //
  86. // Create a Direct Draw video steam
  87. //
  88. TRef<IMediaStream> pPrimaryVidStream;
  89. TRef<IDirectDrawMediaStream> pDDStream;
  90. TRef<IDirectDrawSurface> pdds;
  91. ZSucceeded(m_pAMStream->GetMediaStream(MSPID_PrimaryVideo, &pPrimaryVidStream));
  92. ZSucceeded(pPrimaryVidStream->QueryInterface(IID_IDirectDrawMediaStream, (void **)&pDDStream));
  93. //
  94. // Get Information about the stream
  95. //
  96. DDSDescription ddsdCurrent;
  97. DDSDescription ddsdDesired;
  98. IDirectDrawPalette* pddpal;
  99. DWORD flags;
  100. HRESULT hr =
  101. pDDStream->GetFormat(
  102. (DDSURFACEDESC*)&ddsdCurrent,
  103. &pddpal,
  104. (DDSURFACEDESC*)&ddsdDesired,
  105. &flags
  106. );
  107. //
  108. // !!! sometime the size will come back zero, in that case just don't display anything
  109. //
  110. if (
  111. FAILED(hr)
  112. || ddsdDesired.XSize() == 0
  113. || ddsdDesired.YSize() == 0
  114. ) {
  115. End();
  116. return;
  117. }
  118. //
  119. // Create a surface that the video will be rendered to
  120. //
  121. CastTo(
  122. m_psurface,
  123. m_pengine->CreateSurface(
  124. ddsdDesired.Size(),
  125. SurfaceType2D()
  126. )
  127. );
  128. DDSurface* pddsurface; CastTo(pddsurface, m_psurface->GetVideoSurface());
  129. m_pddsSample = pddsurface->GetDDSX();
  130. //
  131. // Create a ddsample from the surface
  132. //
  133. ZSucceeded(pDDStream->CreateSample(
  134. pddsurface->GetDDS(),
  135. NULL,
  136. DDSFF_PROGRESSIVERENDER,
  137. &m_psample
  138. ));
  139. }
  140. }
  141. void Start()
  142. {
  143. //
  144. // Start playback
  145. //
  146. m_bStarted = true;
  147. ZSucceeded(m_pAMStream->SetState(STREAMSTATE_RUN));
  148. }
  149. void End()
  150. {
  151. if (!m_bTriggered) {
  152. m_bTriggered = true;
  153. m_peventSource->Trigger();
  154. }
  155. }
  156. //////////////////////////////////////////////////////////////////////////////
  157. //
  158. // DeviceDependant methods
  159. //
  160. //////////////////////////////////////////////////////////////////////////////
  161. void ClearDevice()
  162. {
  163. //
  164. // no need to free the stream since we always use the primary device
  165. //
  166. // m_pAMStream = NULL;
  167. m_pddsSample = NULL;
  168. m_psample = NULL;
  169. }
  170. //////////////////////////////////////////////////////////////////////////////
  171. //
  172. // VideoImage methods
  173. //
  174. //////////////////////////////////////////////////////////////////////////////
  175. IEventSource* GetEventSource()
  176. {
  177. return m_peventSource;
  178. }
  179. //////////////////////////////////////////////////////////////////////////////
  180. //
  181. // Image methods
  182. //
  183. //////////////////////////////////////////////////////////////////////////////
  184. void CalcBounds()
  185. {
  186. m_bounds.SetRect(GetRect()->GetValue());
  187. }
  188. void Render(Context* pcontextArg)
  189. {
  190. if (m_bFirstFrame) {
  191. m_bFirstFrame = false;
  192. return;
  193. }
  194. if (m_psample == NULL) {
  195. AllocateSample();
  196. }
  197. if (m_psample) {
  198. if (!m_bStarted) {
  199. Start();
  200. }
  201. bool bTrigger = (m_psample->Update(0, NULL, NULL, 0) != S_OK);
  202. PrivateContext* pcontext; CastTo(pcontext, pcontextArg);
  203. WinRect rect = WinRect::Cast(GetRect()->GetValue());
  204. WinPoint size = m_psurface->GetSize();
  205. if (
  206. size.X() <= rect.XSize() / 2
  207. && size.Y() <= rect.YSize() / 2
  208. ) {
  209. //
  210. // Double size sample will fit on screen so double it
  211. //
  212. WinPoint offset = rect.Min() + (rect.Size() - size * 2) / 2;
  213. pcontext->GetSurface()->BitBlt(
  214. WinRect(
  215. offset,
  216. offset + size * 2
  217. ),
  218. m_psurface
  219. );
  220. } else {
  221. //
  222. // Center the sample
  223. //
  224. pcontext->GetSurface()->BitBlt(
  225. rect.Min() + (rect.Size() - size) / 2,
  226. m_psurface
  227. );
  228. }
  229. if (bTrigger) {
  230. End();
  231. }
  232. } else {
  233. End();
  234. }
  235. }
  236. //////////////////////////////////////////////////////////////////////////////
  237. //
  238. // Value members
  239. //
  240. //////////////////////////////////////////////////////////////////////////////
  241. ZString GetFunctionName() { return "VideoImage"; }
  242. };
  243. //////////////////////////////////////////////////////////////////////////////
  244. //
  245. //
  246. //
  247. //////////////////////////////////////////////////////////////////////////////
  248. TRef<VideoImage> CreateVideoImage(
  249. Engine* pengine,
  250. RectValue* prect,
  251. const ZString& str
  252. ) {
  253. PrivateEngine* pprivateEngine; CastTo(pprivateEngine, pengine);
  254. return new VideoImageImpl(pprivateEngine, prect, str);
  255. }