opencv VideoCapture 不能采集uvc摄像头的MJPEG 数据_videocapture uvc_smilestone322的博客-程序员秘密

                bool bRet = capture.set(CV_CAP_PROP_FOURCC, CV_FOURCC('M', 'J', 'P', 'G'));
                if (!bRet)
                {
                    printf("set format failed \n");
                }

                capture.set(CV_CAP_PROP_FPS, 30);
                capture.set(CV_CAP_PROP_FRAME_WIDTH, 640);
                capture.set(CV_CAP_PROP_FRAME_HEIGHT, 480);

   这样是获取不到MJPEG 视频图像。 用的Opencv的版本是 2410

 

Using the Sample Grabber-- 转自

https://docs.microsoft.com/en-us/windows/win32/directshow/using-the-sample-grabber

[This API is not supported and may be altered or unavailable in the future.]

The Sample Grabber filter is a transform filter that can be used to grab media samples from a stream as they pass through the filter graph.

If you simply want to grab a bitmap from a video file, it is easier to use the Media Detector (MediaDet) object. See Grabbing a Poster Frame for details. The Sample Grabber is more flexible, however, because it works with nearly any media type (see ISampleGrabber::SetMediaType for the few exceptions), and offers more control to the application.

Create the Filter Graph Manager

To start, create the Filter Graph Manager and query for the IMediaControl and IMediaEventEx interfaces.

C++Copy

    IGraphBuilder *pGraph = NULL;
    IMediaControl *pControl = NULL;
    IMediaEventEx *pEvent = NULL;


    HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, 
        CLSCTX_INPROC_SERVER,IID_PPV_ARGS(&pGraph));
    if (FAILED(hr))
    {
        goto done;
    }

    hr = pGraph->QueryInterface(IID_PPV_ARGS(&pControl));
    if (FAILED(hr))
    {
        goto done;
    }

    hr = pGraph->QueryInterface(IID_PPV_ARGS(&pEvent));
    if (FAILED(hr))
    {
        goto done;
    }

Add the Sample Grabber to the Filter Graph

Create an instance of the Sample Grabber filter and addit to the filter graph. Query the Sample Grabber filter for the ISampleGrabber interface.

C++Copy

    IBaseFilter *pGrabberF = NULL;
    ISampleGrabber *pGrabber = NULL;


    // Create the Sample Grabber filter.
    hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
        IID_PPV_ARGS(&pGrabberF));
    if (FAILED(hr))
    {
        goto done;
    }

    hr = pGraph->AddFilter(pGrabberF, L"Sample Grabber");
    if (FAILED(hr))
    {
        goto done;
    }

    hr = pGrabberF->QueryInterface(IID_PPV_ARGS(&pGrabber));
    if (FAILED(hr))
    {
        goto done;
    }

Set the Media Type

When you first create the Sample Grabber, it has no preferred media type. This means you can connect to almost any filter in the graph, but you would have no control over the type of data that it received. Before building the rest of the graph, therefore, you must set a media type for the Sample Grabber, by calling the ISampleGrabber::SetMediaType method.

When the Sample Grabber connects, it will compare this media type against the media type offered by the other filter. The only fields that it checks are the major type, subtype, and format type. For any of these, the value GUID_NULL means "accept any value." Most of the time, you will want to set the major type and subtype. For example, the following code specifies uncompressed 24-bit RGB video:

C++Copy

    AM_MEDIA_TYPE mt;
    ZeroMemory(&mt, sizeof(mt));
    mt.majortype = MEDIATYPE_Video;
    mt.subtype = MEDIASUBTYPE_RGB24;

    hr = pGrabber->SetMediaType(&mt);
    if (FAILED(hr))
    {
        goto done;
    }

Build the Filter Graph

Now you can build the rest of the filter graph. Because the Sample Grabber will only connect using the media type you have specified, this lets you take advantage of the Filter Graph Manager's Intelligent Connect mechanisms when you build the graph.

For example, if you specified uncompressed video, you can connect a source filter to the Sample Grabber, and the Filter Graph Manager will automatically add the file parser and the decoder. The following example uses the ConnectFilters helper function, which is listed in Connect Two Filters:

