]> git.sesse.net Git - casparcg/commitdiff
2.0.0.2:
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Tue, 4 Jan 2011 14:14:31 +0000 (14:14 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Tue, 4 Jan 2011 14:14:31 +0000 (14:14 +0000)
   - Free-running flash did not work properly.

git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.0.2@318 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

common/concurrency/executor.h
core/core.vcxproj
core/core.vcxproj.filters
core/producer/flash/FlashAxContainer.cpp
core/producer/flash/FlashAxContainer.h
core/producer/flash/TimerHelper.h [new file with mode: 0644]
core/producer/flash/flash_producer.cpp
shell/caspar.config

index 3b0fc3e1ac271fc91d9d365487a2bbb871a623cf..1369dd6004d0630f82fb3402cc62f95f04a79a33 100644 (file)
@@ -49,6 +49,12 @@ public:
                if(policy == wait && boost::this_thread::get_id() != thread_.get_id())\r
                        thread_.join();\r
        }\r
+\r
+       void clear()\r
+       {\r
+               std::function<void()> func;\r
+               while(execution_queue_.try_pop(func)){}\r
+       }\r
                        \r
        template<typename Func>\r
        auto begin_invoke(Func&& func) -> boost::unique_future<decltype(func())> // noexcept\r
index 801a97000f1a2383886320b506f4163016dcbf96..e9b5cbd50652e3001be9068385fe1fee18be1020 100644 (file)
     <ClInclude Include="producer\flash\cg_producer.h" />\r
     <ClInclude Include="producer\flash\FlashAxContainer.h" />\r
     <ClInclude Include="producer\flash\flash_producer.h" />\r
+    <ClInclude Include="producer\flash\TimerHelper.h" />\r
     <ClInclude Include="producer\frame_producer.h" />\r
     <ClInclude Include="producer\image\image_loader.h" />\r
     <ClInclude Include="producer\image\image_producer.h" />\r
index ddd2f1c55e66e8e62af40a4d8e9d182b0840bbc0..483ffca61e52ed276a7e7390987e970900ca8720 100644 (file)
     <ClInclude Include="producer\flash\axflash.h">\r
       <Filter>Source\channel\producer\flash\interop</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="producer\flash\TimerHelper.h">\r
+      <Filter>Source\channel\producer\flash\interop</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClCompile Include="protocol\amcp\AMCPCommandQueue.cpp">\r
index 6357d69f8a6dcc462587d8e936ac5d14e9ef03d0..cdb7641a3a56335558395a2cc572b4afc6fe9b55 100644 (file)
 #include "..\..\stdafx.h"\r
 \r
 #include "FlashAxContainer.h"\r
-#include "..\..\format\video_format.h"\r
-#include "flash_producer.h"\r
+#include "TimerHelper.h"\r
 \r
 using namespace ATL;\r
 \r
 #if defined(_MSC_VER)\r
-#pragma warning (push, 1) // TODO: Legacy code, just disable warnings\r
+#pragma warning (push, 1) // TODO: Legacy code, just disable warnings, will replace with boost::asio in future\r
 #endif\r
 \r
