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.

468 lines
17 KiB

  1. //------------------------------------------------------------------------------
  2. // File: Vtrans.cpp
  3. //
  4. // Desc: DirectShow base classes.
  5. //
  6. // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
  7. //------------------------------------------------------------------------------
  8. #include <streams.h>
  9. #include <measure.h>
  10. // #include <vtransfr.h> // now in precomp file streams.h
  11. CVideoTransformFilter::CVideoTransformFilter
  12. ( TCHAR *pName, LPUNKNOWN pUnk, REFCLSID clsid)
  13. : CTransformFilter(pName, pUnk, clsid)
  14. , m_itrLate(0)
  15. , m_nKeyFramePeriod(0) // No QM until we see at least 2 key frames
  16. , m_nFramesSinceKeyFrame(0)
  17. , m_bSkipping(FALSE)
  18. , m_tDecodeStart(0)
  19. , m_itrAvgDecode(300000) // 30mSec - probably allows skipping
  20. , m_bQualityChanged(FALSE)
  21. {
  22. #ifdef PERF
  23. RegisterPerfId();
  24. #endif // PERF
  25. }
  26. CVideoTransformFilter::~CVideoTransformFilter()
  27. {
  28. // nothing to do
  29. }
  30. // Reset our quality management state
  31. HRESULT CVideoTransformFilter::StartStreaming()
  32. {
  33. m_itrLate = 0;
  34. m_nKeyFramePeriod = 0; // No QM until we see at least 2 key frames
  35. m_nFramesSinceKeyFrame = 0;
  36. m_bSkipping = FALSE;
  37. m_tDecodeStart = 0;
  38. m_itrAvgDecode = 300000; // 30mSec - probably allows skipping
  39. m_bQualityChanged = FALSE;
  40. m_bSampleSkipped = FALSE;
  41. return NOERROR;
  42. }
  43. // Overriden to reset quality management information
  44. HRESULT CVideoTransformFilter::EndFlush()
  45. {
  46. {
  47. // Synchronize
  48. CAutoLock lck(&m_csReceive);
  49. // Reset our stats
  50. //
  51. // Note - we don't want to call derived classes here,
  52. // we only want to reset our internal variables and this
  53. // is a convenient way to do it
  54. CVideoTransformFilter::StartStreaming();
  55. }
  56. return CTransformFilter::EndFlush();
  57. }
  58. HRESULT CVideoTransformFilter::AbortPlayback(HRESULT hr)
  59. {
  60. NotifyEvent(EC_ERRORABORT, hr, 0);
  61. m_pOutput->DeliverEndOfStream();
  62. return hr;
  63. }
  64. // Receive()
  65. //
  66. // Accept a sample from upstream, decide whether to process it
  67. // or drop it. If we process it then get a buffer from the
  68. // allocator of the downstream connection, transform it into the
  69. // new buffer and deliver it to the downstream filter.
  70. // If we decide not to process it then we do not get a buffer.
  71. // Remember that although this code will notice format changes coming into
  72. // the input pin, it will NOT change its output format if that results
  73. // in the filter needing to make a corresponding output format change. Your
  74. // derived filter will have to take care of that. (eg. a palette change if
  75. // the input and output is an 8 bit format). If the input sample is discarded
  76. // and nothing is sent out for this Receive, please remember to put the format
  77. // change on the first output sample that you actually do send.
  78. // If your filter will produce the same output type even when the input type
  79. // changes, then this base class code will do everything you need.
  80. HRESULT CVideoTransformFilter::Receive(IMediaSample *pSample)
  81. {
  82. // If the next filter downstream is the video renderer, then it may
  83. // be able to operate in DirectDraw mode which saves copying the data
  84. // and gives higher performance. In that case the buffer which we
  85. // get from GetDeliveryBuffer will be a DirectDraw buffer, and
  86. // drawing into this buffer draws directly onto the display surface.
  87. // This means that any waiting for the correct time to draw occurs
  88. // during GetDeliveryBuffer, and that once the buffer is given to us
  89. // the video renderer will count it in its statistics as a frame drawn.
  90. // This means that any decision to drop the frame must be taken before
  91. // calling GetDeliveryBuffer.
  92. ASSERT(CritCheckIn(&m_csReceive));
  93. AM_MEDIA_TYPE *pmtOut, *pmt;
  94. #ifdef DEBUG
  95. FOURCCMap fccOut;
  96. #endif
  97. HRESULT hr;
  98. ASSERT(pSample);
  99. IMediaSample * pOutSample;
  100. // If no output pin to deliver to then no point sending us data
  101. ASSERT (m_pOutput != NULL) ;
  102. // The source filter may dynamically ask us to start transforming from a
  103. // different media type than the one we're using now. If we don't, we'll
  104. // draw garbage. (typically, this is a palette change in the movie,
  105. // but could be something more sinister like the compression type changing,
  106. // or even the video size changing)
  107. #define rcS1 ((VIDEOINFOHEADER *)(pmt->pbFormat))->rcSource
  108. #define rcT1 ((VIDEOINFOHEADER *)(pmt->pbFormat))->rcTarget
  109. pSample->GetMediaType(&pmt);
  110. if (pmt != NULL && pmt->pbFormat != NULL) {
  111. // spew some debug output
  112. ASSERT(!IsEqualGUID(pmt->majortype, GUID_NULL));
  113. #ifdef DEBUG
  114. fccOut.SetFOURCC(&pmt->subtype);
  115. LONG lCompression = HEADER(pmt->pbFormat)->biCompression;
  116. LONG lBitCount = HEADER(pmt->pbFormat)->biBitCount;
  117. LONG lStride = (HEADER(pmt->pbFormat)->biWidth * lBitCount + 7) / 8;
  118. lStride = (lStride + 3) & ~3;
  119. DbgLog((LOG_TRACE,3,TEXT("*Changing input type on the fly to")));
  120. DbgLog((LOG_TRACE,3,TEXT("FourCC: %lx Compression: %lx BitCount: %ld"),
  121. fccOut.GetFOURCC(), lCompression, lBitCount));
  122. DbgLog((LOG_TRACE,3,TEXT("biHeight: %ld rcDst: (%ld, %ld, %ld, %ld)"),
  123. HEADER(pmt->pbFormat)->biHeight,
  124. rcT1.left, rcT1.top, rcT1.right, rcT1.bottom));
  125. DbgLog((LOG_TRACE,3,TEXT("rcSrc: (%ld, %ld, %ld, %ld) Stride: %ld"),
  126. rcS1.left, rcS1.top, rcS1.right, rcS1.bottom,
  127. lStride));
  128. #endif
  129. // now switch to using the new format. I am assuming that the
  130. // derived filter will do the right thing when its media type is
  131. // switched and streaming is restarted.
  132. StopStreaming();
  133. m_pInput->CurrentMediaType() = *pmt;
  134. DeleteMediaType(pmt);
  135. // if this fails, playback will stop, so signal an error
  136. hr = StartStreaming();
  137. if (FAILED(hr)) {
  138. return AbortPlayback(hr);
  139. }
  140. }
  141. // Now that we have noticed any format changes on the input sample, it's
  142. // OK to discard it.
  143. if (ShouldSkipFrame(pSample)) {
  144. MSR_NOTE(m_idSkip);
  145. m_bSampleSkipped = TRUE;
  146. return NOERROR;
  147. }
  148. // Set up the output sample
  149. hr = InitializeOutputSample(pSample, &pOutSample);
  150. if (FAILED(hr)) {
  151. return hr;
  152. }
  153. m_bSampleSkipped = FALSE;
  154. // The renderer may ask us to on-the-fly to start transforming to a
  155. // different format. If we don't obey it, we'll draw garbage
  156. #define rcS ((VIDEOINFOHEADER *)(pmtOut->pbFormat))->rcSource
  157. #define rcT ((VIDEOINFOHEADER *)(pmtOut->pbFormat))->rcTarget
  158. pOutSample->GetMediaType(&pmtOut);
  159. if (pmtOut != NULL && pmtOut->pbFormat != NULL) {
  160. // spew some debug output
  161. ASSERT(!IsEqualGUID(pmtOut->majortype, GUID_NULL));
  162. #ifdef DEBUG
  163. fccOut.SetFOURCC(&pmtOut->subtype);
  164. LONG lCompression = HEADER(pmtOut->pbFormat)->biCompression;
  165. LONG lBitCount = HEADER(pmtOut->pbFormat)->biBitCount;
  166. LONG lStride = (HEADER(pmtOut->pbFormat)->biWidth * lBitCount + 7) / 8;
  167. lStride = (lStride + 3) & ~3;
  168. DbgLog((LOG_TRACE,3,TEXT("*Changing output type on the fly to")));
  169. DbgLog((LOG_TRACE,3,TEXT("FourCC: %lx Compression: %lx BitCount: %ld"),
  170. fccOut.GetFOURCC(), lCompression, lBitCount));
  171. DbgLog((LOG_TRACE,3,TEXT("biHeight: %ld rcDst: (%ld, %ld, %ld, %ld)"),
  172. HEADER(pmtOut->pbFormat)->biHeight,
  173. rcT.left, rcT.top, rcT.right, rcT.bottom));
  174. DbgLog((LOG_TRACE,3,TEXT("rcSrc: (%ld, %ld, %ld, %ld) Stride: %ld"),
  175. rcS.left, rcS.top, rcS.right, rcS.bottom,
  176. lStride));
  177. #endif
  178. // now switch to using the new format. I am assuming that the
  179. // derived filter will do the right thing when its media type is
  180. // switched and streaming is restarted.
  181. StopStreaming();
  182. m_pOutput->CurrentMediaType() = *pmtOut;
  183. DeleteMediaType(pmtOut);
  184. hr = StartStreaming();
  185. if (SUCCEEDED(hr)) {
  186. // a new format, means a new empty buffer, so wait for a keyframe
  187. // before passing anything on to the renderer.
  188. // !!! a keyframe may never come, so give up after 30 frames
  189. DbgLog((LOG_TRACE,3,TEXT("Output format change means we must wait for a keyframe")));
  190. m_nWaitForKey = 30;
  191. // if this fails, playback will stop, so signal an error
  192. } else {
  193. // Must release the sample before calling AbortPlayback
  194. // because we might be holding the win16 lock or
  195. // ddraw lock
  196. pOutSample->Release();
  197. AbortPlayback(hr);
  198. return hr;
  199. }
  200. }
  201. // After a discontinuity, we need to wait for the next key frame
  202. if (pSample->IsDiscontinuity() == S_OK) {
  203. DbgLog((LOG_TRACE,3,TEXT("Non-key discontinuity - wait for keyframe")));
  204. m_nWaitForKey = 30;
  205. }
  206. // Start timing the transform (and log it if PERF is defined)
  207. if (SUCCEEDED(hr)) {
  208. m_tDecodeStart = timeGetTime();
  209. MSR_START(m_idTransform);
  210. // have the derived class transform the data
  211. hr = Transform(pSample, pOutSample);
  212. // Stop the clock (and log it if PERF is defined)
  213. MSR_STOP(m_idTransform);
  214. m_tDecodeStart = timeGetTime()-m_tDecodeStart;
  215. m_itrAvgDecode = m_tDecodeStart*(10000/16) + 15*(m_itrAvgDecode/16);
  216. // Maybe we're waiting for a keyframe still?
  217. if (m_nWaitForKey)
  218. m_nWaitForKey--;
  219. if (m_nWaitForKey && pSample->IsSyncPoint() == S_OK)
  220. m_nWaitForKey = FALSE;
  221. // if so, then we don't want to pass this on to the renderer
  222. if (m_nWaitForKey && hr == NOERROR) {
  223. DbgLog((LOG_TRACE,3,TEXT("still waiting for a keyframe")));
  224. hr = S_FALSE;
  225. }
  226. }
  227. if (FAILED(hr)) {
  228. DbgLog((LOG_TRACE,1,TEXT("Error from video transform")));
  229. } else {
  230. // the Transform() function can return S_FALSE to indicate that the
  231. // sample should not be delivered; we only deliver the sample if it's
  232. // really S_OK (same as NOERROR, of course.)
  233. // Try not to return S_FALSE to a direct draw buffer (it's wasteful)
  234. // Try to take the decision earlier - before you get it.
  235. if (hr == NOERROR) {
  236. hr = m_pOutput->Deliver(pOutSample);
  237. } else {
  238. // S_FALSE returned from Transform is a PRIVATE agreement
  239. // We should return NOERROR from Receive() in this case because returning S_FALSE
  240. // from Receive() means that this is the end of the stream and no more data should
  241. // be sent.
  242. if (S_FALSE == hr) {
  243. // We must Release() the sample before doing anything
  244. // like calling the filter graph because having the
  245. // sample means we may have the DirectDraw lock
  246. // (== win16 lock on some versions)
  247. pOutSample->Release();
  248. m_bSampleSkipped = TRUE;
  249. if (!m_bQualityChanged) {
  250. m_bQualityChanged = TRUE;
  251. NotifyEvent(EC_QUALITY_CHANGE,0,0);
  252. }
  253. return NOERROR;
  254. }
  255. }
  256. }
  257. // release the output buffer. If the connected pin still needs it,
  258. // it will have addrefed it itself.
  259. pOutSample->Release();
  260. ASSERT(CritCheckIn(&m_csReceive));
  261. return hr;
  262. }
  263. BOOL CVideoTransformFilter::ShouldSkipFrame( IMediaSample * pIn)
  264. {
  265. REFERENCE_TIME trStart, trStopAt;
  266. HRESULT hr = pIn->GetTime(&trStart, &trStopAt);
  267. // Don't skip frames with no timestamps
  268. if (hr != S_OK)
  269. return FALSE;
  270. int itrFrame = (int)(trStopAt - trStart); // frame duration
  271. if(S_OK==pIn->IsSyncPoint()) {
  272. MSR_INTEGER(m_idFrameType, 1);
  273. if ( m_nKeyFramePeriod < m_nFramesSinceKeyFrame ) {
  274. // record the max
  275. m_nKeyFramePeriod = m_nFramesSinceKeyFrame;
  276. }
  277. m_nFramesSinceKeyFrame = 0;
  278. m_bSkipping = FALSE;
  279. } else {
  280. MSR_INTEGER(m_idFrameType, 2);
  281. if ( m_nFramesSinceKeyFrame>m_nKeyFramePeriod
  282. && m_nKeyFramePeriod>0
  283. ) {
  284. // We haven't seen the key frame yet, but we were clearly being
  285. // overoptimistic about how frequent they are.
  286. m_nKeyFramePeriod = m_nFramesSinceKeyFrame;
  287. }
  288. }
  289. // Whatever we might otherwise decide,
  290. // if we are taking only a small fraction of the required frame time to decode
  291. // then any quality problems are actually coming from somewhere else.
  292. // Could be a net problem at the source for instance. In this case there's
  293. // no point in us skipping frames here.
  294. if (m_itrAvgDecode*4>itrFrame) {
  295. // Don't skip unless we are at least a whole frame late.
  296. // (We would skip B frames if more than 1/2 frame late, but they're safe).
  297. if ( m_itrLate > itrFrame ) {
  298. // Don't skip unless the anticipated key frame would be no more than
  299. // 1 frame early. If the renderer has not been waiting (we *guess*
  300. // it hasn't because we're late) then it will allow frames to be
  301. // played early by up to a frame.
  302. // Let T = Stream time from now to anticipated next key frame
  303. // = (frame duration) * (KeyFramePeriod - FramesSinceKeyFrame)
  304. // So we skip if T - Late < one frame i.e.
  305. // (duration) * (freq - FramesSince) - Late < duration
  306. // or (duration) * (freq - FramesSince - 1) < Late
  307. // We don't dare skip until we have seen some key frames and have
  308. // some idea how often they occur and they are reasonably frequent.
  309. if (m_nKeyFramePeriod>0) {
  310. // It would be crazy - but we could have a stream with key frames
  311. // a very long way apart - and if they are further than about
  312. // 3.5 minutes apart then we could get arithmetic overflow in
  313. // reference time units. Therefore we switch to mSec at this point
  314. int it = (itrFrame/10000)
  315. * (m_nKeyFramePeriod-m_nFramesSinceKeyFrame - 1);
  316. MSR_INTEGER(m_idTimeTillKey, it);
  317. // For debug - might want to see the details - dump them as scratch pad
  318. #ifdef VTRANSPERF
  319. MSR_INTEGER(0, itrFrame);
  320. MSR_INTEGER(0, m_nFramesSinceKeyFrame);
  321. MSR_INTEGER(0, m_nKeyFramePeriod);
  322. #endif
  323. if (m_itrLate/10000 > it) {
  324. m_bSkipping = TRUE;
  325. // Now we are committed. Once we start skipping, we
  326. // cannot stop until we hit a key frame.
  327. } else {
  328. #ifdef VTRANSPERF
  329. MSR_INTEGER(0, 777770); // not near enough to next key
  330. #endif
  331. }
  332. } else {
  333. #ifdef VTRANSPERF
  334. MSR_INTEGER(0, 777771); // Next key not predictable
  335. #endif
  336. }
  337. } else {
  338. #ifdef VTRANSPERF
  339. MSR_INTEGER(0, 777772); // Less than one frame late
  340. MSR_INTEGER(0, m_itrLate);
  341. MSR_INTEGER(0, itrFrame);
  342. #endif
  343. }
  344. } else {
  345. #ifdef VTRANSPERF
  346. MSR_INTEGER(0, 777773); // Decode time short - not not worth skipping
  347. MSR_INTEGER(0, m_itrAvgDecode);
  348. MSR_INTEGER(0, itrFrame);
  349. #endif
  350. }
  351. ++m_nFramesSinceKeyFrame;
  352. if (m_bSkipping) {
  353. // We will count down the lateness as we skip each frame.
  354. // We re-assess each frame. The key frame might not arrive when expected.
  355. // We reset m_itrLate if we get a new Quality message, but actually that's
  356. // not likely because we're not sending frames on to the Renderer. In
  357. // fact if we DID get another one it would mean that there's a long
  358. // pipe between us and the renderer and we might need an altogether
  359. // better strategy to avoid hunting!
  360. m_itrLate = m_itrLate - itrFrame;
  361. }
  362. MSR_INTEGER(m_idLate, (int)m_itrLate/10000 ); // Note how late we think we are
  363. if (m_bSkipping) {
  364. if (!m_bQualityChanged) {
  365. m_bQualityChanged = TRUE;
  366. NotifyEvent(EC_QUALITY_CHANGE,0,0);
  367. }
  368. }
  369. return m_bSkipping;
  370. }
  371. HRESULT CVideoTransformFilter::AlterQuality(Quality q)
  372. {
  373. // to reduce the amount of 64 bit arithmetic, m_itrLate is an int.
  374. // +, -, >, == etc are not too bad, but * and / are painful.
  375. if (m_itrLate>300000000) {
  376. // Avoid overflow and silliness - more than 30 secs late is already silly
  377. m_itrLate = 300000000;
  378. } else {
  379. m_itrLate = (int)q.Late;
  380. }
  381. // We ignore the other fields
  382. // We're actually not very good at handling this. In non-direct draw mode
  383. // most of the time can be spent in the renderer which can skip any frame.
  384. // In that case we'd rather the renderer handled things.
  385. // Nevertheless we will keep an eye on it and if we really start getting
  386. // a very long way behind then we will actually skip - but we'll still tell
  387. // the renderer (or whoever is downstream) that they should handle quality.
  388. return E_FAIL; // Tell the renderer to do his thing.
  389. }
  390. // This will avoid several hundred useless warnings if compiled -W4 by MS VC++ v4
  391. #pragma warning(disable:4514)