C++Copy

    IBaseFilter *pSourceF = NULL;
    IEnumPins *pEnum = NULL;
    IPin *pPin = NULL;


    hr = pGraph->AddSourceFilter(pszVideoFile, L"Source", &pSourceF);
    if (FAILED(hr))
    {
        goto done;
    }

    hr = pSourceF->EnumPins(&pEnum);
    if (FAILED(hr))
    {
        goto done;
    }

    while (S_OK == pEnum->Next(1, &pPin, NULL))
    {
        hr = ConnectFilters(pGraph, pPin, pGrabberF);
        SafeRelease(&pPin);
        if (SUCCEEDED(hr))
        {
            break;
        }
    }

    if (FAILED(hr))
    {
        goto done;
    }

The Sample Grabber is a transform filter, so the output pin must be connected to another filter. Often, you may simply want to discard the samples after you are done with them. In that case, connect the Sample Grabber to the Null Renderer Filter, which discards the data that it receives.

The following example connects the Sample Grabber to the Null Renderer filter:

C++Copy

    IBaseFilter *pNullF = NULL;


    hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, 
        IID_PPV_ARGS(&pNullF));
    if (FAILED(hr))
    {
        goto done;
    }

    hr = pGraph->AddFilter(pNullF, L"Null Filter");
    if (FAILED(hr))
    {
        goto done;
    }

    hr = ConnectFilters(pGraph, pGrabberF, pNullF);
    if (FAILED(hr))
    {
        goto done;
    }

Be aware that placing the Sample Grabber between a video decoder and the video renderer can significantly hurt rendering performance. The Sample Grabber is a trans-in-place filter, which means the output buffer is the same as the input buffer. For video rendering, the output buffer is likely to be located on the graphics card, where read operations are much slower, compared with read operations in main memory.

Run the Graph

The Sample Grabber operates in one of two modes:

  • Buffering mode makes a copy of each sample before delivering the sample downstream.
  • Callback mode invokes an application-defined callback function on each sample.

This article describes buffering mode. (Before using callback mode, be aware that the callback function must be quite limited. Otherwise, it can drastically reduce performance or even cause deadlocks. For more information, see ISampleGrabber::SetCallback.) To activate buffering mode, call the ISampleGrabber::SetBufferSamples method with the value TRUE.

Optionally, call the ISampleGrabber::SetOneShot method with the value TRUE. This causes the Sample Grabber to halt after it receives the first media sample, which is useful if you want to grab a single frame from the stream. Seek to the desired time, run the graph, and wait for the EC_COMPLETE event. Note that the level of frame accuracy depends on the source. For example, seeking an MPEG file is often not frame accurate.

To run the graph as fast as possible, turn of the graph clock as described in Setting the Graph Clock.

The following example enables one-shot mode and buffering mode, runs the filter graph, and waits for completion.

C++Copy

    hr = pGrabber->SetOneShot(TRUE);
    if (FAILED(hr))
    {
        goto done;
    }

    hr = pGrabber->SetBufferSamples(TRUE);
    if (FAILED(hr))
    {
        goto done;
    }

    hr = pControl->Run();
    if (FAILED(hr))
    {
        goto done;
    }

    long evCode;
    hr = pEvent->WaitForCompletion(INFINITE, &evCode);

Grab the Sample

In buffering mode, the Sample Grabber stores a copy of every sample. The ISampleGrabber::GetCurrentBuffer method copies the buffer into a caller-allocated array. To determine the size of the array that is needed, first call GetCurrentBuffer with a NULL pointer for the array address. Then allocate the array and call the method a second time to copy the buffer. The following example shows these steps.

C++Copy

    // Find the required buffer size.
    long cbBuffer;
    hr = pGrabber->GetCurrentBuffer(&cbBuffer, NULL);
    if (FAILED(hr))
    {
        goto done;
    }

    pBuffer = (BYTE*)CoTaskMemAlloc(cbBuffer);
    if (!pBuffer) 
    {
        hr = E_OUTOFMEMORY;
        goto done;
    }

    hr = pGrabber->GetCurrentBuffer(&cbBuffer, (long*)pBuffer);
    if (FAILED(hr))
    {
        goto done;
    }

You will need to know the exact format of the data in the buffer. To get this information, call the ISampleGrabber::GetConnectedMediaType method. This method fills in an AM_MEDIA_TYPE structure with the format.

For an uncompressed video stream, the format information is contained in a VIDEOINFOHEADER structure. The following example shows how to get the format information for an uncompressed video stream.

