C++和DirectShow

发布于 2024-10-07 07:48:04 字数 158 浏览 1 评论 0原文

我刚刚开始接触 DirectShow 编程,DirectShow API 的“C”特性让我感到毛骨悚然。无尽的返回码而不是异常,addref/release 到处都是,函数将指针指向指针...

是否有任何“C++ 友好”的 DirectShow 编程包装器隐藏了所有 COM 丑陋之处?

I'm just getting started with DirectShow programming, and the 'C' nature of the DirectShow API is making my skin crawl. Endless return codes instead of exceptions, addref/release all over the place, functions taking pointer to pointers...

Are there any 'C++ friendly' wrappers for DirectShow programming that hide all the COM ugliness underneath.?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

抽个烟儿 2024-10-14 07:48:04

对于 98% 的 DirectShow 代码,您应该永远不会看到对 AddRef 或 Release 的调用。始终使用 CComPtr<> 。这条规则有一些小的例外。

此外,了解锁定也很重要,CCritSec 和 CAutoLock 也很重要;我再次避免手动锁定 CCritSec 实例,因为这是导致应用程序死锁的好方法。

另外,这段代码非常方便:

#include <dxerr9.h>

...

HRESULT hr = S_OK;

... something goes wrong ...

CString err(::DXGetErrorString9(hr));
err += ::DXGetErrorDescription9(hr);

最后,确保您使用的是 DShow 事件。各种有用的信息都来自 DShow 图表中的事件,令人惊讶的是有多少应用程序没有实现这一点(或者没有正确实现)。

不久前,我写了这个 ,我将一些使用 DShow 的陷阱放在一起。可悲的是,我知道这些陷阱,因为我几乎在所有这些方面都搞砸了。

For 98% of DirectShow code, you should never see a call to AddRef or Release. Always use CComPtr<>. There are a few minor exceptions to this rule.

Also, understanding locking is important, as is CCritSec and CAutoLock; once again, I'd avoid manually locking CCritSec instances because it's a good way to deadlock an application.

Also, this code can be pretty handy:

#include <dxerr9.h>

...

HRESULT hr = S_OK;

... something goes wrong ...

CString err(::DXGetErrorString9(hr));
err += ::DXGetErrorDescription9(hr);

Lastly, make sure you're using the DShow eventing. All sorts of useful info comes in over events from a DShow graph, and it's surprising how many applications don't have this implemented (or have it implemented incorrectly).

A while ago, I wrote this, which I've sort of tossed together a few of the pitfalls of working with DShow. Sadly, I know these pitfalls because I've screwed up in almost all these ways.

榆西 2024-10-14 07:48:04

CComPtr 是一个非常方便的工具,

除此之外,您只需要接受 HRESULTS 之类的东西即可。与例外相比,我更喜欢它们……发现它们更容易合作……每个人都有自己的特色。

CComPtr is a pretty handy one,

Beyond that you just have to live with things like the HRESULTS. I rather prefer them to exceptions ... find them much easier to work with ... each to their own.

夜灵血窟げ 2024-10-14 07:48:04

值得一提的是,DirectShow 是在 quartz.dll 中实现的,DirectShow 编辑服务是在 qedit.dll 中实现的。

您可以将这两个与编译器 COM 支持< /a> 从 Visual C++ 编写 DirectShow 客户端应用程序。

这是一个小型播放 media_file 示例(使用 cl /D_UNICODE playfile.cpp 进行编译):

#include <iostream> 

#import <quartz.dll> rename_namespace("dshow") 
#import <qedit.dll> rename_namespace("dshow")

// Required for CLSID_FilterGraph
#include <uuids.h> 
#pragma comment(lib, "strmiids.lib")

int wmain(int argc, wchar_t* argv[]) 
{  
    using namespace dshow;
    using namespace std;

    if (argc != 2)
    {
        wcout << "Usage: play media_file" << endl;
        return 1;
    }

    struct ComInitializer
    {
        ComInitializer() 
        { 
            ::CoInitialize(0);
        }

        ~ComInitializer()
        {
            ::CoUninitialize();
        }
    } comInit;

    try 
    { 
        IGraphBuilderPtr graphBuilder; 
        graphBuilder.CreateInstance(CLSID_FilterGraph); 

        graphBuilder->RenderFile(argv[1], 0);

        IMediaControlPtr mediaControl = graphBuilder;
        mediaControl->Run();

        wcout << "Press Return to stop playback." << endl;
        wcin.get();

        mediaControl->Stop();
    } 
    catch (const _com_error& err)
    {
        wcout << L"Error code: 0x" << hex << err.Error() << endl;
    }
} 

