DirectShow Теория Часть 1
Начиная с этой статьи, я углублюсь в теорию и начну с технологии COM.
Технология COM.
COM основана на объектах. С точки зрения прикладного программиста это набор компонент (объектов) наследующих интерфейс IUnknown ( подробнее о нем ниже ). COM не зависит от языка программирования, но работает только на Windows. COM представляет собой фундамент для таких технологий как OLE и ActiveX. С точки зрения С++ программиста IUnknown просто интерфейс содержащий всего три чисто виртуальных метода:
struct IUnknown {
virtual ULONG __stdcall AddRef() = 0;
virtual ULONG __stdcall Release() = 0;
virtual HRESULT __stdcall QueryInterface(const IID& iid,void** ppv) = 0;
};
Как я и сказал выше, COM не зависит от языка программирования, поэтому все функции вызываются по соглашению __stdcall для совместимости. Компонент COM как правило реализован в виде DLL, AddRef() и Release() позволяют управлять счетчиком ссылок на компонент, как только количество ссылок достигает нуля, компонент выгружается из памяти.
AddRef() увеличивает количество ссылок, а Release() соответственно его уменьшает, забыв вызвать Release() и не обнулив счетчик ссылок компонента мы обрекаем его висеть у нас в памяти.
QueryInterface не так прост. Это метод предназначенный для запроса интерфейсов у компонента. IID – идентификатор интерфейса, ppv – указатель в который следует передать этот интерфейс в том случае, если компонент его поддерживает.
HRESULT это длинное целое сообщающее о результате выполнения функции. Первый бит указывает на успех \ провал операции, последние 16 битов содержат код возврата, остальные 15 содержат информацию о средстве, вернувшем результат.
Для определения результата вызова функции нужно использовать специальные макросы, как показано ниже:
//……
IMyInterface* ptr = 0;
HRESULT hr = interface->QueryInterface(IID_IMyInterface,&ptr);
if (SUCCEEDED(hr))
//использование ptr
else if (FAILED(hr))
error();
//…….
Так же можно получить сообщение об ошибке при помощи Windows API:
//…..
void showError(LPCTSTR str, HRESULT hr)
{
void* temp;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
0,
hr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&temp,
0,
0
);
cout << str << endl;
cout << “Error (” << hex << hr << “): ” << (LPTSTR)temp << endl;
}
Скопировать интерфейс можно так:
//….
IMyInterface *ptr;
ptr = myIfacePtr;
ptr->AddRef();
//….
Для освобождения интерфейса нужно вызвать Release():
ptr->Release();
Как устроен DirectShow.
DirectShow полностью основан на COM. По сути дела это набор объектно-ориентированных компонентов COM. Но об этом позже, сейчас давайте разберемся с общими принципами. Первое, что нужно сделать, для того, что бы комфортно программировать DirectShow нужно скачать Microsoft SDK в состав которого входит приложение Graph Edit. И так, все по порядку.
Программирование DirectShow основано на графах. Графы строятся из элементов, которыми являются кодеки, декомпрессоры и т.д. У каждого элемента есть каналы, входные и выходные, по которым элементы соединяются между собой. Несколько соединенных между собой элементов образуют граф. Например, давайте посмотрим, как будет выглядеть граф, воспроизводящий AVI видео файл в Graph Edit. Открываем Graph Edit, его окно вы можете видеть на рисунке ниже.
Идем в меню и делаем следующее: File->Render Media File или просто нажимаем Ctrl+R. Открывается окно в котором предлагается выбрать файл для воспроизведения, я рекомендую вам так же как и я выбрать видео файл AVI.
Это граф, который получился у меня. У вас он может выглядеть иначе, это зависит от установленных в системе кодеков. Для того, что бы проиграть файл, делаем следующее: Graph -> Play или просто нажимаем Enter. Вот, что получилось у меня:
Насмотревшись вдоволь, продолжим разбираться. Только что, мы увидели в принципе суть DirectShow – граф. Т.е. для программного воспроизведения файла мы должны программно, используя интерфейсы DirectShow построить такой же граф. Для начала построим такой же граф в Graph Edit. Что бы не усложнять себе задачу, откройте второй экземпляр программы. И так приступим. Для начала нам нужно добавить фильтр источник. Для этого идем в Graph -> Insert Filters или нажимаем Ctrl + F. Перед вами появится окно как на картинке ниже:
Раскрываем узел Direct Show Filters и выбираем там File Source (Async.). Выбираем файл, которому он будет соответствовать. Далее смотрим в первый экземпляр Grph Edit и во втором воссоздаем граф. Рекомендую все же поковыряться в Graph Edit и воссоздать таки граф. В следующей статье мы перейдем к обсуждению концепций Direct Show. А потом детально обсудим его интерфейсы.




Комментарии
Спасибо, Дмитрий!
Просто, понятно и самое главное, тема рассказывается с самого начала.
Пиши пожалуйста дальше.
YO! Брателло! Спасибо конечно, но где продолжение??
И снова Direct Show. Теория Часть 2.