C++Copy

    // Examine the format block.
    if ((mt.formattype == FORMAT_VideoInfo) && 
        (mt.cbFormat >= sizeof(VIDEOINFOHEADER)) &&
        (mt.pbFormat != NULL)) 
    {
        VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)mt.pbFormat;

        hr = WriteBitmap(pszBitmapFile, &pVih->bmiHeader, 
            mt.cbFormat - SIZE_PREHEADER, pBuffer, cbBuffer);
    }
    else 
    {
        // Invalid format.
        hr = VFW_E_INVALIDMEDIATYPE; 
    }

Note

The Sample Grabber does not support VIDEOINFOHEADER2.

 

Example Code

Here is the complete code for the previous examples.

Note

This example uses the SafeRelease function to release interface pointers.

 

C++Copy

#include <windows.h>
#include <dshow.h>
#include "qedit.h"

template <class T> void SafeRelease(T **ppT)
{
    if (*ppT)
    {
        (*ppT)->Release();
        *ppT = NULL;
    }
}



HRESULT WriteBitmap(PCWSTR, BITMAPINFOHEADER*, size_t, BYTE*, size_t);

HRESULT GrabVideoBitmap(PCWSTR pszVideoFile, PCWSTR pszBitmapFile)
{
    IGraphBuilder *pGraph = NULL;
    IMediaControl *pControl = NULL;
    IMediaEventEx *pEvent = NULL;
    IBaseFilter *pGrabberF = NULL;
    ISampleGrabber *pGrabber = NULL;
    IBaseFilter *pSourceF = NULL;
    IEnumPins *pEnum = NULL;
    IPin *pPin = NULL;
    IBaseFilter *pNullF = NULL;

    BYTE *pBuffer = NULL;

    HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, 
        CLSCTX_INPROC_SERVER,IID_PPV_ARGS(&pGraph));
    if (FAILED(hr))
    {
        goto done;
    }

    hr = pGraph->QueryInterface(IID_PPV_ARGS(&pControl));
    if (FAILED(hr))
    {
        goto done;
    }

    hr = pGraph->QueryInterface(IID_PPV_ARGS(&pEvent));
    if (FAILED(hr))
    {
        goto done;
    }

    // Create the Sample Grabber filter.
    hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
        IID_PPV_ARGS(&pGrabberF));
    if (FAILED(hr))
    {
        goto done;
    }

    hr = pGraph->AddFilter(pGrabberF, L&quot;Sample Grabber&quot;);
    if (FAILED(hr))
    {
        goto done;
    }

    hr = pGrabberF->QueryInterface(IID_PPV_ARGS(&pGrabber));
    if (FAILED(hr))
    {
        goto done;
    }

    AM_MEDIA_TYPE mt;
    ZeroMemory(&mt, sizeof(mt));
    mt.majortype = MEDIATYPE_Video;
    mt.subtype = MEDIASUBTYPE_RGB24;

    hr = pGrabber->SetMediaType(&mt);
    if (FAILED(hr))
    {
        goto done;
    }

    hr = pGraph->AddSourceFilter(pszVideoFile, L&quot;Source&quot;, &pSourceF);
    if (FAILED(hr))
    {
        goto done;
    }

    hr = pSourceF->EnumPins(&pEnum);
    if (FAILED(hr))
    {
        goto done;
    }

    while (S_OK == pEnum->Next(1, &pPin, NULL))
    {
        hr = ConnectFilters(pGraph, pPin, pGrabberF);
        SafeRelease(&pPin);
        if (SUCCEEDED(hr))
        {
            break;
        }
    }

    if (FAILED(hr))
    {
        goto done;
    }

    hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, 
        IID_PPV_ARGS(&pNullF));
    if (FAILED(hr))
    {
        goto done;
    }

    hr = pGraph->AddFilter(pNullF, L&quot;Null Filter&quot;);
    if (FAILED(hr))
    {
        goto done;
    }

    hr = ConnectFilters(pGraph, pGrabberF, pNullF);
    if (FAILED(hr))
    {
        goto done;
    }

    hr = pGrabber->SetOneShot(TRUE);
    if (FAILED(hr))
    {
        goto done;
    }

    hr = pGrabber->SetBufferSamples(TRUE);
    if (FAILED(hr))
    {
        goto done;
    }

    hr = pControl->Run();
    if (FAILED(hr))
    {
        goto done;
    }

    long evCode;
    hr = pEvent->WaitForCompletion(INFINITE, &evCode);

    // Find the required buffer size.
    long cbBuffer;
    hr = pGrabber->GetCurrentBuffer(&cbBuffer, NULL);
    if (FAILED(hr))
    {
        goto done;
    }

    pBuffer = (BYTE*)CoTaskMemAlloc(cbBuffer);
    if (!pBuffer) 
    {
        hr = E_OUTOFMEMORY;
        goto done;
    }

    hr = pGrabber->GetCurrentBuffer(&cbBuffer, (long*)pBuffer);
    if (FAILED(hr))
    {
        goto done;
    }

    hr = pGrabber->GetConnectedMediaType(&mt);
    if (FAILED(hr))
    {
        goto done;
    }

    // Examine the format block.
    if ((mt.formattype == FORMAT_VideoInfo) && 
        (mt.cbFormat >= sizeof(VIDEOINFOHEADER)) &&
        (mt.pbFormat != NULL)) 
    {
        VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)mt.pbFormat;

        hr = WriteBitmap(pszBitmapFile, &pVih->bmiHeader, 
            mt.cbFormat - SIZE_PREHEADER, pBuffer, cbBuffer);
    }
    else 
    {
        // Invalid format.
        hr = VFW_E_INVALIDMEDIATYPE; 
    }

    FreeMediaType(mt);

