DirectShow工程如何使用ffdshow

姚小白 2016-08-12 10:30:47
ffdshow官网下的一个安装包,安装后再graphedit中是可以使用ffdshow解码了,但是出现2个疑问:

1. 我要在工程里面使用,需要加载ffdshow.ax,加载时需要CLSID,请问这个怎么得到? 下的安装包没有头文件啊,并且在获取ffdshow的接口时也需要CLSID。

2.在graphedit中加入ffdshow后通过属性页设置了解码h264,但是render一个.264文件显示不支持此格式,这是什么原因?

谢谢
...全文
327 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2016-08-16
  • 打赏
  • 举报
回复
使用DirectX截屏技术?参考下面:
//GDI与DX截屏API操作
LPDIRECTDRAW        lpDD       = NULL;
LPDIRECTDRAWSURFACE lpDDSPrime = NULL;
LPDIRECTDRAWSURFACE lpDDSBack  = NULL;
LPDIRECTDRAWSURFACE lpDDSGdi   = NULL;
LPDIRECTDRAWSURFACE lpSurf     = NULL;

DDSURFACEDESC DDSdesc;
BOOL m_b24=TRUE;
//rfbServerInitMsg m_scrinfo;
RECT    m_bmrect;

struct _BMInfo {
    BITMAPINFO bmi       ;
    BOOL       truecolour;
    RGBQUAD    cmap[256] ;
} m_bminfo; // 用来保存位图信息的结构

int DX_Init() {// DirectX初始化。返回当前表面获取一张屏幕位图的存储空间大小
    HRESULT hr;

    // 初始化directX
    hr = DirectDrawCreate(0, &lpDD, 0);
    if (FAILED(hr)) return FALSE;

    hr = lpDD->SetCooperativeLevel(NULL, DDSCL_NORMAL);
    if (FAILED(hr)) return FALSE;

    ZeroMemory(&DDSdesc, sizeof(DDSdesc));
    DDSdesc.dwSize  = sizeof(DDSdesc);
    DDSdesc.dwFlags = DDSD_CAPS;
    DDSdesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
    hr = lpDD->CreateSurface(&DDSdesc, &lpDDSPrime, 0);
    if (FAILED(hr)) return FALSE;

    hr = lpDD->GetGDISurface(&lpDDSGdi);
    if (FAILED(hr)) return FALSE;

    ZeroMemory(&DDSdesc, sizeof(DDSdesc));
    DDSdesc.dwSize  = sizeof(DDSdesc);
    DDSdesc.dwFlags = DDSD_ALL;
    hr = lpDDSPrime->GetSurfaceDesc(&DDSdesc);
    if (FAILED(hr)) return FALSE;

    // 初始化位图信息
    if ((DDSdesc.dwFlags & DDSD_WIDTH) && (DDSdesc.dwFlags & DDSD_HEIGHT)) {
        m_bmrect.left = m_bmrect.top = 0;
        m_bmrect.right = DDSdesc.dwWidth;
        m_bmrect.bottom = DDSdesc.dwHeight;
    } else return FALSE;

    m_bminfo.bmi.bmiHeader.biCompression = BI_RGB;//BI_BITFIELDS;
    m_bminfo.bmi.bmiHeader.biBitCount = DDSdesc.ddpfPixelFormat.dwRGBBitCount;

    // m_bminfo.truecolour = DDSdesc.ddpfPixelFormat.dwFlags & DDPF_RGB;
    if (m_bminfo.bmi.bmiHeader.biBitCount > 8)
        m_bminfo.truecolour = TRUE;
    else
        m_bminfo.truecolour = FALSE;

    ZeroMemory(&DDSdesc, sizeof(DDSdesc));
    DDSdesc.dwSize = sizeof(DDSdesc);
    DDSdesc.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH;
    DDSdesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
    DDSdesc.dwHeight = m_bmrect.bottom - m_bmrect.top;
    DDSdesc.dwWidth  = m_bmrect.right  - m_bmrect.left;
    hr = lpDD->CreateSurface(&DDSdesc, &lpDDSBack, 0);
    if (FAILED(hr)) return FALSE;
//  hr = lpDDSPrime->QueryInterface( IID_IDirectDrawSurface3, (LPVOID *)&lpSurf);
//  if (FAILED(hr)) return FALSE;

    switch (m_bminfo.bmi.bmiHeader.biBitCount) {
    case 32:
    case 24:
       // Update the bitmapinfo header
       m_b24 = TRUE;
       m_bminfo.bmi.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
       m_bminfo.bmi.bmiHeader.biWidth = 1024;
       m_bminfo.bmi.bmiHeader.biHeight = 768;
       m_bminfo.bmi.bmiHeader.biPlanes = 1;
//     m_bminfo.bmi.bmiHeader.biBitCount = 24;
       m_bminfo.bmi.bmiHeader.biCompression = BI_RGB;
       m_bminfo.bmi.bmiHeader.biSizeImage = abs((m_bminfo.bmi.bmiHeader.biWidth * m_bminfo.bmi.bmiHeader.biHeight * m_bminfo.bmi.bmiHeader.biBitCount)/8);
       m_bminfo.bmi.bmiHeader.biXPelsPerMeter = (1024*1000)/1024;
       m_bminfo.bmi.bmiHeader.biYPelsPerMeter = (768*1000)/768;
       m_bminfo.bmi.bmiHeader.biClrUsed   = 0;
       m_bminfo.bmi.bmiHeader.biClrImportant = 0;
       break;
    }

    return m_bminfo.bmi.bmiHeader.biSizeImage;
}

