295 lines
8.6 KiB
C++
295 lines
8.6 KiB
C++
/* Test AM streams stuff */
|
|
|
|
#include <windows.h>
|
|
#include <uuids.h>
|
|
#include <ddraw.h>
|
|
#include <atlbase.h>
|
|
CComModule _Module;
|
|
#include <atlcom.h>
|
|
#include <atlimpl.cpp>
|
|
#include <initguid.h>
|
|
#include <amstream.h>
|
|
#include <mmstream.h>
|
|
#include <ddstream.h>
|
|
#include <austream.h>
|
|
#include <wave.h>
|
|
|
|
#define CHECK_RESULT(_x_) \
|
|
{ \
|
|
HRESULT hr = check_result(_x_, #_x_); \
|
|
if (FAILED(hr)) { \
|
|
return hr; \
|
|
} \
|
|
}
|
|
|
|
inline check_result(HRESULT _x_, LPCTSTR sz)
|
|
{
|
|
if (FAILED(_x_)) {
|
|
AtlTrace(_T("%s failed code %8.8X\n"), sz);
|
|
}
|
|
return _x_;
|
|
}
|
|
|
|
HRESULT FindCaptureDevice(IMoniker **ppMoniker)
|
|
{
|
|
CComPtr<ICreateDevEnum> pCreateDevEnum;
|
|
HRESULT hr = CoCreateInstance(
|
|
CLSID_SystemDeviceEnum,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_ICreateDevEnum,
|
|
(void**)&pCreateDevEnum);
|
|
if (hr != NOERROR)
|
|
return FALSE;
|
|
|
|
CComPtr<IEnumMoniker> pEm;
|
|
hr = pCreateDevEnum->CreateClassEnumerator(CLSID_CVidCapClassManager,
|
|
&pEm,
|
|
0);
|
|
if (hr != NOERROR)
|
|
return hr;
|
|
|
|
ULONG cFetched;
|
|
return pEm->Next(1, ppMoniker, &cFetched);
|
|
}
|
|
|
|
HRESULT LoadCapture(DWORD dwFlags, IAMMultiMediaStream *pMMStream)
|
|
{
|
|
CComPtr<IMoniker> pMoniker;
|
|
HRESULT hr = FindCaptureDevice(&pMoniker);
|
|
AtlTrace(_T("FindCaptureDevice returned %8.8X\n"), hr);
|
|
if (S_OK != hr) {
|
|
return E_FAIL;
|
|
}
|
|
|
|
hr = pMMStream->OpenMoniker(
|
|
pMoniker,
|
|
dwFlags
|
|
);
|
|
AtlTrace("OpenMoniker returned 0x%8.8X\n", hr);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT LoadFile(LPCSTR lpsz, DWORD dwFlags, IAMMultiMediaStream *pMMStream)
|
|
{
|
|
/* Load our file */
|
|
WCHAR wsz[MAX_PATH];
|
|
MultiByteToWideChar(CP_ACP, 0, lpsz, -1, wsz, MAX_PATH);
|
|
HRESULT hr = pMMStream->OpenFile(
|
|
wsz,
|
|
dwFlags
|
|
);
|
|
AtlTrace("OpenFile returned 0x%8.8X\n", hr);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CreateAMMMStream(IAMMultiMediaStream **ppMMStream)
|
|
{
|
|
/* Create the mmstream object */
|
|
HRESULT hr = CoCreateInstance(
|
|
CLSID_AMMultiMediaStream,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IAMMultiMediaStream,
|
|
(void **)ppMMStream
|
|
);
|
|
AtlTrace(_T("CreateAMMMStream returned 0x%8.8X\n"), hr);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT AddAudioStream(IAMMultiMediaStream *pAMMStream)
|
|
{
|
|
return pAMMStream->AddMediaStream(
|
|
NULL,
|
|
MSPID_PrimaryAudio,
|
|
0,
|
|
NULL);
|
|
}
|
|
HRESULT AddDDStream(IAMMultiMediaStream *pAMMStream)
|
|
{
|
|
CComPtr<IDirectDraw> pDDraw;
|
|
HRESULT hr = DirectDrawCreate(NULL, &pDDraw, NULL);
|
|
if (FAILED(hr)) {
|
|
return hr;
|
|
}
|
|
hr = pDDraw->SetCooperativeLevel(HWND_DESKTOP, DDSCL_NORMAL);
|
|
if (FAILED(hr)) {
|
|
return hr;
|
|
}
|
|
return pAMMStream->AddMediaStream(
|
|
pDDraw,
|
|
MSPID_PrimaryVideo,
|
|
0,
|
|
NULL);
|
|
}
|
|
|
|
// Create a random surface
|
|
HRESULT CreateARandomSurface(
|
|
IDirectDraw *pDDraw,
|
|
LPDDSURFACEDESC pDesc,
|
|
IDirectDrawSurface **ppSurface
|
|
)
|
|
{
|
|
return pDDraw->CreateSurface(pDesc, ppSurface, NULL);
|
|
}
|
|
|
|
HRESULT PlayAudio(IMultiMediaStream *pMMStream)
|
|
{
|
|
// Find the audio stream
|
|
CComPtr<IMediaStream> pMediaStream;
|
|
_ASSERTE(S_OK == pMMStream->GetMediaStream(MSPID_PrimaryAudio, &pMediaStream));
|
|
// Get the audio interface and create our sample
|
|
CComPtr<IAudioMediaStream> pAudioStream;
|
|
CHECK_RESULT(pMediaStream->QueryInterface(IID_IAudioMediaStream, (void**)&pAudioStream));
|
|
WAVEFORMATEX wfx;
|
|
CHECK_RESULT(pAudioStream->GetFormat(&wfx));
|
|
#define NBUFFERS 1
|
|
CComPtr<IAudioData> pAudioData[NBUFFERS];
|
|
CComPtr<IAudioStreamSample> pSample[NBUFFERS];
|
|
PBYTE pBuffer[NBUFFERS];
|
|
HANDLE hEvent[NBUFFERS];
|
|
for (int i = 0; i < NBUFFERS; i++) {
|
|
#define DATA_SIZE 5000
|
|
pBuffer[i] = new BYTE[DATA_SIZE];
|
|
CHECK_RESULT(CoCreateInstance(CLSID_AMAudioData,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IAudioData,
|
|
(void**)&pAudioData[i]));
|
|
CHECK_RESULT(pAudioData[i]->Init(DATA_SIZE, pBuffer[i], 0));
|
|
CHECK_RESULT(pAudioData[i]->SetFormat(&wfx));
|
|
CHECK_RESULT(pAudioStream->CreateSample(
|
|
pAudioData[i],
|
|
0,
|
|
&pSample[i]));
|
|
hEvent[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
}
|
|
|
|
// Make a player
|
|
CWaveOut WaveOut(&wfx, 4, 2048);
|
|
|
|
#define MAX_PLAY_TIME 3
|
|
for (int Times = 0; Times < 3; Times++) {
|
|
DWORD dwStart = timeGetTime();
|
|
for (; ; ) {
|
|
HRESULT hr = pSample[0]->Update(0, hEvent[0], NULL, 0);
|
|
if (FAILED(hr) || hr == MS_S_ENDOFSTREAM) {
|
|
break;
|
|
}
|
|
WaitForSingleObject(hEvent[0], INFINITE);
|
|
CHECK_RESULT(pSample[0]->CompletionStatus(0, 0));
|
|
if ((LONG)(timeGetTime() - dwStart) > MAX_PLAY_TIME * 1000) {
|
|
break;
|
|
}
|
|
DWORD dwLength;
|
|
CHECK_RESULT(pAudioData[0]->GetInfo(NULL, NULL, &dwLength));
|
|
_ASSERTE(dwLength == DATA_SIZE || S_OK != hr);
|
|
WaveOut.Write(pBuffer[0], dwLength);
|
|
#if 0
|
|
if (S_OK != hr) {
|
|
_ASSERTE(hr == MS_S_ENDOFSTREAM || hr == S_FALSE);
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
pMMStream->Seek(0);
|
|
}
|
|
WaveOut.Wait();
|
|
return S_OK;
|
|
}
|
|
|
|
// Play a multimedia stream
|
|
HRESULT PlayVideo(IMultiMediaStream *pMMStream)
|
|
{
|
|
// First get the video stream
|
|
CComPtr<IMediaStream> pMediaStream;
|
|
HRESULT hr = pMMStream->GetMediaStream(MSPID_PrimaryVideo, &pMediaStream);
|
|
if (FAILED(hr)) {
|
|
return hr;
|
|
}
|
|
CComPtr<IDirectDrawMediaStream> pDDStream;
|
|
// Get the dd stream
|
|
hr = pMediaStream->QueryInterface(IID_IDirectDrawMediaStream, (void **)&pDDStream);
|
|
if (FAILED(hr)) {
|
|
return hr;
|
|
}
|
|
|
|
// Now create our surface and play with it
|
|
CComPtr<IDirectDraw> pDDraw;
|
|
hr = pDDStream->GetDirectDraw(&pDDraw);
|
|
if (FAILED(hr)) {
|
|
return hr;
|
|
}
|
|
// Find out the movie size
|
|
DDSURFACEDESC ddFormat;
|
|
ddFormat.dwSize = sizeof(ddFormat);
|
|
hr = pDDStream->GetFormat(&ddFormat, NULL, NULL);
|
|
if (FAILED(hr)) {
|
|
return hr;
|
|
}
|
|
CComPtr<IDirectDrawSurface> pSurface;
|
|
hr = CreateARandomSurface(pDDraw, &ddFormat, &pSurface);
|
|
if (FAILED(hr)) {
|
|
return hr;
|
|
}
|
|
CComPtr<IDirectDrawStreamSample> pSample;
|
|
hr = pDDStream->CreateSample(pSurface, NULL, NULL, &pSample);
|
|
if (FAILED(hr)) {
|
|
return hr;
|
|
}
|
|
for (; ; ) {
|
|
HRESULT hr = pSample->Update(0, NULL, NULL, 0);
|
|
if (S_OK != hr) {
|
|
AtlTrace(_T("Update returned 0x%8.8X\n"), hr);
|
|
return S_OK;
|
|
}
|
|
Sleep(10);
|
|
hr = pSample->CompletionStatus(COMPSTAT_NOUPDATEOK |
|
|
COMPSTAT_WAIT,
|
|
0);
|
|
}
|
|
}
|
|
|
|
void DoTests(LPSTR lpszFileName)
|
|
{
|
|
CComPtr<IAMMultiMediaStream> pAMMStream;
|
|
// Create an AMStream
|
|
HRESULT hr = CreateAMMMStream(&pAMMStream);
|
|
|
|
// Now try to create a stream
|
|
CComPtr<IAMMediaStream> pDDStream;
|
|
hr = AddAudioStream(pAMMStream);
|
|
AtlTrace(_T("CreateDDStream returned 0x%8.8X\n"), hr);
|
|
|
|
hr = lpszFileName ?
|
|
LoadFile(lpszFileName, AMMSF_RENDERTOEXISTING, pAMMStream) :
|
|
LoadCapture(AMMSF_RENDERTOEXISTING, pAMMStream);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
HRESULT hr = pAMMStream->Initialize(STREAMTYPE_READ, NULL);
|
|
CComQIPtr<IMultiMediaStream, &IID_IMultiMediaStream> pMMStream(
|
|
pAMMStream);
|
|
DWORD dwFlags;
|
|
STREAM_TYPE Type;
|
|
hr = pMMStream->GetInformation(&dwFlags, &Type);
|
|
_ASSERTE(Type == STREAMTYPE_READ);
|
|
CComPtr<IMediaStream> pStream;
|
|
hr = pMMStream->GetMediaStream(MSPID_PrimaryAudio, &pStream);
|
|
pStream = NULL;
|
|
hr = pMMStream->GetMediaStream(MSPID_PrimaryVideo, &pStream);
|
|
hr = pMMStream->SetState(STREAMSTATE_RUN);
|
|
AtlTrace(_T("SetState(STREAMSTATE_RUN) returned 0x%8.8X\n"), hr);
|
|
hr = PlayAudio(pMMStream);
|
|
Sleep(5000);
|
|
hr = pMMStream->SetState(STREAMSTATE_STOP);
|
|
AtlTrace(_T("SetState(STREAMSTATE_STOP) returned 0x%8.8X\n"), hr);
|
|
}
|
|
}
|
|
int _CRTAPI1 main(int argc, char *argv[])
|
|
{
|
|
CoInitialize(NULL);
|
|
DoTests(argc < 2 ? NULL : argv[1]);
|
|
CoUninitialize();
|
|
return 0;
|
|
}
|