Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

487 lines
11 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. bgvideo.cpp
  5. Abstract:
  6. Implementation of the Video bridge filters.
  7. Author:
  8. Mu Han (muhan) 11/16/1998
  9. --*/
  10. #include "stdafx.h"
  11. CTAPIVideoBridgeSinkFilter::CTAPIVideoBridgeSinkFilter(
  12. IN LPUNKNOWN pUnk,
  13. IN IDataBridge * pIDataBridge,
  14. OUT HRESULT * phr
  15. )
  16. : CTAPIBridgeSinkFilter(pUnk, pIDataBridge, phr)
  17. {
  18. }
  19. HRESULT CTAPIVideoBridgeSinkFilter::CreateInstance(
  20. IN IDataBridge * pIDataBridge,
  21. OUT IBaseFilter ** ppIBaseFilter
  22. )
  23. /*++
  24. Routine Description:
  25. This method create a instance of the bridge's sink filter.
  26. Arguments:
  27. ppIBaseFilter - the returned filter interface pointer.
  28. Return Value:
  29. E_OUTOFMEMORY - no memory for the new object.
  30. --*/
  31. {
  32. ENTER_FUNCTION("CTAPIVideoBridgeSinkFilter::CreateInstance");
  33. BGLOG((BG_TRACE, "%s entered.", __fxName));
  34. HRESULT hr = S_OK;
  35. CUnknown* pUnknown = new CTAPIVideoBridgeSinkFilter(NULL, pIDataBridge, &hr);
  36. if (pUnknown == NULL)
  37. {
  38. hr = E_OUTOFMEMORY;
  39. DbgLog((LOG_ERROR, 0,
  40. "%s, out of memory creating the filter",
  41. __fxName));
  42. }
  43. else if (FAILED(hr))
  44. {
  45. DbgLog((LOG_ERROR, 0,
  46. "%s, the filter's constructor failed, hr:%d",
  47. __fxName, hr));
  48. delete pUnknown;
  49. }
  50. else
  51. {
  52. pUnknown->NonDelegatingAddRef();
  53. hr = pUnknown->NonDelegatingQueryInterface(
  54. __uuidof(IBaseFilter), (void **)ppIBaseFilter
  55. );
  56. pUnknown->NonDelegatingRelease();
  57. }
  58. BGLOG((BG_TRACE,
  59. "%s, returning:%p, hr:%x", __fxName, *ppIBaseFilter, hr));
  60. return hr;
  61. }
  62. HRESULT CTAPIVideoBridgeSinkFilter::GetMediaType(
  63. IN int iPosition,
  64. OUT CMediaType *pMediaType
  65. )
  66. /*++
  67. Routine Description:
  68. Get the media type that this filter wants to support. Currently we
  69. only support RTP H263 data.
  70. Arguments:
  71. IN int iPosition,
  72. the index of the media type, zero based..
  73. In CMediaType *pMediaType
  74. Pointer to a CMediaType object to save the returned media type.
  75. Return Value:
  76. S_OK - success
  77. E_OUTOFMEMORY - no memory
  78. --*/
  79. {
  80. ENTER_FUNCTION("CTAPIVideoBridgeSinkFilter::GetMediaType");
  81. BGLOG((BG_TRACE,
  82. "%s, iPosition:%d, pMediaType:%p",
  83. __fxName, iPosition, pMediaType));
  84. ASSERT(!IsBadWritePtr(pMediaType, sizeof(AM_MEDIA_TYPE)));
  85. HRESULT hr;
  86. if (iPosition == 0)
  87. {
  88. pMediaType->majortype = __uuidof(MEDIATYPE_RTP_Single_Stream);
  89. pMediaType->subtype = GUID_NULL;
  90. hr = S_OK;
  91. }
  92. else
  93. {
  94. hr = VFW_S_NO_MORE_ITEMS;
  95. }
  96. BGLOG((BG_TRACE, "%s returns %d", __fxName, hr));
  97. return hr;
  98. }
  99. HRESULT CTAPIVideoBridgeSinkFilter::CheckMediaType(
  100. const CMediaType *pMediaType
  101. )
  102. /*++
  103. Routine Description:
  104. Check the media type that this filter wants to support. Currently we
  105. only support RTP H263 data.
  106. Arguments:
  107. In CMediaType *pMediaType
  108. Pointer to a CMediaType object to save the returned media type.
  109. Return Value:
  110. S_OK - success
  111. E_OUTOFMEMORY - no memory
  112. VFW_E_TYPE_NOT_ACCEPTED - media type rejected
  113. VFW_E_INVALIDMEDIATYPE - bad media type
  114. --*/
  115. {
  116. ENTER_FUNCTION("CTAPIVideoBridgeSinkFilter::CheckMediaType");
  117. BGLOG((BG_TRACE,
  118. "%s, pMediaType:%p", __fxName, pMediaType));
  119. ASSERT(!IsBadReadPtr(pMediaType, sizeof(AM_MEDIA_TYPE)));
  120. // H.263 is not published, ignore checking here
  121. HRESULT hr = S_OK;
  122. BGLOG((BG_TRACE, "%s returns %d", __fxName, hr));
  123. return hr;
  124. }
  125. CTAPIVideoBridgeSourceFilter::CTAPIVideoBridgeSourceFilter(
  126. IN LPUNKNOWN pUnk,
  127. OUT HRESULT * phr
  128. )
  129. : CTAPIBridgeSourceFilter(pUnk, phr),
  130. m_dwSSRC(0),
  131. m_lWaitTimer(I_FRAME_TIMER),
  132. m_fWaitForIFrame(FALSE)
  133. {
  134. }
  135. HRESULT CTAPIVideoBridgeSourceFilter::CreateInstance(
  136. OUT IBaseFilter ** ppIBaseFilter
  137. )
  138. /*++
  139. Routine Description:
  140. This method create a instance of the bridge's sink filter.
  141. Arguments:
  142. ppIBaseFilter - the returned filter interface pointer.
  143. Return Value:
  144. E_OUTOFMEMORY - no memory for the new object.
  145. --*/
  146. {
  147. ENTER_FUNCTION("CTAPIVideoBridgeSourceFilter::CreateInstance");
  148. BGLOG((BG_TRACE, "%s entered.", __fxName));
  149. HRESULT hr = S_OK;
  150. CUnknown* pUnknown = new CTAPIVideoBridgeSourceFilter(NULL, &hr);
  151. if (pUnknown == NULL)
  152. {
  153. hr = E_OUTOFMEMORY;
  154. DbgLog((LOG_ERROR, 0,
  155. "%s, out of memory creating the filter",
  156. __fxName));
  157. }
  158. else if (FAILED(hr))
  159. {
  160. DbgLog((LOG_ERROR, 0,
  161. "%s, the filter's constructor failed, hr:%d",
  162. __fxName, hr));
  163. delete pUnknown;
  164. }
  165. else
  166. {
  167. pUnknown->NonDelegatingAddRef();
  168. hr = pUnknown->NonDelegatingQueryInterface(
  169. __uuidof(IBaseFilter), (void **)ppIBaseFilter
  170. );
  171. pUnknown->NonDelegatingRelease();
  172. }
  173. BGLOG((BG_TRACE,
  174. "%s, returning:%p, hr:%x", __fxName, *ppIBaseFilter, hr));
  175. return hr;
  176. }
  177. HRESULT CTAPIVideoBridgeSourceFilter::GetMediaType(
  178. IN int iPosition,
  179. OUT CMediaType *pMediaType
  180. )
  181. /*++
  182. Routine Description:
  183. Get the media type that this filter wants to support. Currently we
  184. only support RTP H263 data.
  185. Arguments:
  186. IN int iPosition,
  187. the index of the media type, zero based..
  188. In CMediaType *pMediaType
  189. Pointer to a CMediaType object to save the returned media type.
  190. Return Value:
  191. S_OK - success
  192. E_OUTOFMEMORY - no memory
  193. --*/
  194. {
  195. ENTER_FUNCTION("CTAPIVideoBridgeSourceFilter::GetMediaType");
  196. BGLOG((BG_TRACE,
  197. "%s, iPosition:%d, pMediaType:%p",
  198. __fxName, iPosition, pMediaType));
  199. ASSERT(!IsBadWritePtr(pMediaType, sizeof(AM_MEDIA_TYPE)));
  200. HRESULT hr;
  201. if (iPosition == 0)
  202. {
  203. pMediaType->majortype = __uuidof(MEDIATYPE_RTP_Single_Stream);
  204. pMediaType->subtype = GUID_NULL;
  205. hr = S_OK;
  206. }
  207. else
  208. {
  209. hr = VFW_S_NO_MORE_ITEMS;
  210. }
  211. BGLOG((BG_TRACE, "%s returns %d", __fxName, hr));
  212. return hr;
  213. }
  214. HRESULT CTAPIVideoBridgeSourceFilter::CheckMediaType(
  215. const CMediaType *pMediaType
  216. )
  217. /*++
  218. Routine Description:
  219. Check the media type that this filter wants to support. Currently we
  220. only support RTP H263 data.
  221. Arguments:
  222. In CMediaType *pMediaType
  223. Pointer to a CMediaType object to save the returned media type.
  224. Return Value:
  225. S_OK - success
  226. E_OUTOFMEMORY - no memory
  227. VFW_E_TYPE_NOT_ACCEPTED - media type rejected
  228. VFW_E_INVALIDMEDIATYPE - bad media type
  229. --*/
  230. {
  231. ENTER_FUNCTION("CTAPIVideoBridgeSourceFilter::CheckMediaType");
  232. BGLOG((BG_TRACE,
  233. "%s, pMediaType:%p", __fxName, pMediaType));
  234. ASSERT(!IsBadReadPtr(pMediaType, sizeof(AM_MEDIA_TYPE)));
  235. // media type H.263 is not published, ignore checking
  236. HRESULT hr = S_OK;
  237. BGLOG((BG_TRACE, "%s returns %d", __fxName, hr));
  238. return hr;
  239. }
  240. BOOL IsIFrame(IN const BYTE * pPacket, IN long lPacketLength)
  241. {
  242. BYTE *pH263PayloadHeader = (BYTE*)(pPacket + sizeof(RTP_HEADER));
  243. // Header in mode A
  244. // 0 1 2 3
  245. // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  246. //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  247. //|F|P|SBIT |EBIT | SRC | R |I|A|S|DBQ| TRB | TR |
  248. //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  249. // If I is 1, it is a key frame.
  250. return (BOOL)(pH263PayloadHeader[2] & 0x80);
  251. }
  252. STDMETHODIMP CTAPIVideoBridgeSourceFilter::Run(REFERENCE_TIME tStart)
  253. /*++
  254. Routine Description:
  255. start the filter
  256. Arguments:
  257. Nothing.
  258. Return Value:
  259. S_OK.
  260. --*/
  261. {
  262. m_dwSSRC = 0;
  263. m_fWaitForIFrame = FALSE;
  264. m_lWaitTimer = 0;
  265. return CBaseFilter::Run(tStart);
  266. }
  267. HRESULT CTAPIVideoBridgeSourceFilter::SendSample(
  268. IN IMediaSample *pSample
  269. )
  270. /*++
  271. Routine Description:
  272. Process a sample from the bridge sink filter. We need to look for I-frames
  273. when the SSRC changes.
  274. Arguments:
  275. pSample - The media sample object. Assumption: it has to contain an RTP
  276. packet that has H.263 data in it.
  277. Return Value:
  278. HRESULT.
  279. --*/
  280. {
  281. ENTER_FUNCTION("CTAPIVideoBridgeSourceFilter::SendSample");
  282. CAutoLock Lock(m_pLock);
  283. // we don't deliver anything if the filter is not in running state.
  284. if (m_State != State_Running)
  285. {
  286. return S_OK;
  287. }
  288. ASSERT(pSample != NULL);
  289. BYTE *pPacket;
  290. HRESULT hr;
  291. if (FAILED (hr = pSample->GetPointer (&pPacket)))
  292. {
  293. BGLOG ((BG_ERROR, "%s failed to get buffer pointer from input sample %p",
  294. __fxName, pSample));
  295. return hr;
  296. }
  297. long lPacketSize = pSample->GetActualDataLength();
  298. const long H263PayloadHeaderLength = 4;
  299. if (lPacketSize < sizeof(RTP_HEADER) + H263PayloadHeaderLength)
  300. {
  301. BGLOG ((BG_ERROR, "%s get a bad RTP packet %p",
  302. __fxName, pSample));
  303. return E_UNEXPECTED;
  304. }
  305. RTP_HEADER *pRTPHeader = (RTP_HEADER *)pPacket;
  306. if (m_dwSSRC == 0)
  307. {
  308. m_dwSSRC = pRTPHeader->dwSSRC;
  309. }
  310. else if (m_dwSSRC != pRTPHeader->dwSSRC)
  311. {
  312. m_dwSSRC = pRTPHeader->dwSSRC;
  313. BGLOG ((BG_TRACE, "%s new SSRC detected", __fxName, m_dwSSRC));
  314. // the source changed, we need to wait for an I-frame
  315. if (IsIFrame(pPacket, lPacketSize))
  316. {
  317. // we got an I-Frame
  318. m_fWaitForIFrame = FALSE;
  319. BGLOG ((BG_TRACE, "%s switched to %x", __fxName, m_dwSSRC));
  320. }
  321. else
  322. {
  323. m_fWaitForIFrame = TRUE;
  324. m_lWaitTimer = I_FRAME_TIMER;
  325. // discard the frame.
  326. return S_FALSE;
  327. }
  328. }
  329. else if (m_fWaitForIFrame)
  330. {
  331. if (IsIFrame(pPacket, lPacketSize))
  332. {
  333. // we got an I-Frame
  334. m_fWaitForIFrame = FALSE;
  335. BGLOG ((BG_TRACE, "%s switched to %x", __fxName, m_dwSSRC));
  336. }
  337. else
  338. {
  339. // this is not an I frame,
  340. m_lWaitTimer --;
  341. if (m_lWaitTimer > 0)
  342. {
  343. // discard the frame.
  344. return S_FALSE;
  345. }
  346. BGLOG ((BG_TRACE, "%s switched to because of timeout %x",
  347. __fxName, m_dwSSRC));
  348. }
  349. }
  350. _ASSERT(m_pOutputPin != NULL);
  351. return m_pOutputPin->Deliver(pSample);
  352. }