BOOL CaptureScreen(RECT &rect, BYTE *scrBuff, UINT scrBuffSize) {// 捕捉屏幕。rect: 区域。scrBuff: 输出缓冲。scrBuffSize: 缓冲区大小
    HRESULT hr=0;

    hr = lpDDSBack->BltFast(rect.left,rect.top,lpDDSPrime,&rect,DDBLTFAST_NOCOLORKEY | DDBLTFAST_WAIT);
    if (FAILED(hr)) return FALSE;

    DDSURFACEDESC surfdesc;
    ZeroMemory(&surfdesc, sizeof(surfdesc));
    surfdesc.dwSize = sizeof(surfdesc);

    hr = lpDDSBack->Lock(&rect, &surfdesc, DDLOCK_READONLY | DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR /*|DDLOCK_NOSYSLOCK*/, NULL);
//  hr = lpDDSPrime->Lock(&rect, &surfdesc, DDLOCK_READONLY | DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR /*|DDLOCK_NOSYSLOCK*/, NULL);
    if (FAILED(hr)) return FALSE;

    // copy the data into our buffer
    BYTE * destbuffpos, * srcbuffpos;
//  m_scrinfo.format.bitsPerPixel = 24;
    srcbuffpos = (BYTE *) surfdesc.lpSurface;
    destbuffpos = scrBuff;

    memcpy( destbuffpos, srcbuffpos,m_bminfo.bmi.bmiHeader.biSizeImage);

    // unlock the primary surface
//  lpDDSPrime->Unlock(surfdesc.lpSurface);
    lpDDSBack->Unlock(surfdesc.lpSurface);
    return TRUE;
}

int SaveBitmapToFile(BITMAP *bitmap, LPSTR lpFileName,char *lpBuf) {
   DWORD dwWritten;
   BITMAPFILEHEADER   bmfHdr;
   BITMAPINFOHEADER   bi;
   HANDLE          fh=NULL;
   bi.biSize = sizeof(BITMAPINFOHEADER);
   bi.biWidth= bitmap->bmWidth;
   bi.biHeight = bitmap->bmHeight;
   bi.biPlanes = 1;
   bi.biBitCount      = bitmap->bmBitsPixel*8;
   bi.biCompression   = BI_RGB;
   bi.biSizeImage     = 0;
   bi.biXPelsPerMeter = 0;
   bi.biYPelsPerMeter = 0;
   bi.biClrUsed       = 0;
   bi.biClrImportant  = 0;
   fh = CreateFile(lpFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
   if (fh == INVALID_HANDLE_VALUE) return FALSE;
   bmfHdr.bfType = 0x4D42; // "BM"
   bmfHdr.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)+bitmap->bmWidth*bitmap->bmHeight*bitmap->bmBitsPixel;
   bmfHdr.bfReserved1 = 0;
   bmfHdr.bfReserved2 = 0;
   bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
   WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
   WriteFile(fh, (char *)&bi,sizeof(BITMAPINFOHEADER), &dwWritten, NULL);
   WriteFile(fh, (char *)lpBuf,bitmap->bmWidth*bitmap->bmHeight*bitmap->bmBitsPixel, &dwWritten, NULL);
   FlushFileBuffers(fh);
   CloseHandle(fh);
   return true;
}

