DX是由微软公司开发的多媒体编程接口.由很多API组成的(处于低系统级别);

DX本身是用C写成的. 像素格式使用DDPIXELFORMAT.

  • 不同的硬件对外公开了不同的 API 编程接口,因此:微软想要在编程上做一统一处理!
    DirectX 就是在所有硬件的接口之上再提供一个公共的接口,相当于一个桥梁,
    当然硬件制造商也必须依照DirectX的标准来规范自己
  • moduels
    DDraw + Direct3D + DirectSound + DirectInput + DirectPlay
    DShow = DirectDraw + DirectSound

DDraw

DirectDraw 可以看成是 GDI 的升级,它可以直接对显存操作,提高了速度(显存最低应该>2M)

DDraw 不支持YUV.

  • DirectDraw 与硬件打交道的层次结构如下:
    Hardware → HAL(Hardware Abstract Layer,or HEL) → DirectDraw → Application
    当硬件加速被关闭时,DDraw使用HEL来实现所有的操作,HEL比HAL更远离底层,效率低一些
  • 精灵
    精灵就是在屏幕上移动的图象,精灵画在一个表面上,覆盖已有背景;
    精灵图象本身不是矩形的,但却包含在矩形区域中.矩形区域中不属于精灵的像素就被"透明"处理
  • 页面
    页面(Surface)通常代表了内存(也可以在显存)中的一块区域(存储了图像数据)
    在全屏下 Page Flipping 叫做 Flip
    在窗口下 Page Flipping 叫做 Blt(将内存中的数据块从一处传送到另一处).
