Здравствуйте, VAstronom, Вы писали:
Нужно использовать SampleGrabber фильтр. В нем изображение еще не ушло в видео память и потому более быстро доступно через интерфейс IMediaSample. Либо можно написать свой фильтр который будет делать то что надо, благо примеров в СДК полно.
VA>Стоит задача анализа содержимого видео файла. Я больше инженер, чем программист, но пришлось разбираться с DirectShow, поэтому сильно не
VA>пинайте… Использую Builder6.
VA>Необходимо последовательно (иногда пропуская) сменять кадры, затем извлекать их содержимое для анализа. Соответственно на экране
VA>исходный кадр отображаться не должен, т.к. там будет измененная картинка.
VA>Для перехода к кадру использую связку
VA> pMediaSeeking->SetPositions(&Nf,AM_SEEKING_AbsolutePositioning,NULL,AM_SEEKING_NoPositioning);
VA> pBasicVideo->GetCurrentImage(&lBufSize,(long*)pDIB);
VA>но GetCurrentImage жутко тормозит и на получение одного кадра уходит пол секунды времени!
VA>Подскажите пожалуйста, как можно повысить быстродействие?
VA>Выкладываю весь блок кода, возможно ошибка в самом подходе к решению задачи?
VA>VA>#include <vcl.h>
VA>#include <dshow.h>
VA>#include "Unit1.h"
VA>#include "c_DirectShow.h" // объявления функций ниже
VA>#pragma comment (lib, "strmiids.lib") // IVideoFrameStep
VA>//------------------------------------------------------------------------------//
VA>HRESULT hr;
VA>IGraphBuilder *pGraphBuilder;
VA>IBasicVideo *pBasicVideo;
VA>IMediaSeeking *pMediaSeeking;
VA>//IVideoWindow *pVideoWindow;
VA>BYTE *pDIB; // попиксельный массив видео кадра с заголовком.
VA>extern Graphics::TBitmap *mFRAME; // моя результирующая картинка
VA>//==============================================================================//
VA>//------------------------------------------------------------------------------//
VA>// Инициализация и построение постоянных графов. //
VA>//------------------------------------------------------------------------------//
VA>int OpenDirShow()
VA>{
VA> pGraphBuilder = NULL; // Интерфейс менеджера графа-фильтров
VA> pBasicVideo = NULL;
VA> pMediaSeeking = NULL;
VA> //--------------------------------------------------------------------------
VA> hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); // Инициализируем библиотеку COM
VA> if(FAILED(hr)) return 1;
VA> hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, // Создание менеджера графа-фильтров
VA> IID_IGraphBuilder, (void **)&pGraphBuilder);
VA> if(FAILED(hr)) return 2;
VA> hr = pGraphBuilder->QueryInterface(IID_IBasicVideo,(void**)&pBasicVideo);
VA> if(FAILED(hr)) return 3;
VA> hr = pGraphBuilder->QueryInterface(IID_IMediaSeeking,(void**)&pMediaSeeking);
VA> if(FAILED(hr)) return 4;
VA> //--------------------------------------------------------------------------
VA> return 0;
VA>}
VA>//------------------------------------------------------------------------------//
VA>// освобождение ресурсов. //
VA>//------------------------------------------------------------------------------//
VA>void CloseDirShow()
VA>{
VA> if(pMediaSeeking) pMediaSeeking->Release();
VA> if(pBasicVideo) pBasicVideo->Release();
VA> if(pGraphBuilder) pGraphBuilder->Release();
VA> CoUninitialize();
VA>}
VA>//------------------------------------------------------------------------------//
VA>// Открываем видео файл (Для Unicode) //
VA>// Для не Unicode hr = pGraph->RenderFile((LPCWSTR)pcFileName, NULL); //
VA>//------------------------------------------------------------------------------//
VA>// Получает: //
VA>// - имя файла //
VA>// Возвращает: //
VA>// - количество кадров //
VA>// - размер кадра //
VA>//------------------------------------------------------------------------------//
VA>int OpenAVI(char *pcFileName, __int64 *Lframe, long *Xframe, long *Yframe)
VA>{
VA> const GUID TIME_FORMAT_FRAME = { 0x7b785570, 0x8c82, 0x11cf, { 0xbc, 0xc, 0x0, 0xaa, 0x0, 0xac, 0x74, 0xf6}};
VA> __int64 Nframe;
VA> WCHAR wFileName[MAX_PATH];
VA> MultiByteToWideChar(CP_ACP, 0, pcFileName, -1, wFileName, MAX_PATH); // строку преобразую в Юникод
VA> hr = pGraphBuilder->RenderFile((LPCWSTR)wFileName, NULL); // открываю файл
VA> if(FAILED(hr)) return 1;
VA> pMediaSeeking->SetTimeFormat(&TIME_FORMAT_FRAME); // формат "кадры"
VA> pMediaSeeking->GetDuration(Lframe); // количество кадров
VA> pBasicVideo->GetVideoSize(Xframe,Yframe); // размер кадра
VA>// hr = pGraphBuilder->QueryInterface(IID_IVideoWindow, (void**)&pVideoWindow); // параметры отображения (где и как)?
VA>// if(FAILED(hr)) return 2;
VA> ChgFrame(1, *Lframe, *Xframe, *Yframe); // отобразили кадр
VA> return 0;
VA>}
VA>//------------------------------------------------------------------------------//
VA>// При закрытии видео файла освобождаем память занятую под кадр //
VA>//------------------------------------------------------------------------------//
VA>void CloseAVI()
VA>{
VA> // if(pVideoWindow) pVideoWindow->Release();
VA> delete [] pDIB;
VA>}
VA>//------------------------------------------------------------------------------//
VA>// Произвольный доступ к заданному кадру. Рисует этот кадр на Form1->Image1 //
VA>// Получает: //
VA>// - признак инициализации (1 - при открытии файла) или работы (0) //
VA>// - номер кадра для показа //
VA>// - размер кадра //
VA>//------------------------------------------------------------------------------//
VA>void ChgFrame(bool init, __int64 Nf, long Xf, long Yf)
VA>{
VA> TDateTime TTT0,TTT1;
VA> AnsiString As[4];
VA> static long lBufSize; // размер данных кадра (шапка + данные)
VA> static HDC wrkDC;
VA> static BITMAPINFOHEADER *bmih;
VA> static BITMAPINFO bmi;
VA> static HBITMAP hbmp;
VA> static char *pData;
VA> TTT0=Time();
VA> // переход к указному кадру
VA> pMediaSeeking->SetPositions(&Nf,AM_SEEKING_AbsolutePositioning,NULL,AM_SEEKING_NoPositioning);
VA>// pVideoFrameStep->Step(Nf, NULL);
VA> if (init==1) // при инициализации
VA> {
VA> wrkDC = GetDC(0); // ...\dx9sdk\Samples\C++\DirectShow\Editing\TransViewer
VA> //wrkDC = CreateCompatibleDC(NULL);
VA> pBasicVideo->GetCurrentImage(&lBufSize,NULL); // определяем размер памяти под кадр
VA> pDIB=new BYTE[lBufSize]; // резерв памяти под кадр
VA> mFRAME->PixelFormat = pf24bit;
VA> mFRAME->Width =Xf;
VA> mFRAME->Height=Yf;
VA> }
VA> //----------------------------------------------------------------------------
VA> TTT1=Time();
VA> DateTimeToString(As[0], "ss.zzzz", TTT1-TTT0);
VA> pBasicVideo->GetCurrentImage(&lBufSize,(long*)pDIB); // получаю данные кадра
VA> TTT0=Time();
VA> DateTimeToString(As[1], "ss.zzzz", TTT0-TTT1);
VA> pData = (char*)(int)pDIB+sizeof(BITMAPINFOHEADER); // адрес первого пикселя
VA> TTT1=Time();
VA> DateTimeToString(As[2], "ss.zzzz", TTT1-TTT0);
VA> bmih = (BITMAPINFOHEADER*)pDIB; // махинации для дальнейшей конвертации изображения
VA> ZeroMemory(&bmi, sizeof(BITMAPINFO));
VA> CopyMemory(&(bmi.bmiHeader), bmih, sizeof(BITMAPINFOHEADER));
VA> hbmp=CreateDIBitmap(wrkDC,bmih,CBM_INIT,pDIB,(PBITMAPINFO)&bmi,DIB_RGB_COLORS);
VA> mFRAME->Handle=hbmp;
VA> TTT0=Time();
VA> DateTimeToString(As[3], "ss.zzzz", TTT0-TTT1);
VA> Form1->Caption="Frame "+IntToStr(Nf)+" "+As[0]+" "+As[1]+" "+As[2]+" "+As[3];
VA> Form1->Image1->Canvas->Draw(0,0, mFRAME); // отрисовка картинки.
VA> Form1->Image1->Refresh();
VA>}
VA>