//(1)获取屏幕绘图设备
//(2)创建一个与屏幕绘图设备相兼容的内存绘图设备
//(2)在内存中创建一个与屏幕绘图设备相兼容的图像对象
//(3)将屏幕设备中的图像复制到内存绘图设备中
//(4)将内存图像保存到文件中
//相关函数:
//GetDIBits:按位的方式返回指定的BITMAP,并按指定的格式存储到内存中
int GetBitmapFromScreen(char *lpFileName) {
    char *lpBuf;
    HBITMAP hBitmap,hOld ;
    HDC hDC,hcDC;
    BITMAP bb;
    BITMAPINFO b;
    HANDLE hp,fh=NULL;
    DWORD dwX,dwY;

    dwX=GetSystemMetrics(SM_CXSCREEN);
    dwY=GetSystemMetrics(SM_CYSCREEN);
    hDC=GetDC(NULL);
    hcDC=CreateCompatibleDC(hDC);
    hBitmap=CreateCompatibleBitmap(hDC,dwX,dwY);
    hOld=(HBITMAP)SelectObject(hcDC,hBitmap);
    BitBlt(hcDC,0, 0,dwX,dwY, hDC, 0, 0, SRCCOPY);
    bb.bmWidth=dwX;
    bb.bmHeight =dwY;
    bb.bmPlanes = 1;
    bb.bmWidthBytes=bb.bmWidth*3;
    bb.bmBitsPixel=3;
    bb.bmType=0;
    b.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    b.bmiHeader.biWidth        =dwX;
    b.bmiHeader.biHeight       =dwY;
    b.bmiHeader.biPlanes       =1;
    b.bmiHeader.biBitCount     =3*8;
    b.bmiHeader.biCompression  =BI_RGB;
    b.bmiHeader.biSizeImage    =0;
    b.bmiHeader.biXPelsPerMeter=0;
    b.bmiHeader.biYPelsPerMeter=0;
    b.bmiHeader.biClrUsed      =0;
    b.bmiHeader.biClrImportant =0;
    b.bmiColors[0].rgbBlue     =8;
    b.bmiColors[0].rgbGreen    =8;
    b.bmiColors[0].rgbRed      =8;
    b.bmiColors[0].rgbReserved =0;
    hp=GetProcessHeap();
    lpBuf=(char *)HeapAlloc(hp,HEAP_ZERO_MEMORY,bb.bmHeight*bb.bmWidth*4);
    GetDIBits(hcDC,hBitmap,0,dwY,lpBuf,&b,DIB_RGB_COLORS);
    SaveBitmapToFile(&bb,lpFileName,lpBuf);
    ReleaseDC(NULL,hDC);
    DeleteDC(hcDC);
    DeleteObject(hBitmap);
    DeleteObject(hOld);
    HeapFree(hp,0,lpBuf);
    return true;
}

姚小白 2016-08-16
  • 打赏
  • 举报
回复
引用 3 楼 zhao4zhong1 的回复:
同一个.ax,其CLSID在不同机器上都是一样的。
多谢,赵四老师。 还想问个问题。 目前我用Directshow的VMR9,把视频渲染到一个球体上,转动视角就能看到球体内壁不同视角的视频,现在我想将某个视角的视频流单独保存下来,也就是导出来,该怎么做? 观察点在球体中心,相当于导出的视频流是原来渲染到球体上的某个部分,但因为把视频渲染到了球面上,所以看到的和其原来的原始视频是不一样的,有的地方是有形变的,我想把有形变的部分视频单独保存或者导出,封装成一个transform filter
赵4老师 2016-08-15
  • 打赏
  • 举报
回复
同一个.ax,其CLSID在不同机器上都是一样的。
姚小白 2016-08-15
  • 打赏
  • 举报
回复
引用 1 楼 zhao4zhong1 的回复:
1 使用OleView.exe 2 不知道
1.我要是想在程序中直接使用呢? 想把ffdshow.ax 包含在我的工程中,然后运行的时候能自行检测注册,然后可以create ffdshow filter。 如果使用OleView,岂不是要打开这个exe才能知道CLSID? 2. 网上找了很多,在create ffdshow filter的时候都用到了CLSID_FFDSHOW,是不是就是说要包含某些ffdshow源码的头文件,否则显示未定义啊
赵4老师 2016-08-12
  • 打赏
  • 举报
