хехе.. короче тогда (в 2006 году) я с DirectShow разобрался при помощи примера в MSDN.. но теперь возникла странная проблема которая не дает мне спокойно жить :'(..
вот такой код (DXSDK 8.0)..
#include <dshow.h>
#include <mmstream.h> // IMultiMediaStream
#include <amstream.h> // IAMMultiMediaStream
#include <ddstream.h> // <dshow.h>
#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "strmiids.lib")
class RESOURCE
{
public:
char* Name;
char* Type;
void* Content;
RESOURCE(const char* type, const char* name);
~RESOURCE();
};
class BITMAP : public RESOURCE
{
public:
RECT* Rect;
int Width() { return (Rect) ? (Rect->right - Rect->left + 1) : 0; }
int Height() { return (Rect) ? (Rect->bottom - Rect->top + 1) : 0; }
long Transparent;
BITMAP(const char* type, const char* name) : RESOURCE(type, name) { Rect = NULL; Transparent = -1; }
};
class VIDEO : public BITMAP
{
public:
IMultiMediaStream* Stream;
IMediaStream* pPrimaryVidStream;
IDirectDrawMediaStream* pDDStream;
IDirectDrawStreamSample* pSample;
SURFACE* Surface;
int From;
int Duration;
VIDEO(const char* type, const char* name) : BITMAP(type, name) { Stream = NULL; pPrimaryVidStream = NULL; pDDStream = NULL; pSample = NULL; From = 0; Duration = 0; }
~VIDEO() { if(pSample) pSample->Release(); if(pDDStream) pDDStream->Release(); if(pPrimaryVidStream) pPrimaryVidStream->Release(); if(Stream) Stream->Release(); if(Content) ((SURFACE*)Content)->Release(); if(Name) free(Name); if(Type) free(Type); }
};
PLAYER::PLAYER(HWND handle, char* cmdln)
{
...
CoInitialize(NULL);
...
video = new VIDEO(RESOURCE_VIDEO, "video");
if(! OpenVideoStreamFromFile(video, "C:\\sample.avi")) Log("!!! OPEN");
if(video->Stream->SetState(STREAMSTATE_RUN) != S_OK) Error("!!! RUN1");
...
}
bool PLAYER::OpenVideoStreamFromFile(VIDEO* &video, String filename, bool sound)
{
IAMMultiMediaStream* pAMStream;
if(FAILED(CoCreateInstance(CLSID_AMMultiMediaStream, NULL, CLSCTX_INPROC_SERVER, IID_IAMMultiMediaStream, (void**)&pAMStream))) Error("CCI");
WCHAR wPath[MAX_PATH];
MultiByteToWideChar(CP_ACP, 0, filename.c_str(), -1, wPath, sizeof(wPath)/sizeof(wPath[0]));
if(FAILED(pAMStream->Initialize(STREAMTYPE_READ, AMMSF_NOGRAPHTHREAD, NULL))) Error("AMS_I");
if(FAILED(pAMStream->AddMediaStream(DDraw, &MSPID_PrimaryVideo, 0, NULL))) Error("AMS_AMS_1");
if(sound)
{
if(FAILED(pAMStream->AddMediaStream(NULL, &MSPID_PrimaryAudio, AMMSF_ADDDEFAULTRENDERER, NULL))) Error("AMS_AMS_2");
}
if(FAILED(pAMStream->OpenFile(wPath, 0))) return false; // file not found ?
video->Stream = pAMStream;
DDSURFACEDESC ddsd;
if(FAILED(video->Stream->GetMediaStream(MSPID_PrimaryVideo, &video->pPrimaryVidStream))) Error("MMS_GMS");
if(FAILED(video->pPrimaryVidStream->QueryInterface(IID_IDirectDrawMediaStream, (void**)&video->pDDStream))) Error("PVS_QI");
ddsd.dwSize = sizeof(ddsd);
if(FAILED(video->pDDStream->GetFormat(&ddsd, NULL, NULL, NULL))) Error("DDS_GF");
video->Content = NULL;
DDSURFACEDESC2 ddsd2;
memset(&ddsd2, 0, sizeof(ddsd2));
ddsd2.dwSize = sizeof(ddsd2);
ddsd2.dwFlags = DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS;
ddsd2.dwWidth = ddsd.dwWidth;
ddsd2.dwHeight = ddsd.dwHeight;
ddsd2.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
if(FAILED(DDraw->CreateSurface(&ddsd2, (SURFACE**)&video->Content, NULL))) Error("DD_CV");
IDirectDrawSurface* ddsurface; // DirectDraw1
if(SUCCEEDED(((SURFACE*)video->Content)->QueryInterface(IID_IDirectDrawSurface, (void**)&ddsurface)))
{
if(FAILED(video->pDDStream->CreateSample(ddsurface, NULL, 0, &video->pSample))) Error("DDS_CS");
}
return true;
}
int PLAYER::Execute() // оконное событие (WM_TIMER с 1 миллисекундным интервалом)
{
...
// update running video
if(FAILED(((VIDEO*)scene->Image)->Stream->GetState(&state))) Error("DS_GS");
// здесь ((VIDEO*)scene->Image) = video
if(state == STREAMSTATE_RUN)
{
if(FAILED(((VIDEO*)scene->Image)->pSample->Update(0, NULL, NULL, NULL))) Error("DS_U");
}
if(FAILED(Layer[layer]->Blt(NULL, (SURFACE*)((VIDEO*)scene->Image)->Content, NULL, DDBLT_WAIT, NULL))) Error("DD_B_BACK_VIDEO");
// здесь Layer[layer] это задняя (пробовал и с первичной) поверхность размером с окно.. Content - это поверхность размером с видео на которую должен прорисовываться ролик..
...
}
PLAYER::~PLAYER()
{
...
CoUninitialize();
...
}
раньше (где то год назад) нормально компилился и работал а теперь нормально компилится но.. НЕ РАБОТАЕТ (((..
а точнее — при выполнении программа виснет на строчке pSample->Update при этом звук идет а изображения нет.. управление не возвращается (даже после окончания видео)..
пробовал менять на асинхронную прорисовку:
STREAM_STATE state;
if(video->Stream->GetState(&state) != S_OK) Error("!!! GETSTATE"); else Log("STATE: " + String(state));
STREAM_TIME time;
if(video->Stream->GetTime(&time) != S_OK) Error("!!! GETTIME"); else Log("TIME: " + String((int)time));
STREAM_TIME end;
if(video->Stream->GetDuration(&end) != S_OK) Error("!!! GETDURATION"); else Log("END: " + String((int)end));
if(time >= end)
{
if(video->Stream->SetState(STREAMSTATE_STOP) != S_OK) Error("!!! STOP");
if(video->Stream->Seek(0) != S_OK) Error("!!! SEEK");
if(video->Stream->SetState(STREAMSTATE_RUN) != S_OK) Error("!!! RUN");
}
if(video->Stream->GetState(&state) != S_OK) Error("!!! GETSTATE0");
if(state == STREAMSTATE_RUN)
{
int count = 0;
DWORD ret = video->pSample->Update(SSUPDATE_ASYNC, NULL, NULL, NULL);
if(ret == E_ABORT) Log("E_ABORT");
else if(ret == E_ABORT) Log("E_ABORT");
else if(ret == E_INVALIDARG) Log("E_INVALIDARG");
else if(ret == E_POINTER) Log("E_POINTER");
else if(ret == MS_E_BUSY) Log("MS_E_BUSY");
else if(ret == MS_S_ENDOFSTREAM) Log("MS_S_ENDOFSTREAM");
else if(ret == MS_S_PENDING) Log("MS_S_PENDING");
else if(ret == VFW_E_NOT_COMMITTED) Log("VFW_E_NOT_COMMITTED");
if(ret == MS_S_PENDING)
{
do {
ret = video->pSample->CompletionStatus(COMPSTAT_WAIT, 10); // wait 10 milliseconds before returning
count++;
} while((ret == MS_S_PENDING || ret == MS_E_BUSY) && count <= 3);
}
}
if(FAILED(Layer[layer]->Blt(NULL, (SURFACE*)video->Content, NULL, DDBLT_WAIT, NULL))) Error("!!! BLT");
выдает следующее:
MS_S_PENDING
MS_E_BUSY
MS_E_BUSY
MS_E_BUSY
...
в чем дело ??? ((( помогите пожалуйста а то запарился искать источник проблемы..