123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- #include "pch.h"
- #include "mmstream.h"
- #include "amstream.h"
- #include "ddstream.h"
- //////////////////////////////////////////////////////////////////////////////
- //
- // VideoImage
- //
- //////////////////////////////////////////////////////////////////////////////
- class VideoImageImpl : public VideoImage {
- public:
- //////////////////////////////////////////////////////////////////////////////
- //
- // Data members
- //
- //////////////////////////////////////////////////////////////////////////////
- RectValue* GetRect() { return RectValue::Cast(GetChild(0)); }
- TRef<EventSourceImpl> m_peventSource;
- TRef<PrivateEngine> m_pengine;
- TRef<IAMMultiMediaStream> m_pAMStream;
- TRef<IDirectDrawStreamSample> m_psample;
- TRef<IDirectDrawSurfaceX> m_pddsSample;
- TRef<PrivateSurface> m_psurface;
- ZString m_strFile;
- bool m_bTriggered;
- bool m_bFirstFrame;
- bool m_bStarted;
- //////////////////////////////////////////////////////////////////////////////
- //
- // Constructor
- //
- //////////////////////////////////////////////////////////////////////////////
- VideoImageImpl(
- PrivateEngine* pengine,
- RectValue* prect,
- const ZString& str
- ) :
- VideoImage(prect),
- m_pengine(pengine),
- m_peventSource(new EventSourceImpl()),
- m_strFile(str),
- m_bStarted(false),
- m_bTriggered(false),
- m_bFirstFrame(true)
- {
- //
- // Create the Active Movie Multi Media Stream
- //
- HRESULT hr = CoCreateInstance(CLSID_AMMultiMediaStream, NULL, CLSCTX_INPROC_SERVER, IID_IAMMultiMediaStream, (void **)&m_pAMStream);
-
- if (FAILED(hr) || m_pAMStream == NULL) {
- m_pAMStream = NULL;
- return;
- }
- ZSucceeded(m_pAMStream->Initialize(STREAMTYPE_READ, 0, NULL));
- //
- // Add renders for sound and video
- //
- DDDevice* pdddevice = m_pengine->GetPrimaryDevice();
- ZSucceeded(m_pAMStream->AddMediaStream(pdddevice->GetDD(), &MSPID_PrimaryVideo, 0, NULL));
- //
- // Don't check the return value. If this fails there just won't be audio playback.
- //
- m_pAMStream->AddMediaStream(NULL, &MSPID_PrimaryAudio, AMMSF_ADDDEFAULTRENDERER, NULL);
- //
- // Open the AVI File
- //
- WCHAR wPath[MAX_PATH];
- MultiByteToWideChar(CP_ACP, 0, m_strFile, -1, wPath, ArrayCount(wPath));
- if (FAILED(m_pAMStream->OpenFile(wPath, 0))) {
- m_pAMStream = NULL;
- }
- }
- bool IsValid()
- {
- return m_pAMStream != NULL;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Implementation methods
- //
- //////////////////////////////////////////////////////////////////////////////
- void AllocateSample()
- {
- if (m_pAMStream) {
- //
- // Create a Direct Draw video steam
- //
- TRef<IMediaStream> pPrimaryVidStream;
- TRef<IDirectDrawMediaStream> pDDStream;
- TRef<IDirectDrawSurface> pdds;
- ZSucceeded(m_pAMStream->GetMediaStream(MSPID_PrimaryVideo, &pPrimaryVidStream));
- ZSucceeded(pPrimaryVidStream->QueryInterface(IID_IDirectDrawMediaStream, (void **)&pDDStream));
- //
- // Get Information about the stream
- //
- DDSDescription ddsdCurrent;
- DDSDescription ddsdDesired;
- IDirectDrawPalette* pddpal;
- DWORD flags;
- HRESULT hr =
- pDDStream->GetFormat(
- (DDSURFACEDESC*)&ddsdCurrent,
- &pddpal,
- (DDSURFACEDESC*)&ddsdDesired,
- &flags
- );
- //
- // !!! sometime the size will come back zero, in that case just don't display anything
- //
- if (
- FAILED(hr)
- || ddsdDesired.XSize() == 0
- || ddsdDesired.YSize() == 0
- ) {
- End();
- return;
- }
- //
- // Create a surface that the video will be rendered to
- //
- CastTo(
- m_psurface,
- m_pengine->CreateSurface(
- ddsdDesired.Size(),
- SurfaceType2D()
- )
- );
- DDSurface* pddsurface; CastTo(pddsurface, m_psurface->GetVideoSurface());
- m_pddsSample = pddsurface->GetDDSX();
- //
- // Create a ddsample from the surface
- //
- ZSucceeded(pDDStream->CreateSample(
- pddsurface->GetDDS(),
- NULL,
- DDSFF_PROGRESSIVERENDER,
- &m_psample
- ));
- }
- }
- void Start()
- {
- //
- // Start playback
- //
- m_bStarted = true;
- ZSucceeded(m_pAMStream->SetState(STREAMSTATE_RUN));
- }
- void End()
- {
- if (!m_bTriggered) {
- m_bTriggered = true;
- m_peventSource->Trigger();
- }
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // DeviceDependant methods
- //
- //////////////////////////////////////////////////////////////////////////////
- void ClearDevice()
- {
- //
- // no need to free the stream since we always use the primary device
- //
- // m_pAMStream = NULL;
- m_pddsSample = NULL;
- m_psample = NULL;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // VideoImage methods
- //
- //////////////////////////////////////////////////////////////////////////////
- IEventSource* GetEventSource()
- {
- return m_peventSource;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Image methods
- //
- //////////////////////////////////////////////////////////////////////////////
- void CalcBounds()
- {
- m_bounds.SetRect(GetRect()->GetValue());
- }
- void Render(Context* pcontextArg)
- {
- if (m_bFirstFrame) {
- m_bFirstFrame = false;
- return;
- }
- if (m_psample == NULL) {
- AllocateSample();
- }
- if (m_psample) {
- if (!m_bStarted) {
- Start();
- }
- bool bTrigger = (m_psample->Update(0, NULL, NULL, 0) != S_OK);
- PrivateContext* pcontext; CastTo(pcontext, pcontextArg);
- WinRect rect = WinRect::Cast(GetRect()->GetValue());
- WinPoint size = m_psurface->GetSize();
- if (
- size.X() <= rect.XSize() / 2
- && size.Y() <= rect.YSize() / 2
- ) {
- //
- // Double size sample will fit on screen so double it
- //
- WinPoint offset = rect.Min() + (rect.Size() - size * 2) / 2;
- pcontext->GetSurface()->BitBlt(
- WinRect(
- offset,
- offset + size * 2
- ),
- m_psurface
- );
- } else {
- //
- // Center the sample
- //
- pcontext->GetSurface()->BitBlt(
- rect.Min() + (rect.Size() - size) / 2,
- m_psurface
- );
- }
- if (bTrigger) {
- End();
- }
- } else {
- End();
- }
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Value members
- //
- //////////////////////////////////////////////////////////////////////////////
- ZString GetFunctionName() { return "VideoImage"; }
- };
- //////////////////////////////////////////////////////////////////////////////
- //
- //
- //
- //////////////////////////////////////////////////////////////////////////////
- TRef<VideoImage> CreateVideoImage(
- Engine* pengine,
- RectValue* prect,
- const ZString& str
- ) {
- PrivateEngine* pprivateEngine; CastTo(pprivateEngine, pengine);
- return new VideoImageImpl(pprivateEngine, prect, str);
- }
|