#include <DDraw.h>
#pragma comment(lib, "ddraw.lib")
#pragma comment(lib, "dxguid.lib")
// 1. 初始化
DIRECTDRAW* lpDD = NULL;
DirectDrawCreate(NULL, &lpDD, NULL);
lpDD->SetCooperativeLevel(GetActiveWindow(), DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
lpDD->SetDisplayMode(640, 480, 8); //8表示色深

// 2. 在内存里建立 PageFlipping 所需要的两个页, 前页和后页.
// 使用 DIRECTDRAWSURFACE* 来定义
LPDIRECTDRAWSURFACE lpDDSPrimary, lpDDSBack, lpDDSOffscreen;
DDSURFACEDESC ddsd;
DDSCAPS ddscaps = {sizeof(DDSCAPS)};
// 创建主页面
ddsd.dwFlags = DDSD_CAPS; //ddsCaps成员为可用
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; //指定要创建的是主页面
lpDD->CreateSurface(&ddsd, &lpDDSPrimary, NULL);
// 创建从页面
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
lpDDSPrimary->GetAttachedSurface(&ddscaps, &lpDDSBack);

// 3. 创建Clip,避免画到外面.使用 LPDIRECTDRAWCLIPPER 来定义
IDirectDrawClipper* lpClipper = NULL;
lpDD->CreateClipper(0, &lpClipper, NULL);
//将裁剪器与窗口关联
lpClipper->SetHWnd(0, m_wndStatic.GetSafeHwnd());
//将裁剪器添加到主页面
lpDDSPrimary->SetClipper(lpClipper);

// 4. 在后页画图, 然后"刷"的一下子换到前页来.
lpDDSPrimary->GetDC(&hdc);
SetBkColor(hdc, RGB(0, 0, 255));
SetTextColor(hdc, RGB(255, 255, 0));
TextOut(hdc, 220, 200, "haha", lstrlen("haha"));
lpDDSPrimary->ReleaseDC(hdc);

// 5, 清理
void FreeDDraw(void) {
    if (lpDD != NULL) {
        if (lpDDSPrimary) {
            lpDDSPrimary->Release();
            lpDDSPrimary = NULL;
        }
        lpDD->Release();
        lpDD = NULL;
    }
}

// 得到一个页面的desc
lpDDSPrimary->GetSurfaceDesc(&ddsd);

// 获取像素格式
DDPIXELFORMAT* lpDDPixelFormat;
lpDDSPrimary->GetPixelFormat(lpDDPixelFormat);

// 设置关键色(被透明掉的颜色)
DDCOLORKEY ddck;
ddck.dwColorSpaceLowValue = RGB(255, 0, 0);
ddck.dwColorSpaceHighValue = 0;
lpDDSOffScreen->SetColorKey(DDCKEY_SRCBLT, &ddck);

DirectShow

Active Movie:是其最原始的名称,代码中还可以见到AM开头的结构.开发代号为Quartz.

filter

filter是一个特殊的COM组件,他是一个功能模块,表现为.ax或.dll文件.

filter之间的数据被封装在sample内.

filter都实现了IBaseFilter接口.

Source filter,Transform filter,Render filter

一般情况下,创建Filter使用一个普通的Win32 DLL项目

而且一般不使用MFC,一般要添加这几个库文件:

strmbasd.lib winmm.lib msvcrtd.lib, + ignore all default libraries

  • PIN
    PIN 类一般作为 Filter 类的一个成员变量来使用;
    outPIN 拥有 allocator 的使用决定权利(多少个buffer,buffer的大小)
    outPIN 连接到 inPIN,但是 不要调用filter或pin自身的method
    调用Graph上的方法链建立连接,如:IFilterGraph::ConnectDirect(),IGraphBuilder::Connect();
  • API
    GetMediaType() -> CheckMediaType() -> SetMediaType() -> DecideBufferSize()
    GetMediaType :PIN 上首选的媒体类型,媒体类型的过滤
    CheckMediaType :在输出PIN上进行媒体类型的检查
    SetMediaType :更新 CBasePin::m_mt
    DecideBufferSize :当媒体类型协商之后,就要确定buffer的大小如一帧图片的大小
// D:\dxsdk\include
// D:\dxsdk\samples\c++\directshow\baseclasses
// D:\dxsdk\samples\c++\common\include
// D:\Program Files\Microsoft Visual Studio\VC98\INCLUDE
// D:\Program Files\Microsoft Visual Studio\VC98\MFC\INCLUDE
// D:\Program Files\Microsoft Visual Studio\VC98\ATL\INCLUDE
// D:\dxsdk\lib // lib
// D:\dxsdk\samples\c++\directshow\baseclasses\debug
// D:\dxsdk\samples\c++\directshow\baseclassed\release
// D:\Program Files\Microsoft Visual Studio\VC98\LIB
// D:\Program Files\Microsoft Visual Studio\VC98\MFC\LIB
// 
// strmbasd.lib uuid.lib winmm.lib strmiids.lib :debug
// strmbase.lib uuid.lib winmm.lib strmiids.lib :release
#include <dshow.h>

VFW

VFW(视频采集卡)趋于被淘汰.

  • 声卡 声卡一般都有些混音的功能(几个声道),相对包装的Filter就有几个 IN PIN(Microphone..) 这些PIN都是代表者物理的输入端子,在 Graph 中是永远不会连接到其他 Filter 上的! 声卡的输出功能一般有两个 Filter 包装类: DirectSound Render Filter(DirectSound),Audio Render Filter(waveOut,不支持混音)
  • 微软使用Audio-Capture-Filter来代表声卡(这些Filter内如使用waveIn函数族来实现)
    CLSID_AudioInputDeviceCategory
    在 “Audio Capture Sources” 目录下可以找到代表各个声卡的Filter
    inputPIN: Line In, CD Audio, Microphone, Stereo Mix(声卡输入端子的象征)

WDM

WDM驱动的硬件都使用Ksproxy.ax这个Filter,该Filter有"瑞士军刀"的称号.

WDM硬件支持内核流数据传输

// 0, 基础准备
// 创建文件 demoCOM.def (导出COM公共函数,如 DllRegisterServer)
// 创建文件 demoGuids.h (使用GUID生成工具并按一定的格式书写)
// 创建文件 setup.cpp  (def中几个函数的实现,filter注册时需要.主要就是实现DllMain,DllRegisterServer,DllUnregisterServer)
// 注意 setup.cpp 中"demoGuids.h"内不要再包含 initguid.h !!
// 类工厂模板中注意 FilterDemo::CreateInstance() 的传入
// 1, 框架类
// 创建文件 FilterDemo.cpp
// 其实框架类就是实现纯虚函数,与部分虚函数,其他的不必管
// 实现: CreateInstance(),NonDelegatingQueryInterface()...
// 主要是完成输入或输出Pin上的媒体类型的检查,以及Sample内存的分配
// 各种重要的系统头文件最好包含在这个类的cpp文件中如:G729EncodeFilter.cpp
// 2, 逻辑类
// 逻辑类不应该影响filter的框架,一般作为框架类的一个成员对象.
// 逻辑类要负责的是"对输入的数据进行处理",至于数据是如何流动的它并不关心.
// 3, 自定义接口的声明与实现
// 为了给使用者提供接口,对外的!要实现 NoDelegatingQueryInterface();
// 一般会创建一个 demoCOM.idl 文件,但是并不是必须的(该文件使用MIDL.exe编译,编译后生成demo.h,demo_i.c等文件)
// 接口的声明要放在单独的一个文件,完了在框架类中要#include进来,并一一声明接口函数.
// 最后还要在框架类中实现这些接口,实现这些接口(外部使用者)显然用到了逻辑类,它属于我们的内部实现或者叫内部接口.
#include <streams.h>
#include "stdafx.h"
#include <stdio.h>
#include <streams.h>
#include <mmsystem.h>
#include <initguid.h>
#include "G729EncodeFilter.h"
#ifdef _DEBUG
#pragma comment(lib,"strmbasd.lib")
#else
#pragma comment(lib,"strmbase.lib")
#endif
#pragma comment(lib,"strmiids.lib")

IMemAllocator, IMediaSample1, 输出PIN必须调用 GetBuffer 使用该 sample2, GetBuffer会阻塞直到获得可用的sample3, Allocator 由一方 PIN 来创建IMemAllocator -> {Sample Pool} => IMemSample::GetBuffer() -> bufer

// AM_MEDIA_TYPE
* AM_MEDIA_TYPE* WINAPI CreateMediaType(AM_MEDIA_TYPE const *pSrc );
* void WINAPI DeleteMediaType(AM_MEDIA_TYPE* pmt);
* major type,subtype, format type 都是一个GUID
* bFixedSizeSamples: 音频和未压缩的视频通常是TRUE, 压缩的视频则为FALSE; 起到提示的作用
* lSampleSize : 对于压缩的数据, 该值可以为 0
// major type :
MEDIATYPE_Audio, MEDIATYPE_Video, MEDIATYPE_AnalogAudio, MEDIATYPE_AnalogVideo,
MEDIATYPE_Interleaved(DV), MEDIATYPE_Midi, MEDIATYPE_Stream(NO timeStamps), MEDIATYPE_Text..
// subtype :
MEDIASUBTYPE_PCM, MEDIASUBTYPE_MPEG_ADTS_AAC, MEDIASUBTYPE_MPEG_HEAAC, MEDIASUBTYPE_RAW_AAC1
MEDIASUBTYPE_AVC1(h.264 with start codes),
MEDIASUBTYPE_H264(with start codes)
MEDIASUBTYPE_h264(== H264)
MEDIASUBTYPE_X264(== H264)
MEDIASUBTYPE_x264(== H264)
MEDIASUBTYPE_RGB24(uncompressed RGB formats)
MEDIASUBTYPE_RGB32(uncompressed RGB formats, 最后一个字节被忽略)
MEDIASUBTYPE_ARGB32(with alpha channel)
MEDIASUBTYPE_None(这个格式不需要指定一个subtype)
// formattype:
FORMAT_MPEG2Video(MPEG2VIDEOINFO), FORMAT_MPEGVideo(MPEG1VIDEOINFO),
FORMAT_VideoInfo2(VIDEOINFOHEADER2), FORMAT_VideoInfo(VIDEOINFOHEADER),
FORMAT_WaveFormatEx(WAVEFORMATEX), FORMAT_None