DirectShow открывает видео
От: Аноним  
Дата: 23.10.05 08:52
Оценка:
Помогите пожалуйста...
Никогда до этого не работал с DShow...

нужно всего лишь получать данные (не открывать цельный файл, а из указателя на блок памяти или файла), представляющие собой файлы AVI сжатые DIVX или другим кодеком.... выбирать заданный по номеру кадр и воспроизводить его на Surface....
итак: указатель на данные AVI + номер кадра -> изображение на поверхности....

как это реализовать ?...
пробовал смотреть Samples (DDrawXCL, PlayWnd), но они слишком сложные для моей простой задачи.....
в сети есть похожие примеры на Delphi но мне не удается перевести их на мой BCB....

помогите пожалуйста с кодом — получение заданного по номеру кадра из блока AVI данных на поверхность.....

Заранее — большое спасибо ! ...
Re: DirectShow открывает видео
От: _INDY_ Россия  
Дата: 24.10.05 04:32
Оценка: 7 (2)
Здравствуйте, Аноним, Вы писали:

А>Помогите пожалуйста...

А>Никогда до этого не работал с DShow...

А>нужно всего лишь получать данные (не открывать цельный файл, а из указателя на блок памяти или файла), представляющие собой файлы AVI сжатые DIVX или другим кодеком.... выбирать заданный по номеру кадр и воспроизводить его на Surface....

А>итак: указатель на данные AVI + номер кадра -> изображение на поверхности....

А>как это реализовать ?...

А>пробовал смотреть Samples (DDrawXCL, PlayWnd), но они слишком сложные для моей простой задачи.....
А>в сети есть похожие примеры на Delphi но мне не удается перевести их на мой BCB....

А>помогите пожалуйста с кодом — получение заданного по номеру кадра из блока AVI данных на поверхность.....


А>Заранее — большое спасибо ! ...


