Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » Разное - [решено] *DirectShow* | не работает пример из SDK

Ответить
Настройки темы
Разное - [решено] *DirectShow* | не работает пример из SDK
pva pva вне форума

Аватара для pva

Ветеран


Сообщения: 1180
Благодарности: 279

Профиль | Отправить PM | Цитировать


Изменения
Автор: pva
Дата: 01-10-2009
Описание: забыл специализацию шаблона com_object
Здравствуйте мною глубокоуважаемые обитатели форума, да восхвалится имя ваше (во веки веков). У меня почему-то пример из MSDN перечисления устройств DirectShow захвата видео работает не так, как там описано:
Код: Выделить весь код
// есть шаблон com_object<typename Interface>, который выполняет IUnknown::Release(),
// функции stop_error и log_error, которые сообщают результат HRESULT,
// stop* выдаёт исключение в случае ошибки, log* возвращает булевскую удачу-неудачу.

    IEnumMoniker *dev_enum_val = 0;

    // получаем перечислитель устройств
    // com_object<Interface>::com_object<Interface>(Interface** intf, HRESULT hr) проверяет stop_error(hr) и инициализирует
    // указатель на интерфейс значением *intf
    com_object<IEnumMoniker> dev_enum(&dev_enum_val,
            // com_object<Interface>::com_object<Interface>(const GUID&) использует CoCreateInstance для создания объекта
            com_object<ICreateDevEnum>(CLSID_SystemDeviceEnum)->CreateClassEnumerator(
                        CLSID_VideoInputDeviceCategory, &dev_enum_val, 0));

    // перебираем устройства внутри категории
    IMoniker* dev_item_val=0;

    while(!log_error(dev_enum->Next(1, &dev_item_val, 0))
    {
         com_object<IMoniker> dev_item(&dev_item_val, 0);
         // я проверял, dev_item->GetDisplayName(0, 0, &name) даёт правильный результат,
         // но дальше всё не по сценарию:

         // получаем набор свойств устройства
         IPropertyBag* prop_bag = 0;

         if(log_error(dev_item->BindToStorage(0, 0, IID_IPropertyBag, (void **)&prop_bag_val)))
         {
            com_object<IPropertyBag> prop_bag(&prop_bag_val, 0);

           // меня устраивает любое из свойств 
           variant<wstring> friendly_name;
            if (
                log_error(prop_bag->Read(L"Description", friendly_name.arg(), 0)) ||           // ошибка: неверный доступ к памяти
                log_error(prop_bag->Read(L"FriendlyName", friendly_name.arg(), 0)) ||       // ошибка: неверный доступ к памяти
                log_error(prop_bag->Read(L"Name", friendly_name.arg(), 0)))                     // ошибка: неверный доступ к памяти
            {
                // здесь, судя по примеру из MSDN, должно отображаться человеческое имя устройства
                // но до сюда не доходит :(
                MessageBoxW(Handle, friendly_name.value().c_str(), L"Enum", MB_OK);
            }
        }
    }
вспомогательный код (если понадобится):
Код: Выделить весь код
// шаблон com_object

void stop_error(HRESULT hr);
bool log_error(HRESULT hr);

template<typename Interface>
class com_object
{
public:
	static const GUID& id();

	~com_object() {_ptr->Release();}
	com_object(const GUID& type_id, IUnknown* parent=0);
	com_object(Interface** outer_interface, HRESULT hr);
	com_object(com_object const& other) throw() : _ptr(other._ptr) {_ptr->AddRef();}
	template<typename Interface2> com_object(com_object<Interface2> const&);
	Interface* operator->() throw() {return _ptr;}
	Interface* get() const throw() {return _ptr;}

private:
	Interface* _ptr;
};

template<typename Interface>
com_object<Interface>::com_object(const GUID& type_id, IUnknown* parent) : _ptr()
{
    stop_error(CoCreateInstance(type_id, parent, CLSCTX_INPROC_SERVER, id(), reinterpret_cast<void**>(&_ptr)));
}

template<typename Interface> com_object<Interface>::com_object(Interface** outer_interface, HRESULT hr) : _ptr(*outer_interface)
{
    stop_error(hr);
    if (!*outer_interface) throw runtime_error("got null interface");
}

template<typename Interface> template<typename Interface2>
com_object<Interface>::com_object(com_object<Interface2> const& other) : _ptr()
{
    stop_error(other.get()->QueryInterface(id(), reinterpret_cast<void**>(_ptr)));
}


// шаблон variant

template<typename DataT>
class variant
{
public:
    static const VARTYPE type_id();
    ~variant()              {VariantClear(&_arg);}
    variant()               {VariantInit(&_arg);}
    variant(const variant& v2) {VariantCopy(&_arg, &v2._arg);}
    template<typename Data2>
    variant(const variant<Data2>& v2) {VariantChangeType(&_arg, &v2._arg, 0, type_id());}
    void reset()            {VariantClear(&_arg);}
    bool is_clear() const     {return _arg.vt == VT_EMPTY;}
    bool is_null() const      {return _arg.vt == VT_NULL;}
    bool is_error() const     {return _arg.vt == VT_ERROR;}
    DataT value() const;

    // для вызовов API
    VARIANT* arg() {return &_arg;}

private:
    VARIANT _arg;

    const VARIANT& _assert_value() const {
        // проверка что именно нужного типа (а не VT_EMPTY например)
        if (_arg.vt!=type_id()) throw logic_error("variant::_assert_value of different type");
        return _arg;
    }
};

template<> const VARTYPE variant<unsigned>::type_id(){return VT_UI4;}
template<> unsigned variant<unsigned>::value() const {return _assert_value().lVal;}
template<> const VARTYPE variant<int>::type_id()     {return VT_I4;}
template<> int variant<int>::value() const           {return _assert_value().ulVal;}
template<> const VARTYPE variant<float>::type_id()   {return VT_R4;}
template<> float variant<float>::value() const       {return _assert_value().fltVal;}
template<> const VARTYPE variant<double>::type_id()  {return VT_R8;}
template<> double variant<double>::value() const     {return _assert_value().dblVal;}
template<> const VARTYPE variant<wstring>::type_id() {return VT_BSTR;}
template<> wstring variant<wstring>::value() const   {return wstring(_assert_value().bstrVal);}
Теперь отдельный вопрос про получение текстового описания сообщения об ошибке: У меня возничает ситуация, когда система не может выдать текстовое сообщение (FormatMessage выдаёт пустую строку). Как с этим бороться? Мне же надо знать, чем он недоволен
Код: Выделить весь код
bool log_error(HRESULT hr)
{
    if (hr)
    {
        hr &= 0xffff;

        char *ddstr;
        if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
                0, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*) &ddstr, 0, 0))
        {
            MessageBoxA(0, ddstr, 0, MB_OK|MB_ICONERROR);
            LocalFree(ddstr);
        }
        else
        {
            ostringstream ss;
            ss << "Undefined error 0x" << hex << hr;
            MessageBoxA(0, ss.str().c_str(), 0, MB_OK|MB_ICONERROR);
        }
    };

    return hr==0;
}

