ISubPic.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:18k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* 
  2.  * Copyright (C) 2003-2005 Gabest
  3.  * http://www.gabest.org
  4.  *
  5.  *  This Program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2, or (at your option)
  8.  *  any later version.
  9.  *   
  10.  *  This Program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13.  *  GNU General Public License for more details.
  14.  *   
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with GNU Make; see the file COPYING.  If not, write to
  17.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  18.  *  http://www.gnu.org/copyleft/gpl.html
  19.  *
  20.  */
  21. #include "stdafx.h"
  22. #include "ISubPic.h"
  23. #include "..DSUtilDSUtil.h"
  24. //
  25. // ISubPicImpl
  26. //
  27. ISubPicImpl::ISubPicImpl() 
  28. : CUnknown(NAME("ISubPicImpl"), NULL)
  29. , m_rtStart(0), m_rtStop(0)
  30. , m_rcDirty(0, 0, 0, 0), m_maxsize(0, 0), m_size(0, 0), m_vidrect(0, 0, 0, 0)
  31. {
  32. }
  33. STDMETHODIMP ISubPicImpl::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  34. {
  35. return 
  36. QI(ISubPic)
  37. __super::NonDelegatingQueryInterface(riid, ppv);
  38. }
  39. // ISubPic
  40. STDMETHODIMP_(REFERENCE_TIME) ISubPicImpl::GetStart()
  41. {
  42. return(m_rtStart);
  43. }
  44. STDMETHODIMP_(REFERENCE_TIME) ISubPicImpl::GetStop()
  45. {
  46. return(m_rtStop);
  47. }
  48. STDMETHODIMP_(void) ISubPicImpl::SetStart(REFERENCE_TIME rtStart)
  49. {
  50. m_rtStart = rtStart;
  51. }
  52. STDMETHODIMP_(void) ISubPicImpl::SetStop(REFERENCE_TIME rtStop)
  53. {
  54. m_rtStop = rtStop;
  55. }
  56. STDMETHODIMP ISubPicImpl::CopyTo(ISubPic* pSubPic)
  57. {
  58. if(!pSubPic)
  59. return E_POINTER;
  60. pSubPic->SetStart(m_rtStart);
  61. pSubPic->SetStop(m_rtStop);
  62. pSubPic->SetDirtyRect(m_rcDirty);
  63. pSubPic->SetSize(m_size, m_vidrect);
  64. return S_OK;
  65. }
  66. STDMETHODIMP ISubPicImpl::GetDirtyRect(RECT* pDirtyRect)
  67. {
  68. return pDirtyRect ? *pDirtyRect = m_rcDirty, S_OK : E_POINTER;
  69. }
  70. STDMETHODIMP ISubPicImpl::SetDirtyRect(RECT* pDirtyRect)
  71. {
  72. return pDirtyRect ? m_rcDirty = *pDirtyRect, S_OK : E_POINTER;
  73. }
  74. STDMETHODIMP ISubPicImpl::GetMaxSize(SIZE* pMaxSize)
  75. {
  76. return pMaxSize ? *pMaxSize = m_maxsize, S_OK : E_POINTER;
  77. }
  78. STDMETHODIMP ISubPicImpl::SetSize(SIZE size, RECT vidrect)
  79. {
  80. m_size = size;
  81. m_vidrect = vidrect;
  82. if(m_size.cx > m_maxsize.cx)
  83. {
  84. m_size.cy = MulDiv(m_size.cy, m_maxsize.cx, m_size.cx);
  85. m_size.cx = m_maxsize.cx;
  86. }
  87. if(m_size.cy > m_maxsize.cy)
  88. {
  89. m_size.cx = MulDiv(m_size.cx, m_maxsize.cy, m_size.cy);
  90. m_size.cy = m_maxsize.cy;
  91. }
  92. if(m_size.cx != size.cx || m_size.cy != size.cy)
  93. {
  94. m_vidrect.top = MulDiv(m_vidrect.top, m_size.cx, size.cx);
  95. m_vidrect.bottom = MulDiv(m_vidrect.bottom, m_size.cx, size.cx);
  96. m_vidrect.left = MulDiv(m_vidrect.left, m_size.cy, size.cy);
  97. m_vidrect.right = MulDiv(m_vidrect.right, m_size.cy, size.cy);
  98. }
  99. return S_OK;
  100. }
  101. //
  102. // ISubPicAllocatorImpl
  103. //
  104. ISubPicAllocatorImpl::ISubPicAllocatorImpl(SIZE cursize, bool fDynamicWriteOnly, bool fPow2Textures)
  105. : CUnknown(NAME("ISubPicAllocatorImpl"), NULL)
  106. , m_cursize(cursize)
  107. , m_fDynamicWriteOnly(fDynamicWriteOnly)
  108. , m_fPow2Textures(fPow2Textures)
  109. {
  110. m_curvidrect = CRect(CPoint(0,0), m_cursize);
  111. }
  112. STDMETHODIMP ISubPicAllocatorImpl::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  113. {
  114. return 
  115. QI(ISubPicAllocator)
  116. __super::NonDelegatingQueryInterface(riid, ppv);
  117. }
  118. // ISubPicAllocator
  119. STDMETHODIMP ISubPicAllocatorImpl::SetCurSize(SIZE cursize)
  120. {
  121. m_cursize = cursize; 
  122. return S_OK;
  123. }
  124. STDMETHODIMP ISubPicAllocatorImpl::SetCurVidRect(RECT curvidrect)
  125. {
  126. m_curvidrect = curvidrect; 
  127. return S_OK;
  128. }
  129. STDMETHODIMP ISubPicAllocatorImpl::GetStatic(ISubPic** ppSubPic)
  130. {
  131. if(!ppSubPic)
  132. return E_POINTER;
  133. if(!m_pStatic)
  134. {
  135. if(!Alloc(true, &m_pStatic) || !m_pStatic) 
  136. return E_OUTOFMEMORY;
  137. }
  138. m_pStatic->SetSize(m_cursize, m_curvidrect);
  139. (*ppSubPic = m_pStatic)->AddRef();
  140. return S_OK;
  141. }
  142. STDMETHODIMP ISubPicAllocatorImpl::AllocDynamic(ISubPic** ppSubPic)
  143. {
  144. if(!ppSubPic)
  145. return E_POINTER;
  146. if(!Alloc(false, ppSubPic) || !*ppSubPic)
  147. return E_OUTOFMEMORY;
  148. (*ppSubPic)->SetSize(m_cursize, m_curvidrect);
  149. return S_OK;
  150. }
  151. STDMETHODIMP_(bool) ISubPicAllocatorImpl::IsDynamicWriteOnly()
  152. {
  153. return(m_fDynamicWriteOnly);
  154. }
  155. STDMETHODIMP ISubPicAllocatorImpl::ChangeDevice(IUnknown* pDev)
  156. {
  157. m_pStatic = NULL;
  158. return S_OK;
  159. }
  160. //
  161. // ISubPicProviderImpl
  162. //
  163. ISubPicProviderImpl::ISubPicProviderImpl(CCritSec* pLock)
  164. : CUnknown(NAME("ISubPicProviderImpl"), NULL)
  165. , m_pLock(pLock)
  166. {
  167. }
  168. ISubPicProviderImpl::~ISubPicProviderImpl()
  169. {
  170. }
  171. STDMETHODIMP ISubPicProviderImpl::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  172. {
  173. return
  174. QI(ISubPicProvider)
  175. __super::NonDelegatingQueryInterface(riid, ppv);
  176. }
  177. // ISubPicProvider
  178. STDMETHODIMP ISubPicProviderImpl::Lock()
  179. {
  180. return m_pLock ? m_pLock->Lock(), S_OK : E_FAIL;
  181. }
  182. STDMETHODIMP ISubPicProviderImpl::Unlock()
  183. {
  184. return m_pLock ? m_pLock->Unlock(), S_OK : E_FAIL;
  185. }
  186. //
  187. // ISubPicQueueImpl
  188. //
  189. ISubPicQueueImpl::ISubPicQueueImpl(ISubPicAllocator* pAllocator, HRESULT* phr) 
  190. : CUnknown(NAME("ISubPicQueueImpl"), NULL)
  191. , m_pAllocator(pAllocator)
  192. , m_rtNow(0)
  193. , m_fps(25.0)
  194. {
  195. if(phr) *phr = S_OK;
  196. if(!m_pAllocator)
  197. {
  198. if(phr) *phr = E_FAIL;
  199. return;
  200. }
  201. }
  202. ISubPicQueueImpl::~ISubPicQueueImpl()
  203. {
  204. }
  205. STDMETHODIMP ISubPicQueueImpl::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  206. {
  207. return 
  208. QI(ISubPicQueue)
  209. __super::NonDelegatingQueryInterface(riid, ppv);
  210. }
  211. // ISubPicQueue
  212. STDMETHODIMP ISubPicQueueImpl::SetSubPicProvider(ISubPicProvider* pSubPicProvider)
  213. {
  214. CAutoLock cAutoLock(&m_csSubPicProvider);
  215. // if(m_pSubPicProvider != pSubPicProvider)
  216. {
  217. m_pSubPicProvider = pSubPicProvider;
  218. Invalidate();
  219. }
  220. return S_OK;
  221. }
  222. STDMETHODIMP ISubPicQueueImpl::GetSubPicProvider(ISubPicProvider** pSubPicProvider)
  223. {
  224. if(!pSubPicProvider)
  225. return E_POINTER;
  226. CAutoLock cAutoLock(&m_csSubPicProvider);
  227. if(m_pSubPicProvider)
  228. (*pSubPicProvider = m_pSubPicProvider)->AddRef();
  229. return !!*pSubPicProvider ? S_OK : E_FAIL;
  230. }
  231. STDMETHODIMP ISubPicQueueImpl::SetFPS(double fps)
  232. {
  233. m_fps = fps;
  234. return S_OK;
  235. }
  236. STDMETHODIMP ISubPicQueueImpl::SetTime(REFERENCE_TIME rtNow)
  237. {
  238. m_rtNow = rtNow;
  239. return S_OK;
  240. }
  241. // private
  242. HRESULT ISubPicQueueImpl::RenderTo(ISubPic* pSubPic, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double fps)
  243. {
  244. HRESULT hr = E_FAIL;
  245. if(!pSubPic)
  246. return hr;
  247. CComPtr<ISubPicProvider> pSubPicProvider;
  248. if(FAILED(GetSubPicProvider(&pSubPicProvider)) || !pSubPicProvider)
  249. return hr;
  250. if(FAILED(pSubPicProvider->Lock()))
  251. return hr;
  252. SubPicDesc spd;
  253. if(SUCCEEDED(pSubPic->ClearDirtyRect(0xFF000000))
  254. && SUCCEEDED(pSubPic->Lock(spd)))
  255. {
  256. CRect r(0,0,0,0);
  257. hr = pSubPicProvider->Render(spd, (rtStart+rtStop)/2, fps, r);
  258. pSubPic->SetStart(rtStart);
  259. pSubPic->SetStop(rtStop);
  260. pSubPic->Unlock(r);
  261. }
  262. pSubPicProvider->Unlock();
  263. return hr;
  264. }
  265. //
  266. // CSubPicQueue
  267. //
  268. CSubPicQueue::CSubPicQueue(int nMaxSubPic, ISubPicAllocator* pAllocator, HRESULT* phr) 
  269. : ISubPicQueueImpl(pAllocator, phr)
  270. , m_nMaxSubPic(nMaxSubPic)
  271. , m_rtQueueStart(0)
  272. {
  273. if(phr && FAILED(*phr))
  274. return;
  275. if(m_nMaxSubPic < 1)
  276. {if(phr) *phr = E_INVALIDARG; return;}
  277. m_fBreakBuffering = false;
  278. for(int i = 0; i < EVENT_COUNT; i++) 
  279. m_ThreadEvents[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
  280. CAMThread::Create();
  281. }
  282. CSubPicQueue::~CSubPicQueue()
  283. {
  284. m_fBreakBuffering = true;
  285. SetEvent(m_ThreadEvents[EVENT_EXIT]);
  286. CAMThread::Close();
  287. for(int i = 0; i < EVENT_COUNT; i++) 
  288. CloseHandle(m_ThreadEvents[i]);
  289. }
  290. // ISubPicQueue
  291. STDMETHODIMP CSubPicQueue::SetFPS(double fps)
  292. {
  293. HRESULT hr = __super::SetFPS(fps);
  294. if(FAILED(hr)) return hr;
  295. SetEvent(m_ThreadEvents[EVENT_TIME]);
  296. return S_OK;
  297. }
  298. STDMETHODIMP CSubPicQueue::SetTime(REFERENCE_TIME rtNow)
  299. {
  300. HRESULT hr = __super::SetTime(rtNow);
  301. if(FAILED(hr)) return hr;
  302. SetEvent(m_ThreadEvents[EVENT_TIME]);
  303. return S_OK;
  304. }
  305. STDMETHODIMP CSubPicQueue::Invalidate(REFERENCE_TIME rtInvalidate)
  306. {
  307. {
  308. // CAutoLock cQueueLock(&m_csQueueLock);
  309. // RemoveAll();
  310. m_rtInvalidate = rtInvalidate;
  311. m_fBreakBuffering = true;
  312. SetEvent(m_ThreadEvents[EVENT_TIME]);
  313. }
  314. return S_OK;
  315. }
  316. STDMETHODIMP_(bool) CSubPicQueue::LookupSubPic(REFERENCE_TIME rtNow, ISubPic** ppSubPic)
  317. {
  318. if(!ppSubPic)
  319. return(false);
  320. *ppSubPic = NULL;
  321. CAutoLock cQueueLock(&m_csQueueLock);
  322. POSITION pos = GetHeadPosition();
  323. while(pos)
  324. {
  325. CComPtr<ISubPic> pSubPic = GetNext(pos);
  326. if(pSubPic->GetStart() <= rtNow && rtNow < pSubPic->GetStop())
  327. {
  328. *ppSubPic = pSubPic.Detach();
  329. break;
  330. }
  331. }
  332. return(!!*ppSubPic);
  333. }
  334. STDMETHODIMP CSubPicQueue::GetStats(int& nSubPics, REFERENCE_TIME& rtNow, REFERENCE_TIME& rtStart, REFERENCE_TIME& rtStop)
  335. {
  336. CAutoLock cQueueLock(&m_csQueueLock);
  337. nSubPics = GetCount();
  338. rtNow = m_rtNow;
  339. rtStart = m_rtQueueStart;
  340. rtStop = GetCount() > 0 ? GetTail()->GetStop() : rtStart;
  341. return S_OK;
  342. }
  343. STDMETHODIMP CSubPicQueue::GetStats(int nSubPic, REFERENCE_TIME& rtStart, REFERENCE_TIME& rtStop)
  344. {
  345. CAutoLock cQueueLock(&m_csQueueLock);
  346. rtStart = rtStop = -1;
  347. if(nSubPic >= 0 && nSubPic < (int)GetCount())
  348. {
  349. if(POSITION pos = FindIndex(nSubPic))
  350. {
  351. rtStart = GetAt(pos)->GetStart();
  352. rtStop = GetAt(pos)->GetStop();
  353. }
  354. }
  355. else
  356. {
  357. return E_INVALIDARG;
  358. }
  359. return S_OK;
  360. }
  361. // private
  362. REFERENCE_TIME CSubPicQueue::UpdateQueue()
  363. {
  364. CAutoLock cQueueLock(&m_csQueueLock);
  365. REFERENCE_TIME rtNow = m_rtNow;
  366. if(rtNow < m_rtQueueStart)
  367. {
  368. RemoveAll();
  369. }
  370. else
  371. {
  372. while(GetCount() > 0 && rtNow >= GetHead()->GetStop())
  373. RemoveHead();
  374. }
  375. m_rtQueueStart = rtNow;
  376. if(GetCount() > 0)
  377. rtNow = GetTail()->GetStop();
  378. return(rtNow);
  379. }
  380. void CSubPicQueue::AppendQueue(ISubPic* pSubPic)
  381. {
  382. CAutoLock cQueueLock(&m_csQueueLock);
  383. AddTail(pSubPic);
  384. }
  385. // overrides
  386. DWORD CSubPicQueue::ThreadProc()
  387. {
  388. SetThreadPriority(m_hThread, THREAD_PRIORITY_LOWEST/*THREAD_PRIORITY_BELOW_NORMAL*/);
  389. while((WaitForMultipleObjects(EVENT_COUNT, m_ThreadEvents, FALSE, INFINITE) - WAIT_OBJECT_0) == EVENT_TIME)
  390. {
  391. double fps = m_fps;
  392. REFERENCE_TIME rtNow = UpdateQueue();
  393. int nMaxSubPic = m_nMaxSubPic;
  394. CComPtr<ISubPicProvider> pSubPicProvider;
  395. if(SUCCEEDED(GetSubPicProvider(&pSubPicProvider)) && pSubPicProvider
  396. && SUCCEEDED(pSubPicProvider->Lock()))
  397. {
  398. for(POSITION pos = pSubPicProvider->GetStartPosition(rtNow, fps); 
  399. pos && !m_fBreakBuffering && GetCount() < (size_t)nMaxSubPic; 
  400. pos = pSubPicProvider->GetNext(pos))
  401. {
  402. REFERENCE_TIME rtStart = pSubPicProvider->GetStart(pos, fps);
  403. REFERENCE_TIME rtStop = pSubPicProvider->GetStop(pos, fps);
  404. if(m_rtNow >= rtStart)
  405. {
  406. // m_fBufferUnderrun = true;
  407. if(m_rtNow >= rtStop) continue;
  408. }
  409. if(rtStart >= m_rtNow + 60*10000000i64) // we are already one minute ahead, this should be enough
  410. break;
  411. if(rtNow < rtStop)
  412. {
  413. CComPtr<ISubPic> pStatic;
  414. if(FAILED(m_pAllocator->GetStatic(&pStatic)))
  415. break;
  416. HRESULT hr = RenderTo(pStatic, rtStart, rtStop, fps);
  417. if(FAILED(hr))
  418. break;
  419. if(S_OK != hr) // subpic was probably empty
  420. continue;
  421. CComPtr<ISubPic> pDynamic;
  422. if(FAILED(m_pAllocator->AllocDynamic(&pDynamic))
  423. || FAILED(pStatic->CopyTo(pDynamic)))
  424. break;
  425. AppendQueue(pDynamic);
  426. }
  427. }
  428. pSubPicProvider->Unlock();
  429. }
  430. if(m_fBreakBuffering)
  431. {
  432. CAutoLock cQueueLock(&m_csQueueLock);
  433. REFERENCE_TIME rtInvalidate = m_rtInvalidate;
  434. while(GetCount() && GetTail()->GetStop() > rtInvalidate)
  435. {
  436. if(GetTail()->GetStart() < rtInvalidate)
  437. GetTail()->SetStop(rtInvalidate);
  438. else
  439. RemoveTail();
  440. }
  441. m_fBreakBuffering = false;
  442. }
  443. }
  444. return(0);
  445. }
  446. //
  447. // CSubPicQueueNoThread
  448. //
  449. CSubPicQueueNoThread::CSubPicQueueNoThread(ISubPicAllocator* pAllocator, HRESULT* phr) 
  450. : ISubPicQueueImpl(pAllocator, phr)
  451. {
  452. }
  453. CSubPicQueueNoThread::~CSubPicQueueNoThread()
  454. {
  455. }
  456. // ISubPicQueue
  457. STDMETHODIMP CSubPicQueueNoThread::Invalidate(REFERENCE_TIME rtInvalidate)
  458. {
  459. CAutoLock cQueueLock(&m_csLock);
  460. m_pSubPic = NULL;
  461. return S_OK;
  462. }
  463. STDMETHODIMP_(bool) CSubPicQueueNoThread::LookupSubPic(REFERENCE_TIME rtNow, ISubPic** ppSubPic)
  464. {
  465. if(!ppSubPic)
  466. return(false);
  467. *ppSubPic = NULL;
  468. CComPtr<ISubPic> pSubPic;
  469. {
  470. CAutoLock cAutoLock(&m_csLock);
  471. if(!m_pSubPic)
  472. {
  473. if(FAILED(m_pAllocator->AllocDynamic(&m_pSubPic)))
  474. return(false);
  475. }
  476. pSubPic = m_pSubPic;
  477. }
  478. if(pSubPic->GetStart() <= rtNow && rtNow < pSubPic->GetStop())
  479. {
  480. (*ppSubPic = pSubPic)->AddRef();
  481. }
  482. else
  483. {
  484. CComPtr<ISubPicProvider> pSubPicProvider;
  485. if(SUCCEEDED(GetSubPicProvider(&pSubPicProvider)) && pSubPicProvider
  486. && SUCCEEDED(pSubPicProvider->Lock()))
  487. {
  488. double fps = m_fps;
  489. if(POSITION pos = pSubPicProvider->GetStartPosition(rtNow, fps))
  490. {
  491. REFERENCE_TIME rtStart = pSubPicProvider->GetStart(pos, fps);
  492. REFERENCE_TIME rtStop = pSubPicProvider->GetStop(pos, fps);
  493. if(pSubPicProvider->IsAnimated(pos))
  494. {
  495. rtStart = rtNow;
  496. rtStop = rtNow+1;
  497. }
  498. if(rtStart <= rtNow && rtNow < rtStop)
  499. {
  500. if(m_pAllocator->IsDynamicWriteOnly())
  501. {
  502. CComPtr<ISubPic> pStatic;
  503. if(SUCCEEDED(m_pAllocator->GetStatic(&pStatic))
  504. && SUCCEEDED(RenderTo(pStatic, rtStart, rtStop, fps))
  505. && SUCCEEDED(pStatic->CopyTo(pSubPic)))
  506. (*ppSubPic = pSubPic)->AddRef();
  507. }
  508. else
  509. {
  510. if(SUCCEEDED(RenderTo(m_pSubPic, rtStart, rtStop, fps)))
  511. (*ppSubPic = pSubPic)->AddRef();
  512. }
  513. }
  514. }
  515. pSubPicProvider->Unlock();
  516. if(*ppSubPic)
  517. {
  518. CAutoLock cAutoLock(&m_csLock);
  519. m_pSubPic = *ppSubPic;
  520. }
  521. }
  522. }
  523. return(!!*ppSubPic);
  524. }
  525. STDMETHODIMP CSubPicQueueNoThread::GetStats(int& nSubPics, REFERENCE_TIME& rtNow, REFERENCE_TIME& rtStart, REFERENCE_TIME& rtStop)
  526. {
  527. CAutoLock cAutoLock(&m_csLock);
  528. nSubPics = 0;
  529. rtNow = m_rtNow;
  530. rtStart = rtStop = 0;
  531. if(m_pSubPic)
  532. {
  533. nSubPics = 1;
  534. rtStart = m_pSubPic->GetStart();
  535. rtStop = m_pSubPic->GetStop();
  536. }
  537. return S_OK;
  538. }
  539. STDMETHODIMP CSubPicQueueNoThread::GetStats(int nSubPic, REFERENCE_TIME& rtStart, REFERENCE_TIME& rtStop)
  540. {
  541. CAutoLock cAutoLock(&m_csLock);
  542. if(!m_pSubPic || nSubPic != 0)
  543. return E_INVALIDARG;
  544. rtStart = m_pSubPic->GetStart();
  545. rtStop = m_pSubPic->GetStop();
  546. return S_OK;
  547. }
  548. //
  549. // ISubPicAllocatorPresenterImpl
  550. //
  551. ISubPicAllocatorPresenterImpl::ISubPicAllocatorPresenterImpl(HWND hWnd)
  552. : CUnknown(NAME("ISubPicAllocatorPresenterImpl"), NULL)
  553. , m_hWnd(hWnd)
  554. , m_NativeVideoSize(0, 0), m_AspectRatio(0, 0)
  555. , m_VideoRect(0, 0, 0, 0), m_WindowRect(0, 0, 0, 0)
  556. , m_fps(25.0)
  557. {
  558. SetVideoAngle(Vector(), false);
  559. }
  560. ISubPicAllocatorPresenterImpl::~ISubPicAllocatorPresenterImpl()
  561. {
  562. }
  563. STDMETHODIMP ISubPicAllocatorPresenterImpl::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  564. {
  565. return 
  566. QI(ISubPicAllocatorPresenter)
  567. __super::NonDelegatingQueryInterface(riid, ppv);
  568. }
  569. void ISubPicAllocatorPresenterImpl::AlphaBltSubPic(CSize size, SubPicDesc* pTarget)
  570. {
  571. CComPtr<ISubPic> pSubPic;
  572. if(m_pSubPicQueue->LookupSubPic(m_rtNow, &pSubPic))
  573. {
  574. SubPicDesc spd;
  575. pSubPic->GetDesc(spd);
  576. CRect r;
  577. pSubPic->GetDirtyRect(r);
  578. // FIXME
  579. r.DeflateRect(1, 1);
  580. CRect rDstText(
  581. r.left * size.cx / spd.w,
  582. r.top * size.cy / spd.h,
  583. r.right * size.cx / spd.w,
  584. r.bottom * size.cy / spd.h);
  585. pSubPic->AlphaBlt(r, rDstText, pTarget);
  586. }
  587. }
  588. // ISubPicAllocatorPresenter
  589. STDMETHODIMP_(SIZE) ISubPicAllocatorPresenterImpl::GetVideoSize(bool fCorrectAR)
  590. {
  591. CSize VideoSize(m_NativeVideoSize);
  592. if(fCorrectAR && m_AspectRatio.cx > 0 && m_AspectRatio.cy > 0)
  593. VideoSize.cx = VideoSize.cy*m_AspectRatio.cx/m_AspectRatio.cy;
  594. return(VideoSize);
  595. }
  596. STDMETHODIMP_(void) ISubPicAllocatorPresenterImpl::SetPosition(RECT w, RECT v)
  597. {
  598. bool fWindowPosChanged = !!(m_WindowRect != w);
  599. bool fWindowSizeChanged = !!(m_WindowRect.Size() != CRect(w).Size());
  600. m_WindowRect = w;
  601. bool fVideoRectChanged = !!(m_VideoRect != v);
  602. m_VideoRect = v;
  603. if(fWindowSizeChanged || fVideoRectChanged)
  604. {
  605. if(m_pAllocator)
  606. {
  607. m_pAllocator->SetCurSize(m_WindowRect.Size());
  608. m_pAllocator->SetCurVidRect(m_VideoRect);
  609. }
  610. if(m_pSubPicQueue)
  611. {
  612. m_pSubPicQueue->Invalidate();
  613. }
  614. }
  615. if(fWindowPosChanged || fVideoRectChanged)
  616. Paint(fWindowSizeChanged || fVideoRectChanged);
  617. }
  618. STDMETHODIMP_(void) ISubPicAllocatorPresenterImpl::SetTime(REFERENCE_TIME rtNow)
  619. {
  620. m_rtNow = rtNow;
  621. if(m_pSubPicQueue)
  622. {
  623. m_pSubPicQueue->SetTime(rtNow);
  624. }
  625. }
  626. STDMETHODIMP_(double) ISubPicAllocatorPresenterImpl::GetFPS()
  627. {
  628. return(m_fps);
  629. }
  630. STDMETHODIMP_(void) ISubPicAllocatorPresenterImpl::SetSubPicProvider(ISubPicProvider* pSubPicProvider)
  631. {
  632. // CComPtr will make sure it gets destroyed even if it was passed 
  633. // here with 0 refcnt and m_pSubPicQueue->SetSubPicProvider fails 
  634. // to accept it.
  635. CComPtr<ISubPicProvider> pSPP = pSubPicProvider;
  636. if(m_pSubPicQueue)
  637. m_pSubPicQueue->SetSubPicProvider(pSPP); // pSPP == NULL is ok, we use it to empty the provider
  638. }
  639. STDMETHODIMP_(void) ISubPicAllocatorPresenterImpl::Invalidate(REFERENCE_TIME rtInvalidate)
  640. {
  641. if(m_pSubPicQueue)
  642. m_pSubPicQueue->Invalidate(rtInvalidate);
  643. }
  644. #include <math.h>
  645. void ISubPicAllocatorPresenterImpl::Transform(CRect r, Vector v[4])
  646. {
  647. v[0] = Vector(r.left, r.top, 0);
  648. v[1] = Vector(r.right, r.top, 0);
  649. v[2] = Vector(r.left, r.bottom, 0);
  650. v[3] = Vector(r.right, r.bottom, 0);
  651. Vector center(r.CenterPoint().x, r.CenterPoint().y, 0);
  652. int l = (int)(Vector(r.Size().cx, r.Size().cy, 0).Length()*1.5f)+1;
  653. for(int i = 0; i < 4; i++)
  654. {
  655. v[i] = m_xform << (v[i] - center);
  656. v[i].z = v[i].z / l + 0.5f;
  657. v[i].x /= v[i].z*2;
  658. v[i].y /= v[i].z*2;
  659. v[i] += center;
  660. }
  661. }
  662. STDMETHODIMP ISubPicAllocatorPresenterImpl::SetVideoAngle(Vector v, bool fRepaint)
  663. {
  664. m_xform = XForm(Ray(Vector(0, 0, 0), v), Vector(1, 1, 1), false);
  665. if(fRepaint) Paint(true);
  666. return S_OK;
  667. }