-namespace caspar { namespace core {\r
+namespace caspar {\r
 namespace flash {\r
 \r
 CComBSTR FlashAxContainer::flashGUID_(_T("{D27CDB6E-AE6D-11CF-96B8-444553540000}"));\r
@@ -38,20 +37,19 @@ CComBSTR FlashAxContainer::flashGUID_(_T("{D27CDB6E-AE6D-11CF-96B8-444553540000}
 _ATL_FUNC_INFO fnInfoFlashCallEvent = { CC_STDCALL, VT_EMPTY, 1, { VT_BSTR } };\r
 _ATL_FUNC_INFO fnInfoReadyStateChangeEvent = { CC_STDCALL, VT_EMPTY, 1, { VT_I4 } };\r
 \r
-FlashAxContainer::FlashAxContainer() : bInPlaceActive_(FALSE), m_lpDD4(0)\r
+FlashAxContainer::FlashAxContainer() : bInPlaceActive_(FALSE), pTimerHelper(0), bInvalidRect_(false), bReadyToRender_(false), bHasNewTiming_(false), m_lpDD4(0), timerCount_(0)\r
 {\r
-       bInvalidRect_ = false;\r
-       bCallSuccessful_ = false;\r
-       bReadyToRender_ = false;\r
 }\r
 FlashAxContainer::~FlashAxContainer()\r
-{\r
+{      \r
        if(m_lpDD4)\r
        {\r
                m_lpDD4->Release();\r
                m_lpDD4 = nullptr;\r
        }\r
-       CASPAR_LOG(info) << "[FlashAxContainer] Destroyed";\r
+\r
+       if(pTimerHelper != 0)\r
+               delete pTimerHelper;\r
 }\r
 \r
 \r
@@ -409,6 +407,35 @@ HRESULT STDMETHODCALLTYPE FlashAxContainer::ShowPropertyFrame()
 }\r
 \r
 \r
+///////////////////\r
+// IAdviseSink\r
+///////////////////\r
+void STDMETHODCALLTYPE FlashAxContainer::OnDataChange(FORMATETC* pFormatetc, STGMEDIUM* pStgmed)\r
+{\r
+       ATLTRACE(_T("IAdviseSink::OnDataChange\n"));\r
+}\r
+\r
+void STDMETHODCALLTYPE FlashAxContainer::OnViewChange(DWORD dwAspect, LONG lindex)\r
+{\r
+       ATLTRACE(_T("IAdviseSink::OnViewChange\n"));\r
+}\r
+\r
+void STDMETHODCALLTYPE FlashAxContainer::OnRename(IMoniker* pmk)\r
+{\r
+       ATLTRACE(_T("IAdviseSink::OnRename\n"));\r
+}\r
+\r
+void STDMETHODCALLTYPE FlashAxContainer::OnSave()\r
+{\r
+       ATLTRACE(_T("IAdviseSink::OnSave\n"));\r
+}\r
+\r
+void STDMETHODCALLTYPE FlashAxContainer::OnClose()\r
+{\r
+       ATLTRACE(_T("IAdviseSink::OnClose\n"));\r
+}\r
+\r
+\r
 //DirectDraw GUIDS\r
 \r
 DEFINE_GUID2(CLSID_DirectDraw,0xD7B70EE0,0x4340,0x11CF,0xB0,0x63,0x00,0x20,0xAF,0xC2,0xCD,0x35);\r
@@ -433,7 +460,6 @@ HRESULT STDMETHODCALLTYPE FlashAxContainer::QueryService( REFGUID rsid, REFIID r
        *ppvObj = NULL;\r
        \r
        HRESULT hr;\r
-\r
        // Author: Makarov Igor\r
        // Transparent Flash Control in Plain C++ \r
        // http://www.codeproject.com/KB/COM/flashcontrol.aspx \r
@@ -447,7 +473,6 @@ HRESULT STDMETHODCALLTYPE FlashAxContainer::QueryService( REFGUID rsid, REFIID r
                        {\r
                                delete m_lpDD4;\r
                                m_lpDD4 = NULL;\r
-                               CASPAR_LOG(warning) << "[FlashAxContainer] Failed to query DirectDraw Service";\r
                                return E_NOINTERFACE;\r
                        }\r
                }\r
@@ -465,6 +490,97 @@ HRESULT STDMETHODCALLTYPE FlashAxContainer::QueryService( REFGUID rsid, REFIID r
        return hr;\r
 }\r
 \r
+\r
+///////////////////\r
+// ITimerService\r
+///////////////////\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::CreateTimer(ITimer *pReferenceTimer, ITimer **ppNewTimer)\r
+{\r
+       ATLTRACE(_T("ITimerService::CreateTimer\n"));\r
+       if(pTimerHelper != 0)\r
+       {\r
+               delete pTimerHelper;\r
+               pTimerHelper = 0;\r
+       }\r
+       pTimerHelper = new TimerHelper();\r
+       return QueryInterface(__uuidof(ITimer), (void**) ppNewTimer);\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::GetNamedTimer(REFGUID rguidName, ITimer **ppTimer)\r
+{\r
+       ATLTRACE(_T("ITimerService::GetNamedTimer"));\r
+       if(ppTimer == NULL)\r
+               return E_POINTER;\r
+       else\r
+               *ppTimer = NULL;\r
+\r
+       return E_FAIL;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::SetNamedTimerReference(REFGUID rguidName, ITimer *pReferenceTimer)\r
+{\r
+       ATLTRACE(_T("ITimerService::SetNamedTimerReference"));\r
+       return S_OK;\r
+}\r
+\r
+///////////\r
+// ITimer\r
+///////////\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::Advise(VARIANT vtimeMin, VARIANT vtimeMax, VARIANT vtimeInterval, DWORD dwFlags, ITimerSink *pTimerSink, DWORD *pdwCookie)\r
+{\r
+       ATLTRACE(_T("Timer::Advise\n"));\r
+\r
+       if(pdwCookie == 0)\r
+               return E_POINTER;\r
+\r
+       if(pTimerHelper != 0)\r
+       {\r
+               pTimerHelper->Setup(vtimeMin.ulVal, vtimeInterval.ulVal, pTimerSink);\r
+               *pdwCookie = pTimerHelper->ID;\r
+               bHasNewTiming_ = true;\r
+\r
+               return S_OK;\r
+       }\r
+       else\r
+               return E_OUTOFMEMORY;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::Unadvise(/* [in] */ DWORD dwCookie)\r
+{\r
+       ATLTRACE(_T("Timer::Unadvice\n"));\r
+       if(pTimerHelper != 0)\r
+       {\r
+               pTimerHelper->pTimerSink = 0;\r
+               return S_OK;\r
+       }\r
+       else\r
+               return E_FAIL;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::Freeze(/* [in] */ BOOL fFreeze)\r
+{\r
+       ATLTRACE(_T("Timer::Freeze\n"));\r
+       return S_OK;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::GetTime(/* [out] */ VARIANT *pvtime)\r
+{\r
+       ATLTRACE(_T("Timer::GetTime\n"));\r
+       if(pvtime == 0)\r
+               return E_POINTER;\r
+\r
+//     return E_NOTIMPL;\r
+       pvtime->lVal = 0;\r
+       return S_OK;\r
+}\r
+\r
+int FlashAxContainer::GetFPS() {\r
+       if(pTimerHelper != 0 && pTimerHelper->interval > 0)\r
+               return (1000 / pTimerHelper->interval);\r
+       \r
+       return 0;\r
+}\r
+\r
 bool FlashAxContainer::IsReadyToRender() const {\r
        return bReadyToRender_;\r
 }\r
@@ -489,36 +605,37 @@ void STDMETHODCALLTYPE FlashAxContainer::OnFlashCall(BSTR request)
        }\r
        else if(str.find(TEXT("OnCommand")) != std::wstring::npos) {\r
                //this is how templatehost 1.8 reports that a command has been received\r
-               CASPAR_LOG(info) << "TEMPLATEHOST: " << str;\r
+               CASPAR_LOG(info) << TEXT("TEMPLATEHOST: ") << str;\r
                bCallSuccessful_ = true;\r
        }\r
        else if(str.find(TEXT("Activity")) != std::wstring::npos)\r
        {\r
-               CASPAR_LOG(info) << "TEMPLATEHOST: " << str;\r
+               CASPAR_LOG(info) << TEXT("TEMPLATEHOST: ") << str;\r
 \r
                //this is how templatehost 1.7 reports that a command has been received\r
                if(str.find(TEXT("Command recieved")) != std::wstring::npos)\r
                        bCallSuccessful_ = true;\r
 \r
-               /*if(pflash_producer_ != 0 && pflash_producer_->pMonitor_) {\r
+               /*if(pFlashProducer_ != 0 && pFlashProducer_->pMonitor_) {\r
                        std::wstring::size_type pos = str.find(TEXT('@'));\r
                        if(pos != std::wstring::npos)\r
-                               pflash_producer_->GetMonitor()->Inform(str.substr(pos, str.find(TEXT('<'), pos)-pos));\r
+                               pFlashProducer_->pMonitor_->Inform(str.substr(pos, str.find(TEXT('<'), pos)-pos));\r
                }*/\r
        }\r
        else if(str.find(TEXT("OnNotify")) != std::wstring::npos)\r
        {\r
-               CASPAR_LOG(info) << "TEMPLATEHOST: " << str;\r
+               CASPAR_LOG(info) << TEXT("TEMPLATEHOST: ") << str;\r
 \r
-               //if(pflash_producer_ != 0 && pflash_producer_->pMonitor_) {\r
+               //if(pFlashProducer_ != 0 && pFlashProducer_->pMonitor_) {\r
                //      std::wstring::size_type pos = str.find(TEXT('@'));\r
                //      if(pos != std::wstring::npos)\r
-               //              pflash_producer_->pMonitor_->Inform(str.substr(pos, str.find(TEXT('<'), pos)-pos));\r
+               //              pFlashProducer_->pMonitor_->Inform(str.substr(pos, str.find(TEXT('<'), pos)-pos));\r
                //}\r
        }\r
        else if(str.find(TEXT("IsEmpty")) != std::wstring::npos)\r
        {\r
                ATLTRACE(_T("ShockwaveFlash::IsEmpty\n"));\r
+               bIsEmpty_ = true;\r
        }\r
        else if(str.find(TEXT("OnError")) != std::wstring::npos)\r
        {\r
@@ -689,18 +806,13 @@ HRESULT FlashAxContainer::CreateAxControl()
        return S_OK;\r
 }\r
 \r
-HRESULT FlashAxContainer::SetFormat(const video_format_desc& format_desc) \r
-{\r
-       if(m_spInPlaceObjectWindowless == nullptr)\r
-               return E_FAIL;\r
-\r
-       if(m_rcPos.right != format_desc.width || m_rcPos.bottom != format_desc.height)\r
+void FlashAxContainer::SetFormat(const core::video_format_desc& fmtDesc) {\r
+       if(m_spInPlaceObjectWindowless != 0)\r
        {\r
-               RECT oldRcPos = m_rcPos;\r
                m_rcPos.top = 0;\r
                m_rcPos.left = 0;\r
-               m_rcPos.right = format_desc.width;\r
-               m_rcPos.bottom = format_desc.height;\r
+               m_rcPos.right = fmtDesc.width;\r
+               m_rcPos.bottom = fmtDesc.height;\r
 \r
                m_pxSize.cx = m_rcPos.right - m_rcPos.left;\r
                m_pxSize.cy = m_rcPos.bottom - m_rcPos.top;\r
@@ -711,15 +823,9 @@ HRESULT FlashAxContainer::SetFormat(const video_format_desc& format_desc)
                m_rcPos.right = m_rcPos.left + m_pxSize.cx;\r
                m_rcPos.bottom = m_rcPos.top + m_pxSize.cy;\r
 \r
-               HRESULT result = m_spInPlaceObjectWindowless->SetObjectRects(&m_rcPos, &m_rcPos);\r
+               m_spInPlaceObjectWindowless->SetObjectRects(&m_rcPos, &m_rcPos);\r
                bInvalidRect_ = true;\r
-               if(FAILED(result))\r
-                        m_spInPlaceObjectWindowless->SetObjectRects(&oldRcPos, &oldRcPos);\r
-\r
-               return result;\r
        }\r
-\r
-       return S_OK;\r
 }\r
 \r
 HRESULT FlashAxContainer::QueryControl(REFIID iid, void** ppUnk)\r
@@ -737,19 +843,17 @@ bool FlashAxContainer::DrawControl(HDC targetDC)
 //     ATLTRACE(_T("FlashAxContainer::DrawControl\n"));\r
        DVASPECTINFO aspectInfo = {sizeof(DVASPECTINFO), DVASPECTINFOFLAG_CANOPTIMIZE};\r
        HRESULT hr = S_OK;\r
-       \r
+\r
        hr = m_spViewObject->Draw(DVASPECT_CONTENT, -1, &aspectInfo, NULL, NULL, targetDC, NULL, NULL, NULL, NULL); \r
-       assert(SUCCEEDED(hr));\r
        bInvalidRect_ = false;\r
-\r
-/*     const video_format_desc& format_desc = video_format_desc::format_descs[format_];\r
+/*     const video_format_desc& fmtDesc = video_format_desc::FormatDescriptions[format_];\r
 \r
        //Trying to redraw just the dirty rectangles. Doesn't seem to work when the movie uses "filters", such as glow, dropshadow etc.\r
        std::vector<flash::DirtyRect>::iterator it = bDirtyRects_.begin();\r
        std::vector<flash::DirtyRect>::iterator end = bDirtyRects_.end();\r
        for(; it != end; ++it) {\r
                flash::DirtyRect& dirtyRect = (*it);\r
-               if(dirtyRect.bWhole || dirtyRect.rect.right >= format_desc.width || dirtyRect.rect.bottom >= format_desc.height) {\r
+               if(dirtyRect.bWhole || dirtyRect.rect.right >= fmtDesc.width || dirtyRect.rect.bottom >= fmtDesc.height) {\r
                        m_spInPlaceObjectWindowless->SetObjectRects(&m_rcPos, &m_rcPos);\r
                        hr = m_spViewObject->Draw(DVASPECT_OPAQUE, -1, NULL, NULL, NULL, targetDC, NULL, NULL, NULL, NULL); \r
                        break;\r
@@ -765,32 +869,32 @@ bool FlashAxContainer::DrawControl(HDC targetDC)
        return (hr == S_OK);\r
 }\r
 \r
-bool FlashAxContainer::InvalidRectangle() const\r
+void FlashAxContainer::Tick()\r
 {\r
-       return bInvalidRect_;\r
+       if(pTimerHelper)\r
+       {\r
+               DWORD time = pTimerHelper->Invoke(); // Tick flash\r
+               if(time - timerCount_ >= 400)\r
+               {\r
+                       timerCount_ = time;\r
+                       HRESULT hr;\r
+                       m_spInPlaceObjectWindowless->OnWindowMessage(WM_TIMER, 3, 0, &hr);\r
+               }\r
+       }\r
 }\r
 \r
-bool FlashAxContainer::CallFunction(const std::wstring& param)\r
+bool FlashAxContainer::FlashCall(const std::wstring& str)\r
 {\r
-       bCallSuccessful_ = false;\r
-\r
+       CComBSTR result;\r
        CComPtr<IShockwaveFlash> spFlash;\r
-       if(SUCCEEDED(QueryControl(&spFlash)))\r
-       {\r
-               CComBSTR request(param.c_str());\r
-               CComBSTR result;\r
-               return SUCCEEDED(spFlash->CallFunction(request, &result)) || bCallSuccessful_;          \r
-       }\r
+       QueryControl(&spFlash);\r
+       CComBSTR request(str.c_str());\r
 \r
-       return false;\r
+       bCallSuccessful_ = false;\r
+       for(size_t retries = 0; !bCallSuccessful_ && retries < 4; ++retries)\r
+               spFlash->CallFunction(request, &result);\r
+       return bCallSuccessful_;\r
 }\r
 \r
-// Receives the following messages:\r
-// 0           0x0000 ?\r
-// 275         0x0113 WM_TIMER\r
-// 536         0x0218 WM_POWERBROADCAST\r
-// 49286       0xC086 ?\r
-\r
-\r
 }      //namespace flash\r
-}}     //namespace caspar
\ No newline at end of file
+}      //namespace caspar
\ No newline at end of file
index e397911aa71366405d582b4fa3a5cc4a36dc481e..baf1998b94e2ac1d21239299256e4b54123bf4bd 100644 (file)
 *\r
 */\r
  \r
-#if defined(_MSC_VER)\r
-#pragma once\r
-#endif\r
-\r
 #ifndef _FLASHAXCONTAINER_H__\r
 #define _FLASHAXCONTAINER_H__\r
 \r
-#pragma warning(push)\r
-#pragma warning(disable : 4996)\r
-\r
-       #include <atlbase.h>\r
-\r
-       #include <atlcom.h>\r
-       #include <atlhost.h>\r
+#pragma once\r
 \r
-#pragma warning(push)\r
+#include <atlbase.h>\r
+#include <atlcom.h>\r
+#include <atlhost.h>\r
 \r
-#include "..\..\processor\write_frame.h"\r
-#include "..\..\format\video_format.h"\r
 \r
 #include <ocmm.h>\r
 #include <vector>\r
-#include <tbb\atomic.h>\r
 \r
+#include "../../format/video_format.h"\r
 #include "axflash.h"\r
+//#import "progid:ShockwaveFlash.ShockwaveFlash.9" no_namespace, named_guids\r
 \r
 #include <ddraw.h>\r
 #include <comdef.h>\r
 \r
+#include "TimerHelper.h"\r
+\r
 #ifndef DEFINE_GUID2\r
 #define DEFINE_GUID2(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \\r
         const GUID name \\r
 \r
 _COM_SMARTPTR_TYPEDEF(IDirectDraw4, IID_IDirectDraw4);\r
 \r
-//#import "progid:ShockwaveFlash.ShockwaveFlash.9" no_namespace, named_guids\r
+namespace caspar {\r
+\r
+namespace flash {\r
+\r
+class TimerHelper;\r
+struct DirtyRect {\r
+       DirtyRect(LONG l, LONG t, LONG r, LONG b, bool e) : bErase(e), bWhole(false) { \r
+               rect.left = l;\r
+               rect.top = t;\r
+               rect.right = r;\r
+               rect.bottom = b; \r
+       }\r
+       DirtyRect(const RECT& rc, bool e) : bErase(e), bWhole(false)  {\r
+               rect.left = rc.left;\r
+               rect.top = rc.top;\r
+               rect.right = rc.right;\r
+               rect.bottom = rc.bottom; \r
+       }\r
+       explicit DirtyRect(bool b) : bWhole(b) {}\r
+\r
+       RECT    rect;\r
+       bool    bErase;\r
+       bool    bWhole;\r
+};\r
 \r
-namespace caspar { namespace core { namespace flash {\r
-       \r
 extern _ATL_FUNC_INFO fnInfoFlashCallEvent;\r
 extern _ATL_FUNC_INFO fnInfoReadyStateChangeEvent;\r
 \r
@@ -71,6 +85,9 @@ class ATL_NO_VTABLE FlashAxContainer :
                public IOleInPlaceSiteWindowless,\r
                public IObjectWithSiteImpl<FlashAxContainer>,\r
                public IServiceProvider,\r
+               public IAdviseSink,\r
+               public ITimerService,\r
+               public ITimer,\r
                public IDispatchImpl<IDispatch>,\r
                public IDispEventSimpleImpl<0, FlashAxContainer, &DIID__IShockwaveFlashEvents>\r
 {\r
@@ -98,6 +115,11 @@ public:
 \r
                COM_INTERFACE_ENTRY(IServiceProvider)\r
 \r
+               COM_INTERFACE_ENTRY(IAdviseSink)\r
+\r
+               COM_INTERFACE_ENTRY(ITimerService)\r
+\r
+               COM_INTERFACE_ENTRY(ITimer)\r
        END_COM_MAP()\r
 \r
        BEGIN_SINK_MAP(FlashAxContainer)\r
@@ -161,6 +183,13 @@ public:
        STDMETHOD(OnFocus)(BOOL fGotFocus);\r
        STDMETHOD(ShowPropertyFrame)();\r
 \r
+// IAdviseSink\r
+       STDMETHOD_(void, OnDataChange)(FORMATETC* pFormatetc, STGMEDIUM* pStgmed);\r
+       STDMETHOD_(void, OnViewChange)(DWORD dwAspect, LONG lindex);\r
+       STDMETHOD_(void, OnRename)(IMoniker* pmk);\r
+       STDMETHOD_(void, OnSave)();\r
+       STDMETHOD_(void, OnClose)();\r
+\r
 // IServiceProvider\r
        STDMETHOD(QueryService)( REFGUID rsid, REFIID riid, void** ppvObj);\r
 \r
@@ -193,6 +222,18 @@ public:
                ATLTRACENOTIMPL(_T("IOleContainer::LockContainer"));\r
        }\r
 \r
+//ITimerService\r
+       STDMETHOD(CreateTimer)(ITimer *pReferenceTimer, ITimer **ppNewTimer);\r
+       STDMETHOD(GetNamedTimer)(REFGUID rguidName, ITimer **ppTimer);\r
+       STDMETHOD(SetNamedTimerReference)(REFGUID rguidName, ITimer *pReferenceTimer);\r
+\r
+//ITimer\r
+       STDMETHOD(Advise)(VARIANT vtimeMin, VARIANT vtimeMax, VARIANT vtimeInterval, DWORD dwFlags, ITimerSink *pTimerSink, DWORD *pdwCookie);\r
+       STDMETHOD(Unadvise)(DWORD dwCookie);\r
+       STDMETHOD(Freeze)(BOOL fFreeze);\r
+       STDMETHOD(GetTime)(VARIANT *pvtime);\r
+       int GetFPS();\r
+\r
        HRESULT CreateAxControl();\r
        void DestroyAxControl();\r
        HRESULT QueryControl(REFIID iid, void** ppUnk);\r
@@ -203,25 +244,36 @@ public:
                return QueryControl(__uuidof(Q), (void**)ppUnk);\r
        }\r
 \r
-       bool InvalidRectangle() const;\r
-       bool CallFunction(const std::wstring& param);\r
-\r
 //     static ATL::CComObject<FlashAxContainer>* CreateInstance();\r
 \r
+       void Tick();\r
+       bool FlashCall(const std::wstring& str);\r
        bool DrawControl(HDC targetDC);\r
+       bool InvalidRect() const { return bInvalidRect_; } \r
+       bool IsEmpty() const { return bIsEmpty_; }\r
 \r
-       HRESULT SetFormat(const video_format_desc&);\r
+       void SetFormat(const core::video_format_desc&);\r
        bool IsReadyToRender() const;\r
        void EnterFullscreen();\r
 \r
        static bool CheckForFlashSupport();\r
+\r
+       ATL::CComPtr<IOleInPlaceObjectWindowless> m_spInPlaceObjectWindowless;\r
+\r
 private:\r
+       TimerHelper* pTimerHelper;\r
+       volatile bool bInvalidRect_;\r
+       volatile bool bCallSuccessful_;\r
+       volatile bool bReadyToRender_;\r
+       volatile bool bIsEmpty_;\r
+       volatile bool bHasNewTiming_;\r
+       std::vector<DirtyRect> bDirtyRects_;\r
+\r
+\r
        IDirectDraw4Ptr *m_lpDD4;\r
        static CComBSTR flashGUID_;\r
 \r
-       tbb::atomic<bool> bInvalidRect_;\r
-       tbb::atomic<bool> bCallSuccessful_;\r
-       tbb::atomic<bool> bReadyToRender_;\r
+       DWORD timerCount_;\r
 \r
 //     state\r
        bool            bUIActive_;\r
@@ -239,12 +291,11 @@ private:
        ATL::CComPtr<IOleObject> m_spServices;\r
        ATL::CComPtr<IOleObject> m_spOleObject;\r
        ATL::CComPtr<IViewObjectEx> m_spViewObject;\r
-       ATL::CComPtr<IOleInPlaceObjectWindowless> m_spInPlaceObjectWindowless;\r
 \r
 //     ATL::CComPtr<ATL::CComObject<MyMoniker> > m_spMyMoniker;\r
 };\r
 \r
 }      //namespace flash\r
-}}     //namespace caspar\r
+}      //namespace caspar\r
 \r
 #endif //_FLASHAXCONTAINER_H__
\ No newline at end of file
diff --git a/core/producer/flash/TimerHelper.h b/core/producer/flash/TimerHelper.h
new file mode 100644 (file)
index 0000000..a0de2b1
--- /dev/null
@@ -0,0 +1,77 @@
+/*\r
+* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
+*\r
+*  This file is part of CasparCG.\r
+*\r
+*    CasparCG is free software: you can redistribute it and/or modify\r
+*    it under the terms of the GNU General Public License as published by\r
+*    the Free Software Foundation, either version 3 of the License, or\r
+*    (at your option) any later version.\r
+*\r
+*    CasparCG is distributed in the hope that it will be useful,\r
+*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*    GNU General Public License for more details.\r
+\r
+*    You should have received a copy of the GNU General Public License\r
+*    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+*/\r
\r
+#ifndef _TIMER_HELPER_H__\r
+#define _TIMER_HELPER_H__\r
+\r
+#include "FlashAxContainer.h"\r
+\r
+namespace caspar {\r
+namespace flash {\r
+\r
+       class TimerHelper\r
+       {\r
+               TimerHelper(const TimerHelper&);\r
+               const TimerHelper& operator=(const TimerHelper&);\r
+\r
+       public:\r
+               TimerHelper()\r
+               {}\r
+               TimerHelper(DWORD first, DWORD interv, ITimerSink* pTS) : firstTime(first), interval(interv), currentTime(first), pTimerSink(pTS)\r
+               {\r
+                       ID = first;\r
+               }\r
+               ~TimerHelper()\r
+               {\r
+               }\r
+               void Setup(DWORD first, DWORD interv, ITimerSink* pTS)\r
+               {\r
+                       firstTime = first;\r
+                       interval = interv;\r
+                       currentTime = first;\r
+                       pTimerSink = pTS;\r
+                       ID = first;\r
+               }\r
+\r
+               DWORD Invoke()\r
+               {\r
+                       if(pTimerSink != 0)\r
+                       {\r
+                               VARIANT value;\r
+                               value.vt = VT_UI4;\r
+                               value.ulVal = currentTime;\r
+\r
+                               pTimerSink->OnTimer(value);\r
+                               currentTime += interval;\r
+                       }\r
+                       return currentTime;\r
+               }\r
+\r
+               DWORD firstTime;\r
+               DWORD interval;\r
+               DWORD currentTime;\r
+               ATL::CComPtr<ITimerSink> pTimerSink;\r
+               DWORD ID;\r
+       };\r
+\r
+}      //namespace flash\r
+}      //namespace caspar\r
+\r
+#endif //_TIMER_HELPER_H__
\ No newline at end of file
index 07c2848fb66a89356c85366941444268a15d5c43..8af8d3da568b388a48b4ca8383167f715cd27c9e 100644 (file)
@@ -46,26 +46,13 @@ extern __declspec(selectany) CAtlModule* _pAtlModule = &_AtlModule;
 class flash_renderer\r
 {\r
 public:\r
-       flash_renderer() : tail_(draw_frame::empty()), head_(draw_frame::empty()), bmp_data_(nullptr), ax_(nullptr) {}\r
-\r
-       ~flash_renderer()\r
-       {               \r
-               if(ax_)\r
-               {\r
-                       ax_->DestroyAxControl();\r
-                       ax_->Release();\r
-               }\r
-               CASPAR_LOG(info) << print() << L" Ended";\r
-       }\r
-\r
-       void load(const std::shared_ptr<frame_processor_device>& frame_processor, const std::wstring& filename)\r
+       flash_renderer(const std::shared_ptr<frame_processor_device>& frame_processor, const std::wstring& filename) \r
+               : head_(draw_frame::empty()), bmp_data_(nullptr), ax_(nullptr), filename_(filename), hdc_(CreateCompatibleDC(0), DeleteDC), frame_processor_(frame_processor), \r
+                       format_desc_(frame_processor->get_video_format_desc())\r
        {\r
-               filename_ = filename;\r
-               hdc_.reset(CreateCompatibleDC(0), DeleteDC);\r
-               frame_processor_ = frame_processor;\r
                CASPAR_LOG(info) << print() << L" Started";\r
                \r
-               if(FAILED(CComObject<FlashAxContainer>::CreateInstance(&ax_)))\r
+               if(FAILED(CComObject<caspar::flash::FlashAxContainer>::CreateInstance(&ax_)))\r
                        BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(bprint() + "Failed to create FlashAxContainer"));\r
                \r
                if(FAILED(ax_->CreateAxControl()))\r
@@ -84,11 +71,10 @@ public:
                if(FAILED(spFlash->put_ScaleMode(2)))  //Exact fit. Scale without respect to the aspect ratio.\r
                        BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(bprint() + "Failed to Set Scale Mode"));\r
                                                                                                                \r
-               if(FAILED(ax_->SetFormat(frame_processor_->get_video_format_desc())))  // stop if failed\r
-                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(bprint() + "Failed to Set Format"));\r
+               ax_->SetFormat(format_desc_);\r
+               //if(FAILED(ax_->SetFormat(frame_processor_->get_video_format_desc())))  // stop if failed\r
+               //      BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(bprint() + "Failed to Set Format"));\r
                \r
-               format_desc_ = frame_processor->get_video_format_desc();\r
-\r
                BITMAPINFO info;\r
                memset(&info, 0, sizeof(BITMAPINFO));\r
                info.bmiHeader.biBitCount = 32;\r
@@ -100,38 +86,46 @@ public:
 \r
                bmp_.reset(CreateDIBSection(static_cast<HDC>(hdc_.get()), &info, DIB_RGB_COLORS, reinterpret_cast<void**>(&bmp_data_), 0, 0), DeleteObject);\r
                SelectObject(static_cast<HDC>(hdc_.get()), bmp_.get()); \r
-\r
-               frame_buffer_.set_capacity(20);\r
-               for(int n = 0; n < frame_buffer_.capacity()/2; ++n)\r
-                       frame_buffer_.try_push(draw_frame::empty());\r
-               is_running_ = true;\r
        }\r
 \r
-       void param(const std::wstring& param) \r
+       ~flash_renderer()\r
        {               \r
-               params_.push(param);\r
+               if(ax_)\r
+               {\r
+                       ax_->DestroyAxControl();\r
+                       ax_->Release();\r
+               }\r
+               CASPAR_LOG(info) << print() << L" Ended";\r
        }\r
-               \r
-       void tick()\r
+       \r
+       void param(const std::wstring& param)\r
        {               \r
-               std::wstring param;\r
-               if(params_.try_pop(param))\r
-               {\r
-                       for(size_t retries = 0; !ax_->CallFunction(param); ++retries)\r
-                       {\r
-                               CASPAR_LOG(debug) << print() << L" Retrying. Count: " << retries;\r
-                               if(retries > 3)\r
-                                       CASPAR_LOG(warning) << "Flash Function Call Failed. Param: " << param;\r
-                       }\r
-               }       \r
-\r
-               if(!is_running_)\r
-                       PostQuitMessage(0);\r
+               if(!ax_->FlashCall(param))\r
+                       CASPAR_LOG(warning) << "Flash Function Call Failed. Param: " << param;\r
+       }\r
+       \r
+       safe_ptr<draw_frame> render_frame()\r
+       {\r
+               auto frame = render_simple_frame();\r
+               \r
+               auto running_fps = ax_->GetFPS();\r
+               auto target_fps = static_cast<int>(format_desc_.mode == video_mode::progressive ? format_desc_.fps : format_desc_.fps/2.0);\r
+               if(target_fps < running_fps)\r
+                       frame = draw_frame::interlace(frame, render_simple_frame(), format_desc_.mode);\r
+               return frame;\r
        }\r
+                       \r
+       std::wstring print() const{ return L"flash[" + boost::filesystem::wpath(filename_).filename() + L"] Render thread"; }\r
+       std::string bprint() const{ return narrow(print()); }\r
 \r
-       void render()\r
+private:\r
+\r
+       safe_ptr<draw_frame> render_simple_frame()\r
        {\r
-               if(ax_->IsReadyToRender() && ax_->InvalidRectangle())\r
+               if(!ax_->IsEmpty())\r
+                       ax_->Tick();\r
+\r
+               if(ax_->InvalidRect())\r
                {                       \r
                        std::fill_n(bmp_data_, format_desc_.size, 0);\r
                        ax_->DrawControl(static_cast<HDC>(hdc_.get()));\r
@@ -139,35 +133,11 @@ public:
                        auto frame = frame_processor_->create_frame();\r
                        std::copy_n(bmp_data_, format_desc_.size, frame->image_data().begin());\r
                        head_ = frame;\r
-               }                               \r
-               if(!frame_buffer_.try_push(head_))\r
-                       CASPAR_LOG(trace) << print() << " overflow";\r
-       }\r
-               \r
-       safe_ptr<draw_frame> get_frame()\r
-       {               \r
-               if(!frame_buffer_.try_pop(tail_))\r
-                       CASPAR_LOG(trace) << print() << " underflow";\r
+               }               \r
 \r
-               auto frame = tail_;\r
-               if(frame_buffer_.size() > frame_buffer_.capacity()/2) // Regulate between interlaced and progressive\r
-               {\r
-                       frame_buffer_.try_pop(tail_);\r
-                       frame = draw_frame::interlace(frame, tail_, format_desc_.mode);\r
-               }\r
-               return frame;\r
-       }\r
-       \r
-       void stop()\r
-       {\r
-               is_running_ = false;\r
+               return head_;\r
        }\r
 \r
-       std::wstring print() const{ return L"flash[" + boost::filesystem::wpath(filename_).filename() + L"] Render thread"; }\r
-       std::string bprint() const{ return narrow(print()); }\r
-\r
-private:\r
-       tbb::atomic<bool> is_running_;\r
        std::wstring filename_;\r
        std::shared_ptr<frame_processor_device> frame_processor_;\r
        video_format_desc format_desc_;\r
@@ -177,72 +147,88 @@ private:
        std::shared_ptr<void> hdc_;\r
        std::shared_ptr<void> bmp_;\r
 \r
-       CComObject<FlashAxContainer>* ax_;\r
-       tbb::concurrent_bounded_queue<safe_ptr<draw_frame>> frame_buffer_;      \r
-       safe_ptr<draw_frame> tail_;\r
+       CComObject<caspar::flash::FlashAxContainer>* ax_;\r
        safe_ptr<draw_frame> head_;\r
-\r
-       tbb::concurrent_queue<std::wstring> params_;\r
 };\r
 \r
 struct flash_producer::implementation\r
 {      \r
-       implementation(const std::wstring& filename) : filename_(filename), renderer_(std::make_shared<flash_renderer>())\r
+       implementation(const std::wstring& filename) : filename_(filename), tail_(draw_frame::empty())\r
        {       \r
                if(!boost::filesystem::exists(filename))\r
                        BOOST_THROW_EXCEPTION(file_not_found() << boost::errinfo_file_name(narrow(filename)));\r
+               \r
+               executor_.begin_invoke([=]\r
+               {\r
+                       ::OleInitialize(nullptr);\r
+               });\r
+\r
+               frame_buffer_.set_capacity(25);\r
+               while(frame_buffer_.try_push(draw_frame::empty())){}\r
        }\r
 \r
        ~implementation()\r
        {\r
-               renderer_->stop();\r
-       }\r
-       \r
-       void param(const std::wstring& param) \r
-       {       \r
-               renderer_->param(param);\r
+               executor_.clear();\r
+               executor_.invoke([=]\r
+               {\r
+                       renderer_ = nullptr;\r
+                       ::OleUninitialize();\r
+               });\r
        }\r
-       \r
-       void run()\r
-       {\r
-               CASPAR_LOG(info) << print() << " started.";\r
-\r
-               ::OleInitialize(nullptr);\r
-               \r
-               volatile auto keep_alive = renderer_;\r
-               renderer_->load(frame_processor_, filename_);\r
-\r
-               MSG msg;\r
-               while(GetMessage(&msg, 0, 0, 0))\r
-               {               \r
-                       if(msg.message == WM_USER + 1)\r
-                               renderer_->render();\r
-\r
-                       TranslateMessage(&msg);\r
-                       DispatchMessage(&msg);\r
-\r
-                       renderer_->tick();              \r
-               }\r
 \r
-               renderer_ = nullptr;\r
-\r
-               ::OleUninitialize();\r
+       virtual safe_ptr<draw_frame> receive()\r
+       {               \r
+               if(!frame_buffer_.try_pop(tail_))\r
+                       CASPAR_LOG(trace) << print() << " underflow";\r
 \r
-               CASPAR_LOG(info) << print() << " ended.";\r
+               executor_.begin_invoke([=]\r
+               {\r
+                       auto frame = draw_frame::empty();\r
+                       try\r
+                       {\r
+                               if(renderer_)\r
+                                       frame = renderer_->render_frame();\r
+                       }\r
+                       catch(...)\r
+                       {\r
+                               CASPAR_LOG_CURRENT_EXCEPTION();\r
+                               renderer_ = nullptr;\r
+                       }\r
+                       frame_buffer_.try_push(frame);\r
+               });     \r
+                               \r
+               return tail_;\r
        }\r
-\r
+       \r
        virtual void initialize(const safe_ptr<frame_processor_device>& frame_processor)\r
        {\r
                frame_processor_ = frame_processor;\r
-               thread_ = boost::thread([this]{run();});\r
+               executor_.start();\r
        }\r
+       \r
+       void param(const std::wstring& param) \r
+       {       \r
+               executor_.begin_invoke([=]\r
+               {\r
+                       if(!renderer_)\r
+                               renderer_.reset(new flash_renderer(frame_processor_, filename_));\r
 \r
-       virtual safe_ptr<draw_frame> receive()\r
-       {\r
-               return renderer_->get_frame();\r
+                       try\r
+                       {\r
+                               renderer_->param(param);\r
+                       }\r
+                       catch(...)\r
+                       {\r
+                               CASPAR_LOG_CURRENT_EXCEPTION();\r
+                               renderer_ = nullptr;\r
+                       }\r
+               });\r
        }\r
        \r
-       boost::thread thread_;\r
+       safe_ptr<draw_frame> tail_;\r
+       tbb::concurrent_bounded_queue<safe_ptr<draw_frame>> frame_buffer_;\r
+       executor executor_;\r
 \r
        std::shared_ptr<flash_renderer> renderer_;\r
        std::shared_ptr<frame_processor_device> frame_processor_;\r
index ea5a9d5403661e6b9f69b5fd1f35647f6723d342..f38e5fa61eb227519875061cdd4498e51ba9a321 100644 (file)
@@ -15,7 +15,7 @@
           <stretch>uniform</stretch>\r
           <windowed>true</windowed>\r
         </ogl>\r
-        <audio/>\r
+        <!--audio/-->\r
         <!--decklink>          \r
         </decklink>\r
         <bluefish>\r