void stop_error(HRESULT hr)
{
    if (!log_error(hr))
    {
    	throw runtime_error("check_error");
    };
}
Специализация шаблона com_object для идентификации интрефейсов (простое правило):
Код: Выделить весь код
#include <control.h>
#include <strmif.h>
#include <uuids.h>
template<> GUID const&    com_object<ICreateDevEnum>::id()        {return IID_ICreateDevEnum;}
template<> GUID const&    com_object<IPropertyBag>::id()          {return IID_IPropertyBag;}
template<> GUID const&    com_object<IBaseFilter>::id()           {return IID_IBaseFilter;}
template<> GUID const&    com_object<ICaptureGraphBuilder2>::id()        {return IID_ICaptureGraphBuilder2;}
template<> GUID const&    com_object<IGraphBuilder>::id()           {return IID_IGraphBuilder;}
template<> GUID const&    com_object<IVideoWindow>::id()           {return IID_IVideoWindow;}
template<> GUID const&    com_object<IMediaControl>::id()           {return IID_IMediaControl;}

Отправлено: 08:33, 01-10-2009

 

Аватара для Delirium

Ветеран


Сообщения: 5624
Благодарности: 936

Профиль | Отправить PM | Цитировать


Цитата pva:
У меня почему-то пример из MSDN »
А какая версия MSDN? Их документация часто страдает опечатками и неточностями.

