📄 rtspplayer.cpp
字号:
/***********************************************************************/
/* Created by Kevin Vo
* Copyright Sigma Designs Inc
* Sigma Designs Proprietary and confidential
* Created on 3/12/2001
/************************************************************************/
#include "RtspPlayer.h"
RtspPlayer *g_pPlayer;
/////////////////////////////////////////////////////////////////////////////////////////
RtspPlayer::RtspPlayer(HWND hwnd)
{
// Used by IVideoWindow interface to reposition the display window.
m_hwnd = hwnd;
m_dwPlayrate = 1;
m_bTvOut = TRUE;
m_iFullScreen = OATRUE;
m_szIpAddr[0] = '\0';
m_szPlayFileName[0] = '\0';
m_szPlayFilePath[0] = '\0';
m_szPlayFileFullPath[0] = '\0';
m_szIniFile[0] = '\0';
m_pIRmSourceFilter = NULL;
m_pIGraphBuilder = NULL;
m_pIMediaControl = NULL;
m_pIMediaEventEx = NULL;
m_pIVideoWindow = NULL;
m_pIBasicVideo = NULL;
m_pIPin = NULL;
m_pIMediaFilter = NULL;
m_pIRefClock = NULL;
m_pITvVgaOut = NULL;
m_pIRmSourceStreamEx = NULL;
}
/////////////////////////////////////////////////////////////////////////////////////////
RtspPlayer::~RtspPlayer()
{
Uninitialize();
}
/////////////////////////////////////////////////////////////////////////////////////////
void RtspPlayer::Uninitialize()
{
OutputDebugString("\nRtspPlayer Uninitialize");
if (m_pIMediaControl != NULL)
{
m_pIMediaControl->Stop();
m_pIMediaControl->Release();
}
if (m_pIVideoWindow != NULL)
{
m_pIVideoWindow->put_Visible(OAFALSE);
m_pIVideoWindow->put_Owner(NULL);
m_pIVideoWindow->Release();
}
if (m_pITvVgaOut != NULL)
{
m_pITvVgaOut->SetTvOutput(FALSE);
m_pITvVgaOut->Release();
}
if (m_pIPin != NULL) m_pIPin->Release();
if (m_pIMediaFilter != NULL) m_pIMediaFilter->Release();
if (m_pIBasicVideo != NULL) m_pIBasicVideo->Release();
if (m_pIMediaEventEx != NULL) m_pIMediaEventEx->Release();
if (m_pIRmSourceFilter != NULL) m_pIRmSourceFilter->Release();
if (m_pIGraphBuilder != NULL) m_pIGraphBuilder->Release();
if (m_pIRmSourceStreamEx != NULL) m_pIRmSourceStreamEx->Release();
m_pIPin = NULL;
m_pIMediaFilter = NULL;
m_pIRmSourceFilter = NULL;
m_pIBasicVideo = NULL;
m_pIVideoWindow = NULL;
m_pIGraphBuilder = NULL;
m_pIMediaControl = NULL;
m_pIMediaEventEx = NULL;
m_pITvVgaOut = NULL;
m_pIRmSourceStreamEx = NULL;
}
/////////////////////////////////////////////////////////////////////////////////////////
BOOL RtspPlayer::Initialize()
{
HRESULT rt = 0;
char str[50];
OutputDebugString("\nRtspPlayer Initialize");
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **) &m_pIGraphBuilder);
CoCreateInstance(CLSID_RMSourceFilter, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (void **) &m_pIRmSourceFilter);
// m_pIRmSourceFilter->QueryInterface(IID_IMediaFilter, (void **)&m_pIMediaFilter);
m_pIRmSourceFilter->QueryInterface(IID_IRMSourceStreamEx, (void **)&m_pIRmSourceStreamEx);
// Initialize the RTSP
m_pIRmSourceStreamEx->put_ConnectionParams(m_szIpAddr, m_iServerType, m_szPlayFileFullPath);
rt = m_pIRmSourceStreamEx->StartRtsp();
if (rt != S_OK) // Start running the filter
{
wsprintf(str, "Unable to start...Error Code %d.", rt);
MessageBox(m_hwnd, str, NULL, MB_OK);
Uninitialize();
return FALSE;
}
// Have the graph construct its the appropriate graph automatically
m_pIGraphBuilder->AddFilter(m_pIRmSourceFilter, NULL);
m_pIRmSourceFilter->FindPin(L"1", &m_pIPin);
m_pIGraphBuilder->Render(m_pIPin);
// QueryInterface for some basic interfaces
m_pIGraphBuilder->QueryInterface(IID_IMediaControl, (void **)&m_pIMediaControl);
m_pIGraphBuilder->QueryInterface(IID_IMediaEventEx, (void **)&m_pIMediaEventEx);
m_pIGraphBuilder->QueryInterface(IID_IVideoWindow, (void **)&m_pIVideoWindow);
// Have the graph signal event via window callbacks for performance
m_pIMediaEventEx->SetNotifyWindow((OAHWND)m_hwnd, WM_GRAPHNOTIFY, 0);
m_pIMediaEventEx->SetNotifyFlags(0); // Turn on notifications
// Hide window until displayed at correct position
if (m_pIVideoWindow != NULL)
{
m_pIVideoWindow->put_AutoShow(OAFALSE);
m_pIVideoWindow->put_WindowStyle(WS_CHILD);
m_pIVideoWindow->put_Owner((OAHWND)m_hwnd);
// Send the window messages back to the parent window.
m_pIVideoWindow->put_MessageDrain((OAHWND)m_hwnd);
}
QueryTvVgaOutput();
GetBasicVideoInterface();
// m_pIMediaFilter->GetSyncSource(&m_pIRefClock);
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////////////////
// Get the interface to set the video output to TV/VGA
HRESULT RtspPlayer::QueryTvVgaOutput()
{
IEnumFilters *pEnumFilters;
#define MAX 15
m_pIGraphBuilder->EnumFilters(&pEnumFilters);
if (pEnumFilters != NULL)
{
IBaseFilter *Filters[MAX];
ULONG uActualFilters = 0;
BOOL bFound = FALSE;
BYTE bCount = 0;
do
{
pEnumFilters->Next(MAX, (IBaseFilter **) &Filters, &uActualFilters);
for (ULONG ulFilterNum = 0; ulFilterNum < uActualFilters; ulFilterNum++)
{
if (m_pITvVgaOut == NULL)
{
Filters[ulFilterNum]->QueryInterface(IID_ITvVgaOutput, (void **)&m_pITvVgaOut);
if (m_pITvVgaOut != NULL)
bFound = TRUE;
}
Filters[ulFilterNum]->Release();
}
}
while((!bFound) && (uActualFilters == MAX));
pEnumFilters->Release();
}
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////////////////
// This is a routine that can be used to retrieve IBasicVideo interface from
// Video Renderer or filter connected to Video Renderer when Video Renderer
// is only used as an Overlay surface.
HRESULT RtspPlayer::GetBasicVideoInterface()
{
TCHAR szFilter[] = "Video Renderer";
WCHAR wFile[MAX_PATH];
IBaseFilter *m_pfVRender;
m_pIBasicVideo = NULL;
MultiByteToWideChar(CP_ACP, 0, szFilter, -1, wFile, MAX_PATH);
HRESULT hResult = m_pIGraphBuilder->FindFilterByName(wFile, &m_pfVRender);
// If we fail here, let the graph manager handle this
if(FAILED(hResult) || !m_pfVRender)
return m_pIGraphBuilder->QueryInterface(IID_IBasicVideo, (void **) m_pIBasicVideo);
// Get input pin of video renderer
IPin *pInputPin = GetFirstPin(m_pfVRender, PINDIR_INPUT);
m_pfVRender->Release();
if (!pInputPin)
return m_pIGraphBuilder->QueryInterface(IID_IBasicVideo, (void **) m_pIBasicVideo);
// Check who is connected
IPin *pConnectedPin = NULL;
hResult = pInputPin->ConnectedTo(&pConnectedPin);
if (FAILED(hResult) || !pConnectedPin)
{
pInputPin->Release();
return m_pIGraphBuilder->QueryInterface(IID_IBasicVideo, (void **) m_pIBasicVideo);
}
pInputPin->Release();
PIN_INFO InInfo;
hResult = pConnectedPin->QueryPinInfo(&InInfo);
if (FAILED(hResult) || !InInfo.pFilter)
{
pConnectedPin->Release();
return m_pIGraphBuilder->QueryInterface(IID_IBasicVideo, (void **) m_pIBasicVideo);
}
pConnectedPin->Release();
// Query interface on this filter
if (FAILED(InInfo.pFilter->QueryInterface(IID_IBasicVideo,
(void **) m_pIBasicVideo)) || !m_pIBasicVideo)
{
// Finally if previous filter doesn't have this interface, we give up
hResult = m_pIGraphBuilder->QueryInterface(IID_IBasicVideo, (void **) m_pIBasicVideo);
}
InInfo.pFilter->Release();
return hResult;
}
/////////////////////////////////////////////////////////////////////////////////////////
// Get first pin matching a direction on any filter. This is mostly usefull on
// renderers or transform filters which have only one input and/or output pin.
IPin *RtspPlayer::GetFirstPin(IBaseFilter *filter, PIN_DIRECTION PinDir)
{
IEnumPins *pEnumPins = NULL;
IPin *pRetPin = NULL;
BOOL bDone = FALSE;
filter->EnumPins(&pEnumPins);
if (pEnumPins)
{
ULONG uFetchedPins = 0;
while ( (!bDone)
&& (SUCCEEDED(pEnumPins->Next(1, &pRetPin, &uFetchedPins)))
&& (uFetchedPins == 1) )
{
PIN_DIRECTION TempPinDir;
HRESULT hResult = pRetPin->QueryDirection(&TempPinDir);
if (hResult == S_OK)
{
if (TempPinDir == PinDir)
bDone = TRUE;
}
if (!bDone)
pRetPin->Release();
}
pEnumPins->Release();
}
return bDone ? pRetPin : NULL;
}
/////////////////////////////////////////////////////////////////////////////////////////
void RtspPlayer::Play()
{
// Run the graph if RenderFile succeeded
if (m_pIMediaControl != NULL)
{
m_pIMediaControl->Run();
// Fix position and then show
if (m_pIVideoWindow != NULL)
{
UpdateWindowPos(m_hwnd);
m_pIVideoWindow->put_Visible(OATRUE);
m_pIVideoWindow->put_FullScreenMode(m_iFullScreen);
}
if (m_pITvVgaOut != NULL)
m_pITvVgaOut->SetTvOutput(m_bTvOut);
}
}
/////////////////////////////////////////////////////////////////////////////////////////
void RtspPlayer::Stop()
{
if (m_pIVideoWindow != NULL)
{
m_pIVideoWindow->put_FullScreenMode(OAFALSE);
m_pIVideoWindow->put_Visible(OAFALSE);
UpdateWindowPos(m_hwnd);
}
if (m_pIMediaControl != NULL)
{
m_pIMediaControl->StopWhenReady();
m_pIMediaControl->Stop();
}
}
/////////////////////////////////////////////////////////////////////////////////////////
void RtspPlayer::SetFullScreen(int iFullScreen)
{
OutputDebugString("\nRtspPlayer SetFullScreen");
if (iFullScreen == OAFALSE || iFullScreen == OATRUE)
m_iFullScreen = iFullScreen;
if (m_pIVideoWindow != NULL)
m_pIVideoWindow->put_FullScreenMode(m_iFullScreen);
}
/////////////////////////////////////////////////////////////////////////////////////////
void RtspPlayer::SetTvOut(BOOL bVal)
{
m_bTvOut = bVal;
if (m_pITvVgaOut != NULL)
m_pITvVgaOut->SetTvOutput(m_bTvOut);
}
/////////////////////////////////////////////////////////////////////////////////////////
void RtspPlayer::UpdateWindowPos(HWND hWnd)
{
if (m_pIVideoWindow != NULL)
{
RECT rcWndPos;
GetClientRect(hWnd, &rcWndPos);
m_pIVideoWindow->SetWindowPosition(rcWndPos.left, rcWndPos.top,
rcWndPos.right - rcWndPos.left, rcWndPos.bottom - rcWndPos.top);
}
}
/////////////////////////////////////////////////////////////////////////////////////////
HRESULT RtspPlayer::GetMediaEvent(long *lEventCode, long *lParam1, long *lParam2, long msTimeout)
{
if (m_pIMediaEventEx != NULL)
return m_pIMediaEventEx->GetEvent(lEventCode, lParam1, lParam2, msTimeout);
else
return 0;
}
/////////////////////////////////////////////////////////////////////////////////////////
HRESULT RtspPlayer::FreeMediaEventParams(long lEventCode, long lParam1, long lParam2)
{
if (m_pIMediaEventEx != NULL)
return m_pIMediaEventEx->FreeEventParams(lEventCode, lParam1, lParam2);
else
return 0;
}
/////////////////////////////////////////////////////////////////////////////////////////
// Get the play files from the ini file and display them to the screen.
void RtspPlayer::GetINIInfo(HWND hwnd)
{
char buffer[256];
char key;
// Get the full path of the INI file
if (strcmp(m_szIniFile, "") == 0)
GetFullPathName(INI_FILE, sizeof(m_szIniFile), m_szIniFile, NULL);
SendDlgItemMessage (hwnd, IDC_COMBO_PLAYFILE, CB_RESETCONTENT, 0, 0);
// Read the file names from INI file and display them on the screen
for (int i = 1; ; i++)
{
itoa(i, &key, 10);
GetPrivateProfileString("FILE_NAMES", &key, "", buffer, sizeof(buffer), m_szIniFile);
if (strcmp(buffer, "") == 0)
break;
SendDlgItemMessage (hwnd, IDC_COMBO_PLAYFILE, CB_ADDSTRING, 0, (LPARAM)buffer);
}
SendDlgItemMessage (hwnd, IDC_COMBO_PLAYFILE, CB_SETCURSEL, 0, 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -