Re: DirectShow открывает видео
От: JsK  
Дата: 07.10.08 13:08
Оценка:
хехе.. короче тогда (в 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
...


в чем дело ??? ((( помогите пожалуйста а то запарился искать источник проблемы..
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.