-------

Пройденные курсы:
[Microsoft №10174 Sharepoint], [SharePoint]
Мои проекты:[CheckAdmins], [NetSend7], [System Uptime], [Remote RAdmin LogViewer],[Netdom GDI], [Holidays - напоминалка о днях рождения]

А я офис-гуру :)


Отправлено: 08:38, 01-10-2009 | #2



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.

pva pva вне форума Автор темы

Аватара для pva

Ветеран


Сообщения: 1180
Благодарности: 279

Профиль | Отправить PM | Цитировать


Цитата Delirium:
А какая версия MSDN? »
Которая у них на сайте в онлайне

Проблема решена очень просто: ти ли я недоглядел, то ли они лоханулись, если сделать всё по аналогии с описанием группы интерфейсов IEnumXXXX, то получается так:
Код: Выделить весь код
// дописал wostream& operator<<(wostream&, const GUID&);
// дописал log_message(const wstring&); которая добавляет строчку в ListView

    unsigned long cnt_fetched = 0;
    IMoniker* dev_item_val[1]; // здесь изменение
    // беру только по одному объекту за раз (хотя можно и по 100 взять),
    // только чтобы соблюсти правила безопасных исключений C++

    while (log_error(filter_mons->Next(1, dev_item_val, &cnt_fetched)) && cnt_fetched)
    {
        com_object<IMoniker> dev_item(&dev_item_val[0], 0);

        {
            GUID dev_guid;
            wchar_t* str_name;
            stop_error(dev_item->GetClassID(&dev_guid));
            stop_error(dev_item->GetDisplayName(0, 0, &str_name));

            wostringstream ss;
            ss << dev_guid << str_name;
            __alloc->Free(str_name);

            log_message(ss.str());
        }

        IPropertyBag* prop_bag_val;
        com_object<IPropertyBag> prop_bag(&prop_bag_val,
            dev_item->BindToStorage(0, 0, IID_IPropertyBag, (void**)&prop_bag_val));

        variant<wstring> var_str;
        if (log_error(prop_bag->Read(L"FriendlyName", var_str.arg(), 0)))
        {
            log_message(var_str.value());
        }
    }
И ещё использовал IFilterMapper2 чтобы получить список моникеров устройств. По крайней мере так сработало правильно.
Появились новые вопросы, некоторые помещу в другое темы; Тов. модератор, если сочтёшь нужным, собери обратно в одну тему

Вопрос: имя фильтра DirectShow содержит 2 классида: категория и устройство. Как их можно попрость COM узнать, что соответствует этим классидам? Через IPropertyBag? как узнать, какие вообще свойства есть в IPropertyBag (у меня не получилось создать IPropertyBag2, который это умеет)?

Отправлено: 12:52, 01-10-2009 | #3

pva pva вне форума Автор темы

Аватара для pva

Ветеран


Сообщения: 1180
Благодарности: 279

Профиль | Отправить PM | Цитировать


пример заработал, был косяк в месте IEnumMoniker, нашёл способ получить описание фильтров: http://forum.oszone.net/thread-151991.html
чтобы получить список категорий: http://msdn.microsoft.com/en-us/libr...55(VS.85).aspx

вот что меня удивляет - это как с этим косяком у других работает, кто исходники в инете выкладывает.. у меня ни один не заработал

Отправлено: 12:47, 03-10-2009 | #4



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » Разное - [решено] *DirectShow* | не работает пример из SDK

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
Выпущен Windows 7 beta SDK OSZone News Новости и события Microsoft 5 17-01-2009 10:26
Субтитры в DirectShow tri777ki Видео и аудио: обработка и кодирование 5 25-10-2007 19:46
Посоветуйте идеальный баланс CPU - GPU. Using DirectX SDK, MathCad & 3DMax. SeriousDEN Выбор отдельных компонентов компьютера и конфигурации в целом 23 18-09-2006 13:11
[решено] Пример схемы сети со спутниковым Интернетом. Работать будет? Ded_Ts Сетевые технологии 3 10-07-2006 23:19
*Решено* | Помогите скомпилить пример на С xgg Программирование и базы данных 3 23-03-2005 21:07




 
Переход