回复
1 使用OleView.exe 2 不知道
与 MPlayer 一样从 Linux 平台移植而来的 KMPlayer (简称KMP)几乎可以播放您系统上所有的影音文件。通过各种插件扩展 KMP 可以支持层出不穷的新格式。当然 KMPlayer 也推出了 Android 哦。KMPlayer 播放器作为一款经典的播放器是您电脑放电影不可缺少的工具哦。 来自韩国的影音全能播放器 KMPlayer 中文版来自韩国的影音全能播放器 KMPlayer 中文版 KMPlayer 简称 KMP,早期名叫WaSaVi播放器。作者姜龙喜(韩国),历时七年自主开发的朝鲜语多媒体图形视窗工程免费项目。KMPlayer是一套将网络上所有能见得到的解码程式(Codec)全部收集于一身的影音播放软件;此外,KMPlayer还能够播放DVD与VCD、汇入多种格式的外挂字幕 档、使用普及率最高的WinAMP音效外挂与支援超多种影片效果调整选项等。 KMPlayer – The Professional Media Player!,它支持 Winamp 2/5 的输入、常规、DSP、视觉效果、媒体库插件。无须注册表支持直接调用 Directshow滤镜!FFdshow 的视觉特效系统~超强的 GUI 界面~安装电视卡后可以直接代替原软件直接收看电视~支持播放 DVD/VCD 以及绝大多数电脑的媒体文件(AVI 支持 Xvid/DivX/3vid/H264 OGG/OGM/MKV 容器/AC3/DTS 解码~Monkey Audio 解码~)此播放器除了会将自己的配置信息写入注册表外绝对绿色!KMplayer内置常见的所有解码器,包括real,QT等。 KMPlayer以其强大的操控功能在众多免费播放器中逐渐显示其开发实力。底层调用了WMP的内核DirectShow。外部同时支持临时挂接Windows下的全部解码器。通过各种插件扩展,KMP可以支持层出不穷的新格式。直接从Winamp继承的插件功能,能够直接使用winamp的音频 、输入、视觉效果插件;而通过其独有的扩展能力,只要你喜欢,可以选择使用不同解码器对各种格式进行解码。 只要安装了它,你不用再另外安装 一大堆转码程序,就能够顺利观赏所有特殊格式的影片了。 KMPlayer 优势介绍 KMPlayer把网络上所有能见得到的解码程式(Codec)全部收集,支持大多数的影片、音乐、图片等格式。播放影片时可以作多种调整,例如影像过滤、声道、亮度、画面缩放、画面移动、跳转到5秒~10分钟等等。而在播放音乐可以设定音乐模式、Bass、立体声等等,也可载装Winamp的插件。支持自定按键,支持更换Skin。支持撷取影片画面和声音的功能,不再需要安装其他的软件就能把声音或影片画面撷取出来。 KMPlayer强大的档案支援功能深受用家欢迎,支持的影片档包括:AVI、RealMedia、MPEG 1/2/4.ASF、MKV、OGM、、FLV、VCD、SVCD、MP4等;AVI 支援 Xvid/DivX/3vid/H264 OGG/OGM/MKV 容器/AC3/DTS 解码Monkey Audio 解码等。支援的声音档:APE、MP3.WAV、MPC、Flac、MIDI等。支援的图片档:BMP、 GIF、JPEG、PNG等。支援BIN、ISO、IMG、NRG制成的音乐格式光碟影档。 捕获功能 Kmplayer可以说是影音播放器中的全能王。或许你只用它来听音乐、看电影,如果仅仅是这样的话,也真对不起开发者了。实际上Kmplayer有很多优点,捕获功能就是其中一个,下面我们来看看。 KMPlayer 中文版 1.捕获音频:选择此项后,会弹出“音频捕获”对话框,在这里可以指定输出路径及文件名,然后单击“开始”按钮,即可将当前正在播放的视频的音频信息保存在一个MP3文件当中,简单说就是将电影的声音提取出来。 优点:方便,声音捕获与电影观看同步,不影响观看效果,且无需占用额外时间。 适用场合:当看到经典的外国原声大片时,将音频信息捕获下来放到MP3中,对英语学习有帮助。 2.捕获视频文件:一般来说捕获视频文件视频选项最好选择直接复制视频流(仅对h.264/avc等编码的视频有效),因为kmplayer本身不安装编码器的情况下是无法正确重编码捕获视频的。音频自然推荐用ac3编码器。最好是下载一个x.264vfw编码器,这样的话即使是非h.264/avc等编码的视频在不能使用直接复制视频流的情况下也能通过重编码视频流来正常捕获视频文件了。 优点:同捕获音频类似,可实现边看边转换且无需额外的转换软件。 适用场合:从网上下载的影片大部分是RM或RMVB格式的,Nero不支持,就有必要将其转换成AVI格式。 3.“捕获画面(您所看到的)为…”:实现对影片截图。经常写稿的朋友可

24,855

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 工具平台和程序库
社区管理员
  • 工具平台和程序库社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