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

//==========================================================================;
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// Copyright (c) 1992 - 1997 Microsoft Corporation. All Rights Reserved.
//
//--------------------------------------------------------------------------;
// MPEG2Transport Scope filter
// {981CE280-43E4-11d2-8F82-C52201D96F5C}
DEFINE_GUID(CLSID_MPEG2TRANSPORT_SCOPE,
0x981ce280, 0x43e4, 0x11d2, 0x8f, 0x82, 0xc5, 0x22, 0x1, 0xd9, 0x6f, 0x5c);
const int TRANSPORT_SIZE = 188;
const int TRANSPORT_HEADER_SIZE = 4;
const int PID_MAX = 0x2000; // 8192 (actually one less)
#define INSYNC(p1, p2) (((p1 + TRANSPORT_SIZE) <= p2) ? \
(*p1 == SYNC_BYTE) : (*(p1 + TRANSPORT_SIZE) == SYNC_BYTE))
#pragma pack(1)
typedef struct _TRANSPORTPACKET {
BYTE sync_byte; // Byte 0 0x47
BYTE PID_high:5; // Byte 1
BYTE transport_priority:1;
BYTE payload_unit_start_indicator:1;
BYTE transport_error_indicator:1;
BYTE PID_low; // Byte 2
BYTE continuity_counter:4; // Byte 3
BYTE adaptation_field_control:2;
BYTE transport_scrambling_control:2;
BYTE AdaptationAndData[TRANSPORT_SIZE - TRANSPORT_HEADER_SIZE];
} TRANSPORTPACKET, *PTRANSPORTPACKET;
#define GET_PID(p) ((UINT) ((p->PID_high << 8) + p->PID_low))
typedef struct _ADAPTATIONFIELDHEADER {
BYTE adaptation_field_length; // Byte 0 of adaptation_field
BYTE adaptation_field_extension_flag:1; // Byte 1
BYTE transport_private_data_flag:1;
BYTE splicing_point_flag:1;
BYTE OPCR_flag:1;
BYTE PCR_flag:1;
BYTE elementary_stream_priority_indicator:1;
BYTE random_access_indicator:1;
BYTE discontinuity_indicator:1;
} ADAPTATIONFIELDHEADER, *PADAPTATIONFIELDHEADER;
class PCR {
private:
BYTE b[6];
public:
_int64 PCR64()
{
// 90 kHz
return (_int64) ((unsigned _int64) b[0] << 25 |
b[1] << 17 |
b[2] << 9 |
b[3] << 1 |
b[4] >> 7 );
};
};
#pragma pack()
typedef struct _PIDSTATS {
_int64 PacketCount;
_int64 transport_error_indicator_Count;
_int64 payload_unit_start_indicator_Count;
_int64 transport_priority_Count;
_int64 transport_scrambling_control_not_scrambled_Count;
_int64 transport_scrambling_control_user_defined_Count;
_int64 adaptation_field_Reserved_Count;
_int64 adaptation_field_payload_only_Count;
_int64 adaptation_field_only_Count;
_int64 adaptation_field_and_payload_Count;
_int64 continuity_counter_Error_Count;
_int64 discontinuity_indicator_Count;
_int64 random_access_indicator_Count;
_int64 elementary_stream_priority_indicator_Count;
_int64 PCR_flag_Count;
_int64 OPCR_flag_Count;
_int64 splicing_point_flag_Count;
_int64 transport_private_data_flag_Count;
_int64 adaptation_field_extension_flag_Count;
BYTE continuity_counter_Last;
BYTE splice_countdown;
BYTE transport_private_data_length;
ADAPTATIONFIELDHEADER AdaptationFieldHeaderLast;
PCR PCR_Last;
PCR OPCR_Last;
} PIDSTATS, *PPIDSTATS;
typedef struct _TRANSPORTSTATS {
_int64 TotalMediaSamples;
_int64 TotalMediaSampleDiscontinuities;
_int64 TotalTransportPackets;
_int64 TotalSyncByteErrors;
_int64 MediaSampleSize;
} TRANSPORTSTATS, *PTRANSPORTSTATS;
// -----------------------------------------------------------
// PIDSTATS
// -----------------------------------------------------------
enum {
TSCOL_PID,
TSCOL_0xPID,
TSCOL_PACKETCOUNT,
TSCOL_PERCENT,
TSCOL_transport_error_indicator_Count,
TSCOL_payload_unit_start_indicator_Count,
TSCOL_transport_priority_Count,
TSCOL_transport_scrambling_control_not_scrambled_Count,
TSCOL_transport_scrambling_control_user_defined_Count,
TSCOL_adaptation_field_Reserved_Count,
TSCOL_adaptation_field_payload_only_Count,
TSCOL_adaptation_field_only_Count,
TSCOL_adaptation_field_and_payload_Count,
TSCOL_continuity_counter_Error_Count,
TSCOL_discontinuity_indicator_Count,
TSCOL_random_access_indicator_Count,
TSCOL_elementary_stream_priority_indicator_Count,
TSCOL_PCR_flag_Count,
TSCOL_OPCR_flag_Count,
TSCOL_splicing_point_flag_Count,
TSCOL_transport_private_data_flag_Count,
TSCOL_adaptation_field_extension_flag_Count,
TSCOL_continuity_counter_Last,
TSCOL_splice_countdown,
TSCOL_transport_private_data_length,
TSCOL_AdaptationFieldHeaderLast,
TSCOL_PCR_Last,
TSCOL_OPCR_Last,
TSCOL_PCR_LastMS,
} TSCOL;
typedef struct _TRANSPORT_COLUMN {
BOOL Enabled;
int TSCol;
TCHAR szText[80];
} TRANSPORT_COLUMN, *PTRANSPORT_COLUMN;
TRANSPORT_COLUMN TSColumns[] = {
{TRUE, TSCOL_PID, TEXT("PID") },
{TRUE, TSCOL_0xPID, TEXT("0xPID") },
{TRUE, TSCOL_PACKETCOUNT, TEXT("PacketCount") },
{TRUE, TSCOL_PERCENT, TEXT("% ") },
{TRUE, TSCOL_transport_error_indicator_Count, TEXT("error_indicator") },
{TRUE, TSCOL_payload_unit_start_indicator_Count, TEXT("payload_start_indicator") },
{TRUE, TSCOL_transport_priority_Count, TEXT("priority") },
{TRUE, TSCOL_transport_scrambling_control_not_scrambled_Count, TEXT("not scrambled") },
{TRUE, TSCOL_transport_scrambling_control_user_defined_Count, TEXT("scrambled") },
{TRUE, TSCOL_continuity_counter_Error_Count, TEXT("continuity_counter_Error_Count") },
{TRUE, TSCOL_discontinuity_indicator_Count, TEXT("discontinuity_indicator_Count") },
{TRUE, TSCOL_PCR_flag_Count, TEXT("PCR_flag_Count") },
{TRUE, TSCOL_OPCR_flag_Count, TEXT("OPCR_flag_Count") },
{TRUE, TSCOL_PCR_Last, TEXT("PCR_Last (90kHz)") },
{TRUE, TSCOL_PCR_LastMS, TEXT("PCR_LastMS ") },
};
#define NUM_TSColumns (NUMELMS (TSColumns))
// -----------------------------------------------------------
// PAT
// -----------------------------------------------------------
enum {
PATCOL_PROGRAM,
PATCOL_PID,
PATCOL_0xPID,
} PAT_COL;
typedef struct _PAT_COLUMN {
BOOL Enabled;
int PATCol;
TCHAR szText[80];
} PAT_COLUMN, *PPAT_COLUMN;
PAT_COLUMN PATColumns[] = {
{TRUE, PATCOL_PROGRAM, TEXT("Program") },
{TRUE, PATCOL_PID, TEXT("Program Map Table PID") },
{TRUE, PATCOL_0xPID, TEXT("Program Map Table 0xPID") },
};
#define NUM_PATColumns (NUMELMS (PATColumns))
// -----------------------------------------------------------
// PMT
// -----------------------------------------------------------
enum {
PMTCOL_PROGRAM,
PMTCOL_TABLEID,
PMTCOL_PCRPID,
PMTCOL_0xPCRPID,
PMTCOL_NUMSTREAMS,
PMTCOL_0_Type,
PMTCOL_0_PID,
PMTCOL_0_0xPID,
PMTCOL_1_Type,
PMTCOL_1_PID,
PMTCOL_1_0xPID,
PMTCOL_2_Type,
PMTCOL_2_PID,
PMTCOL_2_0xPID,
PMTCOL_3_Type,
PMTCOL_3_PID,
PMTCOL_3_0xPID,
PMTCOL_4_Type,
PMTCOL_4_PID,
PMTCOL_4_0xPID,
} PMT_COL;
typedef struct _PMT_COLUMN {
BOOL Enabled;
int PMTCol;
TCHAR szText[80];
} PMT_COLUMN, *PPMT_COLUMN;
PMT_COLUMN PMTColumns[] = {
{TRUE, PMTCOL_PROGRAM, TEXT("Program") },
{TRUE, PMTCOL_TABLEID, TEXT("TableID") },
{TRUE, PMTCOL_PCRPID, TEXT("PCRPID") },
{TRUE, PMTCOL_0xPCRPID, TEXT("0xPCRPID") },
{TRUE, PMTCOL_NUMSTREAMS, TEXT("NumStreams") },
{TRUE, PMTCOL_0_Type, TEXT("0 Type") },
{TRUE, PMTCOL_0_PID, TEXT("0 PID") },
{TRUE, PMTCOL_0_0xPID, TEXT("0 0xPID") },
{TRUE, PMTCOL_1_Type, TEXT("1 Type") },
{TRUE, PMTCOL_1_PID, TEXT("1 PID") },
{TRUE, PMTCOL_1_0xPID, TEXT("1 0xPID") },
{TRUE, PMTCOL_2_Type, TEXT("2 Type") },
{TRUE, PMTCOL_2_PID, TEXT("2 PID") },
{TRUE, PMTCOL_2_0xPID, TEXT("2 0xPID") },
{TRUE, PMTCOL_3_Type, TEXT("3 Type") },
{TRUE, PMTCOL_3_PID, TEXT("3 PID") },
{TRUE, PMTCOL_3_0xPID, TEXT("3 0xPID") },
};
#define NUM_PMTColumns (NUMELMS (PMTColumns))
// -----------------------------------------------------------
//
// -----------------------------------------------------------
class CScopeFilter;
class CScopeWindow;
// Class supporting the scope input pin
class CScopeInputPin : public CBaseInputPin
{
friend class CScopeFilter;
friend class CScopeWindow;
public:
CScopeFilter *m_pFilter; // The filter that owns us
private:
// class to pull data from IAsyncReader if we detect that interface
// on the output pin
class CImplPullPin : public CPullPin
{
// forward everything to containing pin
CScopeInputPin* m_pPin;
public:
CImplPullPin(CScopeInputPin* pPin)
: m_pPin(pPin)
{
};
// Override allocator selection to make sure we get our own
HRESULT DecideAllocator(
IMemAllocator* pAlloc,
ALLOCATOR_PROPERTIES * pProps)
{
HRESULT hr = CPullPin::DecideAllocator(pAlloc, pProps);
if (SUCCEEDED(hr) && m_pAlloc != pAlloc) {
return VFW_E_NO_ALLOCATOR;
}
return hr;
}
// forward this to the pin's IMemInputPin::Receive
HRESULT Receive(IMediaSample* pSample) {
return m_pPin->Receive(pSample);
};
// override this to handle end-of-stream
HRESULT EndOfStream(void) {
((CBaseFilter*)(m_pPin->m_pFilter))->NotifyEvent(EC_COMPLETE, S_OK, 0);
return m_pPin->EndOfStream();
};
// these errors have already been reported to the filtergraph
// by the upstream filter so ignore them
void OnError(HRESULT hr) {
// ignore VFW_E_WRONG_STATE since this happens normally
// during stopping and seeking
// if (hr != VFW_E_WRONG_STATE) {
// m_pPin->NotifyError(hr);
// }
};
// flush the pin and all downstream
HRESULT BeginFlush() {
return m_pPin->BeginFlush();
};
HRESULT EndFlush() {
return m_pPin->EndFlush();
};
};
CImplPullPin m_puller;
// true if we are using m_puller to get data rather than
// IMemInputPin
BOOL m_bPulling;
public:
CScopeInputPin(CScopeFilter *pTextOutFilter,
HRESULT *phr,
LPCWSTR pPinName);
~CScopeInputPin();
STDMETHODIMP GetAllocatorRequirements(ALLOCATOR_PROPERTIES*pProps);
HRESULT CompleteConnect(IPin *pPin);
// Lets us know where a connection ends
HRESULT BreakConnect();
// Check that we can support this input type
HRESULT CheckMediaType(const CMediaType *pmt);
// Actually set the current format
HRESULT SetMediaType(const CMediaType *pmt);
// IMemInputPin virtual methods
// Override so we can show and hide the window
HRESULT Active(void);
HRESULT Inactive(void);
// Here's the next block of data from the stream.
// AddRef it if you are going to hold onto it
STDMETHODIMP Receive(IMediaSample *pSample);
}; // CScopeInputPin
// This class looks after the management of a window. When the class gets
// instantiated the constructor spawns off a worker thread that does all
// the window work. The original thread waits until it is signaled to
// continue. The worker thread first registers the window class if it
// is not already done. Then it creates a window and sets it's size to
// a default iWidth by iHeight dimensions. The worker thread MUST be the
// one who creates the window as it is the one who calls GetMessage. When
// it has done all this it signals the original thread which lets it
// continue, this ensures a window is created and valid before the
// constructor returns. The thread start address is the WindowMessageLoop
// function. This takes as it's initialisation parameter a pointer to the
// CVideoWindow object that created it, the function also initialises it's
// window related member variables such as the handle and device contexts
// These are the video window styles
const DWORD dwTEXTSTYLES = (WS_POPUP | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CLIPCHILDREN);
const DWORD dwCLASSSTYLES = (CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNCLIENT | CS_OWNDC);
const LPTSTR RENDERCLASS = TEXT("MPEG2TransportScopeWindowClass");
const LPTSTR TITLE = TEXT("MPEG2TransportScope");
const int iWIDTH = 320; // Initial window width
const int iHEIGHT = 240; // Initial window height
const int WM_GOODBYE (WM_USER + 2); // Sent to close the window
class CScopeWindow : public CCritSec
{
friend class CScopeInputPin;
friend class CScopeFilter;
private:
HINSTANCE m_hInstance; // Global module instance handle
CScopeFilter *m_pRenderer; // The owning renderer object
HWND m_hwndDlg; // Handle for our dialog
HANDLE m_hThread; // Our worker thread
DWORD m_ThreadID; // Worker thread ID
CAMEvent m_SyncWorker; // Synchronise with worker thread
CAMEvent m_RenderEvent; // Signals sample to render
BOOL m_bActivated; // Has the window been activated
BOOL m_bStreaming; // Are we currently streaming
int m_LastMediaSampleSize; // Size of last MediaSample
BOOL m_fFreeze; // Flag to signal we're UI frozen
BOOL m_NewPIDFound; // Need to redo the list
UINT m_DisplayMode; // What are we showing in the table?
TRANSPORTPACKET m_PartialPacket; // Packet which spans buffers
ULONG m_PartialPacketSize; // Size of last partial packet in next buffer
PPIDSTATS m_PIDStats;
TRANSPORTSTATS m_TransportStats;
// Tables
Byte_Stream m_ByteStream;
Transport_Packet m_TransportPacket;
Program_Association_Table m_ProgramAssociationTable;
Conditional_Access_Table m_ConditionalAccessTable;
Program_Map_Table m_ProgramMapTable [256]; // ATSC limit of 255 programs
REFERENCE_TIME m_SampleStart; // Most recent sample start time
REFERENCE_TIME m_SampleEnd; // And it's associated end time
REFERENCE_TIME m_MediaTimeStart;
REFERENCE_TIME m_MediaTimeEnd;
// Hold window handles to controls
HWND m_hwndListViewPID;
HWND m_hwndListViewPAT;
HWND m_hwndListViewPMT;
HWND m_hwndListViewCAT;
HWND m_hwndTotalTSPackets;
HWND m_hwndTotalTSErrors;
HWND m_hwndTotalMediaSampleDiscontinuities;
HWND m_hwndTotalMediaSamples;
HWND m_hwndMediaSampleSize;
HWND m_hwndFreeze;
// These create and manage a video window on a separate thread
HRESULT UninitialiseWindow();
HRESULT InitialiseWindow(HWND hwnd);
HRESULT MessageLoop();
// Deal with the listviews
HWND InitListViewPID ();
HWND InitListViewPIDRows ();
LRESULT ListViewNotifyHandlerPID (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
HWND InitListViewPAT ();
HWND InitListViewPATRows();
LRESULT ListViewNotifyHandlerPAT(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
HWND InitListViewPMT ();
HWND InitListViewPMTRows();
LRESULT ListViewNotifyHandlerPMT (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
HWND InitListViewCAT ();
HWND InitListViewCATRows ();
LRESULT ListViewNotifyHandlerCAT (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static DWORD __stdcall WindowMessageLoop(LPVOID lpvThreadParm);
// Maps windows message loop into C++ virtual methods
friend LRESULT CALLBACK WndProc(HWND hwnd, // Window handle
UINT uMsg, // Message ID
WPARAM wParam, // First parameter
LPARAM lParam); // Other parameter
// Called when we start and stop streaming
HRESULT ResetStreamingTimes();
// Window message handlers
BOOL OnClose();
BOOL OnPaint();
void UpdateDisplay();
void Analyze(IMediaSample *pMediaSample);
void GatherPacketStats(PTRANSPORTPACKET pT);
friend BOOL CALLBACK ScopeDlgProc(HWND hwnd, // Window handle
UINT uMsg, // Message ID
WPARAM wParam, // First parameter
LPARAM lParam); // Other parameter
public:
// Constructors and destructors
CScopeWindow(TCHAR *pName, CScopeFilter *pRenderer, HRESULT *phr);
virtual ~CScopeWindow();
HRESULT StartStreaming();
HRESULT StopStreaming();
HRESULT InactivateWindow();
HRESULT ActivateWindow();
// Called when the input pin receives a sample
HRESULT Receive(IMediaSample * pIn);
}; // CScopeWindow
// This is the COM object that represents the MPEG2TransportScope filter
class CScopeFilter
: public CBaseFilter
, public CCritSec
{
public:
// Implements the IBaseFilter and IMediaFilter interfaces
DECLARE_IUNKNOWN
STDMETHODIMP Stop();
STDMETHODIMP Pause();
STDMETHODIMP Run(REFERENCE_TIME tStart);
public:
CScopeFilter(LPUNKNOWN pUnk,HRESULT *phr);
virtual ~CScopeFilter();
// Return the pins that we support
int GetPinCount();
CBasePin *GetPin(int n);
// This goes in the factory template table to create new instances
static CUnknown * WINAPI CreateInstance(LPUNKNOWN, HRESULT *);
STDMETHODIMP JoinFilterGraph(IFilterGraph * pGraph, LPCWSTR pName);
private:
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);
// The nested classes may access our private state
friend class CScopeInputPin;
friend class CScopeWindow;
CScopeInputPin *m_pInputPin; // Handles pin interfaces
CScopeWindow m_Window; // Looks after the window
CPosPassThru *m_pPosition; // Renderer position controls
}; // CScopeFilter