done:
    CoTaskMemFree(pBuffer);
    SafeRelease(&pPin);
    SafeRelease(&pEnum);
    SafeRelease(&pNullF);
    SafeRelease(&pSourceF);
    SafeRelease(&pGrabber);
    SafeRelease(&pGrabberF);
    SafeRelease(&pControl);
    SafeRelease(&pEvent);
    SafeRelease(&pGraph);
    return hr;
};

// Writes a bitmap file
//  pszFileName:  Output file name.
//  pBMI:         Bitmap format information (including pallete).
//  cbBMI:        Size of the BITMAPINFOHEADER, including palette, if present.
//  pData:        Pointer to the bitmap bits.
//  cbData        Size of the bitmap, in bytes.

HRESULT WriteBitmap(PCWSTR pszFileName, BITMAPINFOHEADER *pBMI, size_t cbBMI,
    BYTE *pData, size_t cbData)
{
    HANDLE hFile = CreateFile(pszFileName, GENERIC_WRITE, 0, NULL, 
        CREATE_ALWAYS, 0, NULL);
    if (hFile == NULL)
    {
        return HRESULT_FROM_WIN32(GetLastError());
    }

    BITMAPFILEHEADER bmf = { };

    bmf.bfType = &#39;MB&#39;;
    bmf.bfSize = cbBMI+ cbData + sizeof(bmf); 
    bmf.bfOffBits = sizeof(bmf) + cbBMI; 

    DWORD cbWritten = 0;
    BOOL result = WriteFile(hFile, &bmf, sizeof(bmf), &cbWritten, NULL);
    if (result)
    {
        result = WriteFile(hFile, pBMI, cbBMI, &cbWritten, NULL);
    }
    if (result)
    {
        result = WriteFile(hFile, pData, cbData, &cbWritten, NULL);
    }

    HRESULT hr = result ? S_OK : HRESULT_FROM_WIN32(GetLastError());

    CloseHandle(hFile);

    return hr;
}

 

 

 

 

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/smilestone322/article/details/88078817

智能推荐

在CentOS中安装setup工具_weixin_34389926的博客-程序员秘密

在CentOS中可以使用setup配置工具很方便地配置防火墙、网络、系统服务等配置项。如果采用最小化安装CentOS的话,默认没有安装该工具。下面我们手动安装下setup工具。1、安装setuptool# yum install setuptool2、安装防火墙设置# yum install system-config-securitylevel-tui3、安装网络设置...

mysql中的mysql设置utf8编码_如何设置mysql数据库为utf-8编码_weixin_39828193的博客-程序员秘密

2016-04-04 回答检查当前数据库编码。使用语句:show variables like ‘%character%’;show variables like’%collation%’;如果不是以上情况,需要将mysql编码设置为utf-8。具体步骤如下:如果安装mysql时安装了“mysql sever instance configuration wizard”,则只需要启动该程序进行相应...

红黑树删除操作_Faded0104的博客-程序员秘密

红黑树删除操作:红黑树要删除某个key值时,首先还是要查找该key值在树中的位置,查找方法和搜索二叉树方法相同.要删除的结点分为两种情况:1.有左右两个孩子都存在.两个孩子都存在时,在该节点的右子树中寻找其直接后继,找到后用其值替换要删除节点的值,然后问题转化为删除该节点的直接后继,直接后继是有一个右孩子或者没有孩子节点.2.只有一个孩子或者没有子孩子.以上两种均归纳为最多只有