我在构建控制台时使用了此方法 DirectShow oggenc 应用程序。

It's worth knowing that DirectShow is implemented in quartz.dll, and DirectShow Editing Services in qedit.dll.

You can use those two with the Compiler COM Support from Visual C++ to write DirectShow client applications.

Here is a small play media_file example (compile with cl /D_UNICODE playfile.cpp):

#include <iostream> 

#import <quartz.dll> rename_namespace("dshow") 
#import <qedit.dll> rename_namespace("dshow")

// Required for CLSID_FilterGraph
#include <uuids.h> 
#pragma comment(lib, "strmiids.lib")

int wmain(int argc, wchar_t* argv[]) 
{  
    using namespace dshow;
    using namespace std;

    if (argc != 2)
    {
        wcout << "Usage: play media_file" << endl;
        return 1;
    }

    struct ComInitializer
    {
        ComInitializer() 
        { 
            ::CoInitialize(0);
        }

        ~ComInitializer()
        {
            ::CoUninitialize();
        }
    } comInit;

    try 
    { 
        IGraphBuilderPtr graphBuilder; 
        graphBuilder.CreateInstance(CLSID_FilterGraph); 

        graphBuilder->RenderFile(argv[1], 0);

        IMediaControlPtr mediaControl = graphBuilder;
        mediaControl->Run();

        wcout << "Press Return to stop playback." << endl;
        wcin.get();

        mediaControl->Stop();
    } 
    catch (const _com_error& err)
    {
        wcout << L"Error code: 0x" << hex << err.Error() << endl;
    }
} 

I've used this method in building a console DirectShow oggenc application.

农村范ル 2024-10-14 07:48:04

如果您找不到包装器,那么您可能会受益于我的博客文章中讨论的编码模式 "B true,或者 B 被抛出(使用 >> 投掷模式)"

该博客条目中的示例(这可以很容易地适应 COM,事实上,我首先“发明”了它用于 COM 使用):

std::ostream& operator<<( std::ostream& stream, wchar_t const s[] )
{
    Size const  nBytes      = wcstombs( 0, s, 0 );
    (nBytes >= 0)
        || throwX( "wcstombs failed to deduce buffer size" );

    Size const              bufSize     = nBytes + 1;
    std::vector< char >     buf( bufSize );

    // The count of bytes written does not include terminating nullbyte.
    wcstombs( &buf[0], s, bufSize )
        >> Accept< IsNonNegative >()
        || throwX( "wcstombs failed to convert string" );

    return (stream << &buf[0]);
}

博客中有一些讨论,显然每个人对合适的运算符等都有自己的偏好,所以我只是在这里提出一般原则

哦,应该添加,而不是 AddRefRelease 调用,只需使用一些 COM 智能指针。它们有很多(例如在 ATL/MFC 中,以及 Visual C++ 的“固有”),因此只需挑选您喜欢的一个即可。或者基于 boost::intrusive_ptr 创建您自己的示例。

干杯&呵呵,

If you don't find a wrapper then you can possibly benefit from the coding pattern discussed in my blog entry "B true, or B thrown! (Using the >> throwing pattern)".

Example from that blog entry (this can easily be adapted for COM, and in fact I first "invented" it for COM usage):

std::ostream& operator<<( std::ostream& stream, wchar_t const s[] )
{
    Size const  nBytes      = wcstombs( 0, s, 0 );
    (nBytes >= 0)
        || throwX( "wcstombs failed to deduce buffer size" );

    Size const              bufSize     = nBytes + 1;
    std::vector< char >     buf( bufSize );

    // The count of bytes written does not include terminating nullbyte.
    wcstombs( &buf[0], s, bufSize )
        >> Accept< IsNonNegative >()
        || throwX( "wcstombs failed to convert string" );

    return (stream << &buf[0]);
}

There is some discussion at the blog, evidently everybody has his or her own preference for suitable operators etc., so I'm just throwing in the general principle here.

Oh, should add, instead of AddRef and Release calls, just use some COM smart pointer. There are so many of them around (e.g. in ATL/MFC, and the "intrinsic" one for Visual C++) that it's just pick and choose the one you like. Or create your own e.g. based on boost::intrusive_ptr.

Cheers & hth.,

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文