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.

552 lines
20 KiB

  1. //==========================================================================;
  2. //
  3. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. // PURPOSE.
  7. //
  8. // Copyright (c) 1992 - 1997 Microsoft Corporation. All Rights Reserved.
  9. //
  10. //--------------------------------------------------------------------------;
  11. // MPEG2Transport Scope filter
  12. // {981CE280-43E4-11d2-8F82-C52201D96F5C}
  13. DEFINE_GUID(CLSID_MPEG2TRANSPORT_SCOPE,
  14. 0x981ce280, 0x43e4, 0x11d2, 0x8f, 0x82, 0xc5, 0x22, 0x1, 0xd9, 0x6f, 0x5c);
  15. const int TRANSPORT_SIZE = 188;
  16. const int TRANSPORT_HEADER_SIZE = 4;
  17. const int PID_MAX = 0x2000; // 8192 (actually one less)
  18. #define INSYNC(p1, p2) (((p1 + TRANSPORT_SIZE) <= p2) ? \
  19. (*p1 == SYNC_BYTE) : (*(p1 + TRANSPORT_SIZE) == SYNC_BYTE))
  20. #pragma pack(1)
  21. typedef struct _TRANSPORTPACKET {
  22. BYTE sync_byte; // Byte 0 0x47
  23. BYTE PID_high:5; // Byte 1
  24. BYTE transport_priority:1;
  25. BYTE payload_unit_start_indicator:1;
  26. BYTE transport_error_indicator:1;
  27. BYTE PID_low; // Byte 2
  28. BYTE continuity_counter:4; // Byte 3
  29. BYTE adaptation_field_control:2;
  30. BYTE transport_scrambling_control:2;
  31. BYTE AdaptationAndData[TRANSPORT_SIZE - TRANSPORT_HEADER_SIZE];
  32. } TRANSPORTPACKET, *PTRANSPORTPACKET;
  33. #define GET_PID(p) ((UINT) ((p->PID_high << 8) + p->PID_low))
  34. typedef struct _ADAPTATIONFIELDHEADER {
  35. BYTE adaptation_field_length; // Byte 0 of adaptation_field
  36. BYTE adaptation_field_extension_flag:1; // Byte 1
  37. BYTE transport_private_data_flag:1;
  38. BYTE splicing_point_flag:1;
  39. BYTE OPCR_flag:1;
  40. BYTE PCR_flag:1;
  41. BYTE elementary_stream_priority_indicator:1;
  42. BYTE random_access_indicator:1;
  43. BYTE discontinuity_indicator:1;
  44. } ADAPTATIONFIELDHEADER, *PADAPTATIONFIELDHEADER;
  45. class PCR {
  46. private:
  47. BYTE b[6];
  48. public:
  49. _int64 PCR64()
  50. {
  51. // 90 kHz
  52. return (_int64) ((unsigned _int64) b[0] << 25 |
  53. b[1] << 17 |
  54. b[2] << 9 |
  55. b[3] << 1 |
  56. b[4] >> 7 );
  57. };
  58. };
  59. #pragma pack()
  60. typedef struct _PIDSTATS {
  61. _int64 PacketCount;
  62. _int64 transport_error_indicator_Count;
  63. _int64 payload_unit_start_indicator_Count;
  64. _int64 transport_priority_Count;
  65. _int64 transport_scrambling_control_not_scrambled_Count;
  66. _int64 transport_scrambling_control_user_defined_Count;
  67. _int64 adaptation_field_Reserved_Count;
  68. _int64 adaptation_field_payload_only_Count;
  69. _int64 adaptation_field_only_Count;
  70. _int64 adaptation_field_and_payload_Count;
  71. _int64 continuity_counter_Error_Count;
  72. _int64 discontinuity_indicator_Count;
  73. _int64 random_access_indicator_Count;
  74. _int64 elementary_stream_priority_indicator_Count;
  75. _int64 PCR_flag_Count;
  76. _int64 OPCR_flag_Count;
  77. _int64 splicing_point_flag_Count;
  78. _int64 transport_private_data_flag_Count;
  79. _int64 adaptation_field_extension_flag_Count;
  80. BYTE continuity_counter_Last;
  81. BYTE splice_countdown;
  82. BYTE transport_private_data_length;
  83. ADAPTATIONFIELDHEADER AdaptationFieldHeaderLast;
  84. PCR PCR_Last;
  85. PCR OPCR_Last;
  86. } PIDSTATS, *PPIDSTATS;
  87. typedef struct _TRANSPORTSTATS {
  88. _int64 TotalMediaSamples;
  89. _int64 TotalMediaSampleDiscontinuities;
  90. _int64 TotalTransportPackets;
  91. _int64 TotalSyncByteErrors;
  92. _int64 MediaSampleSize;
  93. } TRANSPORTSTATS, *PTRANSPORTSTATS;
  94. // -----------------------------------------------------------
  95. // PIDSTATS
  96. // -----------------------------------------------------------
  97. enum {
  98. TSCOL_PID,
  99. TSCOL_0xPID,
  100. TSCOL_PACKETCOUNT,
  101. TSCOL_PERCENT,
  102. TSCOL_transport_error_indicator_Count,
  103. TSCOL_payload_unit_start_indicator_Count,
  104. TSCOL_transport_priority_Count,
  105. TSCOL_transport_scrambling_control_not_scrambled_Count,
  106. TSCOL_transport_scrambling_control_user_defined_Count,
  107. TSCOL_adaptation_field_Reserved_Count,
  108. TSCOL_adaptation_field_payload_only_Count,
  109. TSCOL_adaptation_field_only_Count,
  110. TSCOL_adaptation_field_and_payload_Count,
  111. TSCOL_continuity_counter_Error_Count,
  112. TSCOL_discontinuity_indicator_Count,
  113. TSCOL_random_access_indicator_Count,
  114. TSCOL_elementary_stream_priority_indicator_Count,
  115. TSCOL_PCR_flag_Count,
  116. TSCOL_OPCR_flag_Count,
  117. TSCOL_splicing_point_flag_Count,
  118. TSCOL_transport_private_data_flag_Count,
  119. TSCOL_adaptation_field_extension_flag_Count,
  120. TSCOL_continuity_counter_Last,
  121. TSCOL_splice_countdown,
  122. TSCOL_transport_private_data_length,
  123. TSCOL_AdaptationFieldHeaderLast,
  124. TSCOL_PCR_Last,
  125. TSCOL_OPCR_Last,
  126. TSCOL_PCR_LastMS,
  127. } TSCOL;
  128. typedef struct _TRANSPORT_COLUMN {
  129. BOOL Enabled;
  130. int TSCol;
  131. TCHAR szText[80];
  132. } TRANSPORT_COLUMN, *PTRANSPORT_COLUMN;
  133. TRANSPORT_COLUMN TSColumns[] = {
  134. {TRUE, TSCOL_PID, TEXT("PID") },
  135. {TRUE, TSCOL_0xPID, TEXT("0xPID") },
  136. {TRUE, TSCOL_PACKETCOUNT, TEXT("PacketCount") },
  137. {TRUE, TSCOL_PERCENT, TEXT("% ") },
  138. {TRUE, TSCOL_transport_error_indicator_Count, TEXT("error_indicator") },
  139. {TRUE, TSCOL_payload_unit_start_indicator_Count, TEXT("payload_start_indicator") },
  140. {TRUE, TSCOL_transport_priority_Count, TEXT("priority") },
  141. {TRUE, TSCOL_transport_scrambling_control_not_scrambled_Count, TEXT("not scrambled") },
  142. {TRUE, TSCOL_transport_scrambling_control_user_defined_Count, TEXT("scrambled") },
  143. {TRUE, TSCOL_continuity_counter_Error_Count, TEXT("continuity_counter_Error_Count") },
  144. {TRUE, TSCOL_discontinuity_indicator_Count, TEXT("discontinuity_indicator_Count") },
  145. {TRUE, TSCOL_PCR_flag_Count, TEXT("PCR_flag_Count") },
  146. {TRUE, TSCOL_OPCR_flag_Count, TEXT("OPCR_flag_Count") },
  147. {TRUE, TSCOL_PCR_Last, TEXT("PCR_Last (90kHz)") },
  148. {TRUE, TSCOL_PCR_LastMS, TEXT("PCR_LastMS ") },
  149. };
  150. #define NUM_TSColumns (NUMELMS (TSColumns))
  151. // -----------------------------------------------------------
  152. // PAT
  153. // -----------------------------------------------------------
  154. enum {
  155. PATCOL_PROGRAM,
  156. PATCOL_PID,
  157. PATCOL_0xPID,
  158. } PAT_COL;
  159. typedef struct _PAT_COLUMN {
  160. BOOL Enabled;
  161. int PATCol;
  162. TCHAR szText[80];
  163. } PAT_COLUMN, *PPAT_COLUMN;
  164. PAT_COLUMN PATColumns[] = {
  165. {TRUE, PATCOL_PROGRAM, TEXT("Program") },
  166. {TRUE, PATCOL_PID, TEXT("Program Map Table PID") },
  167. {TRUE, PATCOL_0xPID, TEXT("Program Map Table 0xPID") },
  168. };
  169. #define NUM_PATColumns (NUMELMS (PATColumns))
  170. // -----------------------------------------------------------
  171. // PMT
  172. // -----------------------------------------------------------
  173. enum {
  174. PMTCOL_PROGRAM,
  175. PMTCOL_TABLEID,
  176. PMTCOL_PCRPID,
  177. PMTCOL_0xPCRPID,
  178. PMTCOL_NUMSTREAMS,
  179. PMTCOL_0_Type,
  180. PMTCOL_0_PID,
  181. PMTCOL_0_0xPID,
  182. PMTCOL_1_Type,
  183. PMTCOL_1_PID,
  184. PMTCOL_1_0xPID,
  185. PMTCOL_2_Type,
  186. PMTCOL_2_PID,
  187. PMTCOL_2_0xPID,
  188. PMTCOL_3_Type,
  189. PMTCOL_3_PID,
  190. PMTCOL_3_0xPID,
  191. PMTCOL_4_Type,
  192. PMTCOL_4_PID,
  193. PMTCOL_4_0xPID,
  194. } PMT_COL;
  195. typedef struct _PMT_COLUMN {
  196. BOOL Enabled;
  197. int PMTCol;
  198. TCHAR szText[80];
  199. } PMT_COLUMN, *PPMT_COLUMN;
  200. PMT_COLUMN PMTColumns[] = {
  201. {TRUE, PMTCOL_PROGRAM, TEXT("Program") },
  202. {TRUE, PMTCOL_TABLEID, TEXT("TableID") },
  203. {TRUE, PMTCOL_PCRPID, TEXT("PCRPID") },
  204. {TRUE, PMTCOL_0xPCRPID, TEXT("0xPCRPID") },
  205. {TRUE, PMTCOL_NUMSTREAMS, TEXT("NumStreams") },
  206. {TRUE, PMTCOL_0_Type, TEXT("0 Type") },
  207. {TRUE, PMTCOL_0_PID, TEXT("0 PID") },
  208. {TRUE, PMTCOL_0_0xPID, TEXT("0 0xPID") },
  209. {TRUE, PMTCOL_1_Type, TEXT("1 Type") },
  210. {TRUE, PMTCOL_1_PID, TEXT("1 PID") },
  211. {TRUE, PMTCOL_1_0xPID, TEXT("1 0xPID") },
  212. {TRUE, PMTCOL_2_Type, TEXT("2 Type") },
  213. {TRUE, PMTCOL_2_PID, TEXT("2 PID") },
  214. {TRUE, PMTCOL_2_0xPID, TEXT("2 0xPID") },
  215. {TRUE, PMTCOL_3_Type, TEXT("3 Type") },
  216. {TRUE, PMTCOL_3_PID, TEXT("3 PID") },
  217. {TRUE, PMTCOL_3_0xPID, TEXT("3 0xPID") },
  218. };
  219. #define NUM_PMTColumns (NUMELMS (PMTColumns))
  220. // -----------------------------------------------------------
  221. //
  222. // -----------------------------------------------------------
  223. class CScopeFilter;
  224. class CScopeWindow;
  225. // Class supporting the scope input pin
  226. class CScopeInputPin : public CBaseInputPin
  227. {
  228. friend class CScopeFilter;
  229. friend class CScopeWindow;
  230. public:
  231. CScopeFilter *m_pFilter; // The filter that owns us
  232. private:
  233. // class to pull data from IAsyncReader if we detect that interface
  234. // on the output pin
  235. class CImplPullPin : public CPullPin
  236. {
  237. // forward everything to containing pin
  238. CScopeInputPin* m_pPin;
  239. public:
  240. CImplPullPin(CScopeInputPin* pPin)
  241. : m_pPin(pPin)
  242. {
  243. };
  244. // Override allocator selection to make sure we get our own
  245. HRESULT DecideAllocator(
  246. IMemAllocator* pAlloc,
  247. ALLOCATOR_PROPERTIES * pProps)
  248. {
  249. HRESULT hr = CPullPin::DecideAllocator(pAlloc, pProps);
  250. if (SUCCEEDED(hr) && m_pAlloc != pAlloc) {
  251. return VFW_E_NO_ALLOCATOR;
  252. }
  253. return hr;
  254. }
  255. // forward this to the pin's IMemInputPin::Receive
  256. HRESULT Receive(IMediaSample* pSample) {
  257. return m_pPin->Receive(pSample);
  258. };
  259. // override this to handle end-of-stream
  260. HRESULT EndOfStream(void) {
  261. ((CBaseFilter*)(m_pPin->m_pFilter))->NotifyEvent(EC_COMPLETE, S_OK, 0);
  262. return m_pPin->EndOfStream();
  263. };
  264. // these errors have already been reported to the filtergraph
  265. // by the upstream filter so ignore them
  266. void OnError(HRESULT hr) {
  267. // ignore VFW_E_WRONG_STATE since this happens normally
  268. // during stopping and seeking
  269. // if (hr != VFW_E_WRONG_STATE) {
  270. // m_pPin->NotifyError(hr);
  271. // }
  272. };
  273. // flush the pin and all downstream
  274. HRESULT BeginFlush() {
  275. return m_pPin->BeginFlush();
  276. };
  277. HRESULT EndFlush() {
  278. return m_pPin->EndFlush();
  279. };
  280. };
  281. CImplPullPin m_puller;
  282. // true if we are using m_puller to get data rather than
  283. // IMemInputPin
  284. BOOL m_bPulling;
  285. public:
  286. CScopeInputPin(CScopeFilter *pTextOutFilter,
  287. HRESULT *phr,
  288. LPCWSTR pPinName);
  289. ~CScopeInputPin();
  290. STDMETHODIMP GetAllocatorRequirements(ALLOCATOR_PROPERTIES*pProps);
  291. HRESULT CompleteConnect(IPin *pPin);
  292. // Lets us know where a connection ends
  293. HRESULT BreakConnect();
  294. // Check that we can support this input type
  295. HRESULT CheckMediaType(const CMediaType *pmt);
  296. // Actually set the current format
  297. HRESULT SetMediaType(const CMediaType *pmt);
  298. // IMemInputPin virtual methods
  299. // Override so we can show and hide the window
  300. HRESULT Active(void);
  301. HRESULT Inactive(void);
  302. // Here's the next block of data from the stream.
  303. // AddRef it if you are going to hold onto it
  304. STDMETHODIMP Receive(IMediaSample *pSample);
  305. }; // CScopeInputPin
  306. // This class looks after the management of a window. When the class gets
  307. // instantiated the constructor spawns off a worker thread that does all
  308. // the window work. The original thread waits until it is signaled to
  309. // continue. The worker thread first registers the window class if it
  310. // is not already done. Then it creates a window and sets it's size to
  311. // a default iWidth by iHeight dimensions. The worker thread MUST be the
  312. // one who creates the window as it is the one who calls GetMessage. When
  313. // it has done all this it signals the original thread which lets it
  314. // continue, this ensures a window is created and valid before the
  315. // constructor returns. The thread start address is the WindowMessageLoop
  316. // function. This takes as it's initialisation parameter a pointer to the
  317. // CVideoWindow object that created it, the function also initialises it's
  318. // window related member variables such as the handle and device contexts
  319. // These are the video window styles
  320. const DWORD dwTEXTSTYLES = (WS_POPUP | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CLIPCHILDREN);
  321. const DWORD dwCLASSSTYLES = (CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNCLIENT | CS_OWNDC);
  322. const LPTSTR RENDERCLASS = TEXT("MPEG2TransportScopeWindowClass");
  323. const LPTSTR TITLE = TEXT("MPEG2TransportScope");
  324. const int iWIDTH = 320; // Initial window width
  325. const int iHEIGHT = 240; // Initial window height
  326. const int WM_GOODBYE (WM_USER + 2); // Sent to close the window
  327. class CScopeWindow : public CCritSec
  328. {
  329. friend class CScopeInputPin;
  330. friend class CScopeFilter;
  331. private:
  332. HINSTANCE m_hInstance; // Global module instance handle
  333. CScopeFilter *m_pRenderer; // The owning renderer object
  334. HWND m_hwndDlg; // Handle for our dialog
  335. HANDLE m_hThread; // Our worker thread
  336. DWORD m_ThreadID; // Worker thread ID
  337. CAMEvent m_SyncWorker; // Synchronise with worker thread
  338. CAMEvent m_RenderEvent; // Signals sample to render
  339. BOOL m_bActivated; // Has the window been activated
  340. BOOL m_bStreaming; // Are we currently streaming
  341. int m_LastMediaSampleSize; // Size of last MediaSample
  342. BOOL m_fFreeze; // Flag to signal we're UI frozen
  343. BOOL m_NewPIDFound; // Need to redo the list
  344. UINT m_DisplayMode; // What are we showing in the table?
  345. TRANSPORTPACKET m_PartialPacket; // Packet which spans buffers
  346. ULONG m_PartialPacketSize; // Size of last partial packet in next buffer
  347. PPIDSTATS m_PIDStats;
  348. TRANSPORTSTATS m_TransportStats;
  349. // Tables
  350. Byte_Stream m_ByteStream;
  351. Transport_Packet m_TransportPacket;
  352. Program_Association_Table m_ProgramAssociationTable;
  353. Conditional_Access_Table m_ConditionalAccessTable;
  354. Program_Map_Table m_ProgramMapTable [256]; // ATSC limit of 255 programs
  355. REFERENCE_TIME m_SampleStart; // Most recent sample start time
  356. REFERENCE_TIME m_SampleEnd; // And it's associated end time
  357. REFERENCE_TIME m_MediaTimeStart;
  358. REFERENCE_TIME m_MediaTimeEnd;
  359. // Hold window handles to controls
  360. HWND m_hwndListViewPID;
  361. HWND m_hwndListViewPAT;
  362. HWND m_hwndListViewPMT;
  363. HWND m_hwndListViewCAT;
  364. HWND m_hwndTotalTSPackets;
  365. HWND m_hwndTotalTSErrors;
  366. HWND m_hwndTotalMediaSampleDiscontinuities;
  367. HWND m_hwndTotalMediaSamples;
  368. HWND m_hwndMediaSampleSize;
  369. HWND m_hwndFreeze;
  370. // These create and manage a video window on a separate thread
  371. HRESULT UninitialiseWindow();
  372. HRESULT InitialiseWindow(HWND hwnd);
  373. HRESULT MessageLoop();
  374. // Deal with the listviews
  375. HWND InitListViewPID ();
  376. HWND InitListViewPIDRows ();
  377. LRESULT ListViewNotifyHandlerPID (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  378. HWND InitListViewPAT ();
  379. HWND InitListViewPATRows();
  380. LRESULT ListViewNotifyHandlerPAT(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  381. HWND InitListViewPMT ();
  382. HWND InitListViewPMTRows();
  383. LRESULT ListViewNotifyHandlerPMT (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  384. HWND InitListViewCAT ();
  385. HWND InitListViewCATRows ();
  386. LRESULT ListViewNotifyHandlerCAT (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  387. static DWORD __stdcall WindowMessageLoop(LPVOID lpvThreadParm);
  388. // Maps windows message loop into C++ virtual methods
  389. friend LRESULT CALLBACK WndProc(HWND hwnd, // Window handle
  390. UINT uMsg, // Message ID
  391. WPARAM wParam, // First parameter
  392. LPARAM lParam); // Other parameter
  393. // Called when we start and stop streaming
  394. HRESULT ResetStreamingTimes();
  395. // Window message handlers
  396. BOOL OnClose();
  397. BOOL OnPaint();
  398. void UpdateDisplay();
  399. void Analyze(IMediaSample *pMediaSample);
  400. void GatherPacketStats(PTRANSPORTPACKET pT);
  401. friend BOOL CALLBACK ScopeDlgProc(HWND hwnd, // Window handle
  402. UINT uMsg, // Message ID
  403. WPARAM wParam, // First parameter
  404. LPARAM lParam); // Other parameter
  405. public:
  406. // Constructors and destructors
  407. CScopeWindow(TCHAR *pName, CScopeFilter *pRenderer, HRESULT *phr);
  408. virtual ~CScopeWindow();
  409. HRESULT StartStreaming();
  410. HRESULT StopStreaming();
  411. HRESULT InactivateWindow();
  412. HRESULT ActivateWindow();
  413. // Called when the input pin receives a sample
  414. HRESULT Receive(IMediaSample * pIn);
  415. }; // CScopeWindow
  416. // This is the COM object that represents the MPEG2TransportScope filter
  417. class CScopeFilter
  418. : public CBaseFilter
  419. , public CCritSec
  420. {
  421. public:
  422. // Implements the IBaseFilter and IMediaFilter interfaces
  423. DECLARE_IUNKNOWN
  424. STDMETHODIMP Stop();
  425. STDMETHODIMP Pause();
  426. STDMETHODIMP Run(REFERENCE_TIME tStart);
  427. public:
  428. CScopeFilter(LPUNKNOWN pUnk,HRESULT *phr);
  429. virtual ~CScopeFilter();
  430. // Return the pins that we support
  431. int GetPinCount();
  432. CBasePin *GetPin(int n);
  433. // This goes in the factory template table to create new instances
  434. static CUnknown * WINAPI CreateInstance(LPUNKNOWN, HRESULT *);
  435. STDMETHODIMP JoinFilterGraph(IFilterGraph * pGraph, LPCWSTR pName);
  436. private:
  437. STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);
  438. // The nested classes may access our private state
  439. friend class CScopeInputPin;
  440. friend class CScopeWindow;
  441. CScopeInputPin *m_pInputPin; // Handles pin interfaces
  442. CScopeWindow m_Window; // Looks after the window
  443. CPosPassThru *m_pPosition; // Renderer position controls
  444. }; // CScopeFilter