解决umount.nfs: /data: device is busy 问题_漫步111的博客-程序员秘密

有时候我们需要umount某个挂载目录时会遇到如下问题:12[[email protected] /]# umount /data/umount.nfs: /data: device is busy通过这条命令查看:1234

传奇世界3D手游电脑版使用教程:无需安卓模拟器,tcgames完美适配_lemon5814的博客-程序员秘密

传奇世界3D 手游安卓模拟器怎么用?传奇世界3D手游怎么在电脑上玩?传奇世界3D手游是由腾讯独家代理,盛大游戏金牌制作团队倾力打造的全新3D传奇世界手游。已经开启双端不删档测试。这款全新ARPG游戏你们喜欢吗?那么怎么在电脑上玩传奇世界3D手游呢?今天教一下大家大屏玩传奇世界3D电脑版的方法:1、想在电脑上玩传奇世界3D手游只需要下载“tcgames”电脑玩手机游戏助手即可,无需再下载安卓模拟器。...

在SharePoint Server 2010中更改“我的网站”_weixin_33875564的博客-程序员秘密

  在安装SharePoint Server 2010的时候,创建的第一个站点是一个“NetBIOS名称”的网站,而这个时候,“我的网站”(或称“个人网站”),也是基于此NetBIOS名称的,例如,如果你的计算机名称是SP2010,则创建的SharePoint网站是http://sp2010,而“我的网站”则是“http://sp2010/my”,如果用防火墙(例如ISA Server)将此网...

随便推点

VSCode 快捷键 Windows版_一草二木的博客-程序员秘密

常用 Ctrl + Shift + P, F1 显示命令面板 Ctrl + P 快速打开 Ctrl + Shift + N 打开新窗口 Ctrl + Shift + W 关闭窗口 Ctrl + X 剪切(未选中文本的情况下,剪切光标所在行) Ctrl + C 复制(未选中文本的情况下,复制光标所在行) Alt + Up 向上移动行 Alt + Down 向下移动行 Shift

vue html2canvas 图片模糊问题_vue使用html2canvas模糊_Young_Gao的博客-程序员秘密

话不多说直接上代码首先确定好要被截图的div ,注意里面放 img 不要用 div 的 background-image 不然截图模糊的问题不能用以下代码解决&lt;div id="imageWrapper"&gt; // 这里是要被截图的div // 确保这里都是image,不要用 div 的 background-image // 不然截图模糊的问题无法...

qt qchart缩放后坐标轴间隔取整_dibao8283的博客-程序员秘密

使用qt的qchart显示数据曲线,坐标轴QValueAxis可以设置刻度间隔数量,但每个刻度的数值是根据坐标的极值除以间隔数量得到的,不一定是整数,导致曲线控件的显示刻度不适合观察。如图:纵坐标刻度带有小数,观察数据曲线时,就不容易计算曲线的波动。解决方法很简单,就是设置曲线坐标范围后,根据坐标范围计算设置间隔数量,让每个刻度都是整数,例如:范围-100~70...

Ubuntu20.04 通过netplan 配置静态ip_netplan配置ip_Tombon的博客-程序员秘密

ubuntu 从 17.10 开始,改成 netplan 方式配置,不在 /etc/network/interfaces 里固定 IP 的配置 ,配置写在或者类似名称的 yaml 文件里。

如果因“打杂”而辞职,你将永远一事无成_weixin_30588827的博客-程序员秘密

编者按:成长是人生中的一件非常重要的事情。但对于职场新人来说,在职业规划的初期,我们经常会遇到为数不少的大学生,仅仅因为干着一份“打杂”的工作,从而产生一种“被埋没”的感觉,于是接下来就对工作消极应对,甚至频繁跳槽,去寻找所谓的“前途远大的工作”。殊不知,如果一个人连“打杂”的角色都胜任不了,那么,我们又凭什么相信他能够做出惊天动地的大事来呢?浮躁和眼高手低,永远是年轻人职业规划道路上的大忌...

分布式事务管理以及解决方案_weixin_34107955的博客-程序员秘密

为什么80%的码农都做不了架构师?&gt;&gt;&gt; ...

推荐文章

热门文章

相关标签