Всё достаточно просто: (в случае работы с файлом) тебе надо, во первых: найти в описании DS SDK пример — самого простого плейера — там всего лишь несколько строк — этот плейер — просто подниамет файл и рендерит его(строит граф), после чего запускает Run и ждёт пока не закончится воспроизведение (посмотри внимательно как там сделано). После этого тебе надо руками поднять твой файл т.е. IGraphBuilder::AddSourceFilter, потом поднять руками AVI Splitter, и DIVX или XVID декодер, добавить фильтры в граф, соединить, для того что бы сграбить кадр, надо либо смотреть в примерах(фильтр SampleGrabber точно не скажу), либо взять за пример фильтр ezrgb24, убрать у него выходной пин а входной унаследовать от CRenderedInputPin что бы фильтр как бы рендерером стал и соединяться только на RGB24 или RGB32 — из полученного сампла выковыривай свою картинку и пользуй. Ага чуть не забыл у IGraphBuilder::QueryInterface на IMediaSeeking — и позиционируйся как тебе надо — на выходе будешь получать(в своём фильтре кадр который тебе нужен) — это собственно напрвление раскопок! дальше только сам ...
Per Aspera Ad Astra
Re[2]: DirectShow открывает видео
От: Аноним  
Дата: 24.10.05 19:47
Оценка:
Здравствуйте, _INDY_, Вы писали:
[..SKIPPED..]
_IN>Всё достаточно просто: (

вообще то я просил именно кусочек кода %).... не думаю что там очень много....
потому что разбираться с сложными (для моей задачи) примерами SDK (которые содержат массу нетребуемых наворотов, и у меня в BCB даже не компилятся, чтобы их отладить), как я уже сказал, у меня совсем нет времени ...
я бы и не связывался с этим DShow если бы не значительный объем видео данных, которых непозволительно хранить в обычной последовательности кадров, даже закодированных JPEG....
вот и возникла идея воспользоваться сжатием DivX... а как запрашивать у него кадры — не знаю.....((....
тратиться время на вникание в подробности "темного леса" DShow не могу.....
поэтому и прошу экспертов небольшой помощи.....

неужели никто этим не занимался ?....
Re[3]: DirectShow открывает видео
От: nbober  
Дата: 25.10.05 04:27
Оценка:
Здравсвуйте.

То что вы просите, вобщем задача нестандартная. Поэтому мпловероятно что у когото есть готовое решение.
И с чего вы взяли, что она решается в 10 строчек кода? к тому же в требованиях указанных вами есть досаточно много
непонятного. И как мне кажется (а у меня есть достаточный опыт в директ шоу) робота от 2 до 12 часов, как вы
сами пнимаете никому не хочется тратить столько своего времени для решения чужих проблем.


Как вариант вам можно предложить хранить ваши закодированные видео данные не в памяти, а на диске в виде авишки.
Тогда ответ находится достаточно быстро и строиться он на готовых компонентах.
Re[4]: DirectShow открывает видео
От: nbober  
Дата: 25.10.05 04:39
Оценка:
Сорри, про 2- 12 часов это я так оцениваю трудоемкоть того что вы говорите (такой большой разброс
потому что формулировка недостаточно строга).
Re[4]: DirectShow открывает видео
От: Аноним  
Дата: 31.10.05 06:17
Оценка:
Здравствуйте, nbober, Вы писали:

N>То что вы просите, вобщем задача нестандартная. Поэтому мпловероятно что у когото есть готовое решение.


N>Как вариант вам можно предложить хранить ваши закодированные видео данные не в памяти, а на диске в виде авишки.

N>Тогда ответ находится достаточно быстро и строиться он на готовых компонентах.

имхо она как раз таки стандартная %)
потому что видео хранится именно на диске.
с той лишь только разницей, что все файлы avi (может быть по нескольку секунд или часов) последовательны склеены в один (разумеется начало и длина каждого куска известна)...
какая разница — будет DS читать данные из отдельного файла или из потока...

если вы можете помочь мне хотя бы простым кодом, получающим заданный кадр на поверхность, только из дискового файла avi... это было бы замечательно !..

я подразумеваю конечно не пару часов работы, а минут десять (вы же профессионал и наверняка неоднократно решали подобные задачи)...
Re: DirectShow открывает видео
От: Аноним  
Дата: 08.02.06 07:46
Оценка:
нерешенная проблема снова встала ребром ..

мне нужно получить из файлового потока AVI кадр по его индексу и вывести его на поверхность...

несколько дней пытался разобраться с примерами в поставке DXSDK8.. DDrawXcl...
во первых там отнюдь не 10..20 строчек а три приличных модуля по 1000 строк...
после чистки (удаления функции воспроизведения DVD, логирования ошибок, вывода на поверхность текста и полостатого мячика) — код уменьшился примерно вдвое... но все равно не так то просто со всем этим разобраться...
как я понял там используется ОВЕРЛЕЙ — то есть видео выводится не на нужную мне поверхность (которую я потом обрабатываю как обычно — рисую текст, применяю эффекты, сохраняю в bmp) а черт знает куда (...

нет ли у кого нибудь иного готового решения ?...
может быть даже без DirectShow...
мне нужно только извлекать нужный кадр из AVI который может быть сжат каким нибудь кодеком...
размеры кадра, частота воспроизведения, длина файла — известны заранее...

заранее — большое спасибо за любую помощь ! ...
Re[2]: DirectShow открывает видео
От: zinetz_victor  
Дата: 08.02.06 08:30
Оценка:
Здравствуйте, Аноним, Вы писали:

А>нерешенная проблема снова встала ребром ..


А>мне нужно получить из файлового потока AVI кадр по его индексу и вывести его на поверхность...


А>несколько дней пытался разобраться с примерами в поставке DXSDK8.. DDrawXcl...

А>во первых там отнюдь не 10..20 строчек а три приличных модуля по 1000 строк...
А>после чистки (удаления функции воспроизведения DVD, логирования ошибок, вывода на поверхность текста и полостатого мячика) — код уменьшился примерно вдвое... но все равно не так то просто со всем этим разобраться...
А>как я понял там используется ОВЕРЛЕЙ — то есть видео выводится не на нужную мне поверхность (которую я потом обрабатываю как обычно — рисую текст, применяю эффекты, сохраняю в bmp) а черт знает куда (...

А>нет ли у кого нибудь иного готового решения ?...

А>может быть даже без DirectShow...
А>мне нужно только извлекать нужный кадр из AVI который может быть сжат каким нибудь кодеком...
А>размеры кадра, частота воспроизведения, длина файла — известны заранее...

А>заранее — большое спасибо за любую помощь ! ...


ffmpeg например, если без ds; геморой (под windows) с тем, что компилится под gcc, но зато читает много чего кроме avi, декодирует почти все; доки неважные, но по примерам можно разобраться

но все, что у меня есть, в делфи
Re[3]: DirectShow открывает видео
От: JsK  
Дата: 08.02.06 21:51
Оценка:
Здравствуйте, zinetz_victor, Вы писали:

_>ffmpeg например, если без ds; геморой (под windows) с тем, что компилится под gcc, но зато читает много чего кроме avi, декодирует почти все; доки неважные, но по примерам можно разобраться

_>но все, что у меня есть, в делфи

геморроя то мне как раз и не надо было :\... думал вполне тривиальная задача и справлюсь с решением за пару дней... но как оказалось DShow сильно запутан... и что меня сильно удивило — мало кто с такой проблемой (вывод кадра на поверхность) сталкивался.....

видимо с учетом острой нехватки времени придется применять некрасивые решения и отказавшись от сжатия divx использовать JPEG от чего размер ресурсов увеличится раз в десять =(...
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
...


в чем дело ??? ((( помогите пожалуйста а то запарился искать источник проблемы..
Re[2]: DirectShow открывает видео
От: JsK  
Дата: 10.10.08 18:20
Оценка:
никаких идей ?.. может у кого нибудь завалялись исходники вывода видео на поверхность ?.. я бы попробовал скомпилить у себя — будет работать или нет..
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.