现在的位置: 首页 > 综合 > 正文

视频渲染

2013年08月09日 ⁄ 综合 ⁄ 共 7715字 ⁄ 字号 评论关闭

要为CE做硬件解码的filter,除了驱动部分,更多的工作在于支持媒体类型的查询、适配上。视频渲染组件,是整个filter模型的最后一个环境,负责显示和输出。视频渲染只是显示驱动的控制者,不需要进行媒体sample的处理。

 

视频渲染有2个输出途径:

1、  GDI

2、  Ddraw

 

当graph首次连接时候,视频渲染尝试使用GDI。它需要连接上主显示器支持的某种RGB媒体格式。当进入暂停模式时候,视频渲染会给Ddraw尝试分
配表面(前提是显示驱动支持Ddraw模式)。当某些应用场景不支持Ddraw时候,也会切换回GDI模式(如播放时候,在Ddraw视频表面之上,显示
某个菜单。这个时候整个画面,包括Ddraw视频,都要切换回GDI模式)。

 

选择加速媒体类型:

当视频渲染进入暂停阶段(filter的几个状态,请参考相关资料),可以进行Ddraw表面的分配工作。视频渲染枚举上层filter的所有媒体类型,然后分配出一个支持以上某个媒体类型的表面。如果上层filter是WMV
DMO,那么这个filter支持以下输出媒体类型:

  • YV12
  • NV12
  • YUY2
  • I420
  • IYUV
  • UYVY
  • YVYU
  • RGB565
  • RGB555
  • RGB32
  • RGB24
  • RGB8

视频渲染首先会尝试分配出flip overlay表面,然后才是无filp功能的表面:

1、对于上层filter支持的每种媒体类型,按顺序进行:

A、尝试为这个类型,分配flip表面

B、如果成功,调用上层filter的输出pin上QueryAccept函数

C、如果成功,就使用这个表面

 

2、如果flip表面分配失败,尝试分配flip的主表面

A、分配成功,调用上层filter的输出pin上QueryAccept函数

B、如果成功,就使用这个表面

 

3、 
如果flip主表面分配失败,对于上层filter支持的每种媒体类型,按顺序进行:

A、尝试为这个类型,分配无flip功能的表面

B、如果成功,调用上层filter的输出pin上QueryAccept函数

C、如果成功,就使用这个表面

 

这个过程中,如果上层filter想使用YUV格式,那它需要控制媒体类型的选择。如果显示驱动也可以提供这个类型的表面的话,那这个媒体加速类型就能定下来。整个选择是由上层filter控制,显示驱动被动的过程。

 

视频渲染的动态格式变更:

对于一个优先选择的媒体类型,通常希望有overlay
flip的表面。不尽人意的是,根据显示驱动的上报功能,当视频按原始大小播放时候,flip
overlay的表面不一定能有效的使用起来。当用户进行放大、缩小操作,这个表面也可能无效。这取决于Ddraw硬件上报的功能中
dwMinOverlayStretch和dwMaxOverlayStretch的内容。当显示驱动不支持拉伸,而视频渲染正在使用overlay表
面,那么就要切换到GDI模式。GDI模式能做拉伸处理。

 

每次上层filter从视频渲染中,申请一个新的buffer。视频渲染会尝试返回一个Ddraw的buffer。如果使用环境的要求都符合(如clip、拉伸、视频内存,这部分功能参考《wince
DirectDraw设计分析》),这个表面才能被使用。否则,也是要切换到GDI模式。

 

视频渲染连接问题的调试:

当编写了新的解码filter或者capture驱动时,经常遇到一些问题:

1、  插入到graph的颜色转换

2、  视频渲染连接不上

3、  YUV表面不能使用,只能用GDI

 

认识Dshow的log

首先,打开Dshwo DLL、quartz.dll和连接相关的视频渲染中的debug zone。方法有2个:

1、  quartz.dll加载后,打开debug zone的前4个开关。

2、 
HKEY_CURRENT_USER/Pegasus/Zones的注册表中,添加名字为quartz
的DWORD键值,内容是0xf。

 

开始测试,保存运行的debug输出。找到Filter Graph Dump字段,然后观察log内容。如下:

Filter graph dump
Filter 1a199a30 'Video Renderer' Iunknown 1a199a20
    Pin 1a199f10
Input (Input) connected to 1a0e1880
Filter 1a0e1200 'WMVideo & MPEG4 Decoder DMO'
Iunknown 1a0e11f0
    Pin 1a0e16e0
in0 (Input) connected to 1a0e0600
    Pin 1a0e1880
out0 (PINDIR_OUTPUT) connected to 1a199f10
    Pin 1a0e1a00
~out1 (PINDIR_OUTPUT) connected to 0
Filter 1a0ecc60 'ASF ICM Handler' Iunknown 1a0ecc50
    Pin 1a0ecd70
In (Input) connected to 1a0aa3a0
    Pin 1a0e0600
Out (PINDIR_OUTPUT) connected to 1a0e16e0
Filter 1a0ec240 'Audio Renderer' Iunknown 1a0ec230
wo: GetPin, 0
    Pin 1a0ec4e0
Audio Input pin (rendered) (Input) connected to 1a0eb880
Filter 1a0eb220 'WMAudio Decoder DMO' Iunknown 1a0eb210
    Pin 1a0eb660
in0 (Input) connected to 1a0ea800
    Pin 1a0eb880
out0 (PINDIR_OUTPUT) connected to 1a0ec4e0
Filter 1a0e9380 'ASF ACM Handler' Iunknown 1a0e9370
    Pin 1a0e9490
In (Input) connected to 1a0aa000
    Pin 1a0ea800
Out (PINDIR_OUTPUT) connected to 1a0eb660
Filter 1a0a2ae0 '/Hard Disk2/clips/wmv/0-1.asf' Iunknown
1a0a2ad0
    Pin 1a0aa000
Stream 1 (PINDIR_OUTPUT) connected to 1a0e9490
    Pin 1a0aa3a0
Stream 2 (PINDIR_OUTPUT) connected to 1a0ecd70
End of filter graph dump

 

然后观察视频渲染使用那个媒体类型,查找Allocating video resources,如下:

Allocating video resources
Initialising DCI/DirectDraw
Searching for direct format
Entering ReleaseSurfaces
Entering HideOverlaySurface
Enumerated 32315659
Entering FindSurface
Entering GetMediaType
Not a RGB format
Entering CreateYUVFlipping
Entering CheckCreateOverlay
GWES Hook fails surface creation. IDirectDraw::CreateSurface
fails.
No surface
Entering ReleaseSurfaces
Entering HideOverlaySurface
Enumerated 3231564e
Entering FindSurface
Entering GetMediaType
Not a RGB format
Entering CreateYUVFlipping
Entering CheckCreateOverlay
GWES Hook fails surface creation. IDirectDraw::CreateSurface
fails.
No surface
Entering ReleaseSurfaces
Entering HideOverlaySurface
Enumerated 32595559
Entering FindSurface
Entering GetMediaType
Not a RGB format
Entering CreateYUVFlipping
Entering CheckCreateOverlay
Entering InitOverlaySurface
Entering InitDrawFormat
Entering InitDrawFormat
Entering GetDefaultColorKey
Returning default colour key
Entering InitDefaultColourKey
Entering SetSurfaceSize
Preparing source and destination rectangles
Entering ClipPrepare
Entering InitialiseClipper
Entering InitialiseColourKey
overlay color key on
Colour key
No palette
Found AMDDS_YUVFLP surface

Proposing output type  M type
MEDIATYPE_Video  S type
MEDIASUBTYPE_YUY2

以上是WMV DMO建立表面的过程。显示驱动会建立YUV2的表面,WMV解码器的第三个媒体选项。

 

Graph
的颜色转换问题:

上层filter往往不报出支持的RGB格式,而只有YUV格式。视频渲染就不能直接用RGB格式进行连接,这时graph一般会加入颜色转换。但我们不希望这个情况发生,因为这会导致一个内存复制的动作,所以需要知道上层filter可以提供那些RGB的格式支持。

 

有时候,即使上层filter支持RGB格式,graph也会加入一个颜色转换。这可能是上层filter需要进行内存地址的对全。目前视频渲染只支持1字节的内存对齐,所以这个情况也有可能发生。

 

另一个可能是,颜色转换器加入时候使用BITMAPINFOHEADER。上层filter得到输出媒体时,不知道应该在BITMAPINFOHEADER结束部分,使用哪种bitmask。确认正确的使用bitmask,例如RGB565:

*pdwBitfield++  =
0xF800;      
// Red – 5

 *pdwBitfield++ 
=
0x07E0;      
// Green - 6

 *pdwBitfield   
=
0x001F;      
// Blue - 5

Bitmask应该是0xF800、0x07E0和0x001F。

 

Graph
连接不上:

如果上层filter只支持YUV格式的一个子集,而且没有合适的颜色转换器。那就不能连接到任何视频渲染器上。这就要上层filter提供RGB的支持。

 

YUV
表面没有使用,只使用了GDI

上层filter提供了内存分配器,视频渲染就尝试不使用Ddraw模式(内存buffer不能传递给Ddraw)。要使用flip
overlay的话,就需要内存分配的工作由视频渲染完成(关于filter内存分配的知识,参考filter相关资料)。

 

表面类型,控制视频渲染创建的表面:

有几个方法可以让视频渲染控制加速表面的创建,在调试连接问题时候比较有用。特别是减少显示驱动支持格式选项的这个方式,可以在注册表中控制:

HKEY_LOCAL_MACHINE/Software/Microsoft/DirectX/DirectShow/Video
Renderer/SurfaceTypes

下面是
SurfaceTypes
键值中
AMDDS
的值表:

Flag

Hexadecimal value

Description

AMDDS_NONE

0x00

No support for Device Control Interface (DCI) or
DirectDraw.

AMDDS_DCIPS

0x01

Use DCI primary surface.

AMDDS_PS

0x02

Use DirectDraw primary surface.

AMDDS_RGBOVR

0x04

RGB overlay surfaces.

AMDDS_YUVOVR

0x08

YUV overlay surfaces.

AMDDS_RGBOFF

0x10

RGB off-screen surfaces.

AMDDS_YUVOFF

0x20

YUV off-screen surfaces.

AMDDS_RGBFLP

0x40

RGB flipping surfaces.

AMDDS_YUVFLP

0x80

YUV flipping surfaces.

AMDDS_ALL

0xFF

Use all available surfaces.

AMDDS_DEFAULT

0xFF

Use all available surfaces.

AMDDS_YUV

0xA8

(AMDDS_YUVOFF | AMDDS_YUVOVR | AMDDS_YUVFLP)

AMDDS_RGB

0x58

(AMDDS_RGBOFF | AMDDS_RGBOVR | AMDDS_RGBFLP)

AMDDS_PRIMARY

0x03

(AMDDS_DCIPS | AMDDS_PS)

 

如果调试时候,只想使用YUV的overlay flip表面。就把键值只设置为AMDDS_YUVFLP。

 

关于FourCC:

FourCC是描述媒体格式的GUID方式。每种媒体格式,在全球使用中,都有一个特定的编号。如下:

Enumerated 32315659

0x32 = '2', 0x31 = '1', 0x56 = 'V', 0x59 = 'Y'
===> 0x32315659 = YV12

 Enumerated 3231564e

0x32 = '2', 0x31 = '1', 0x56 = 'V', 0x4e =
'N' ===> 0x3231564e =
NV12

 Enumerated 32595559

0x32 = '2', 0x59 = 'Y', 0x55 = 'U', 0x59 = 'Y'
===> 0x32595559 = YUY2

 Enumerated 56555949

0x56 = 'V', 0x55 = 'U', 0x59 = 'Y', 0x49 = 'I'
===> 0x56555949 = IYUV

 Enumerated 59565955

0x59 = 'Y', 0x56 = 'V', 0x59 = 'Y', 0x55 = 'U'
===> 0x59565955 = UYVY

 Enumerated 55595659

0x55 = 'U', 0x59 = 'Y', 0x56 = 'V', 0x59 = 'Y'
===> 0x55595659 = YVYU

也可以在public/directx/sdk/inc/uuids.h中,查找对应的定义

  • // 32595559-0000-0010-8000-00AA00389B71 'YUY2' ==
    MEDIASUBTYPE_YUY2
  • OUR_GUID_ENTRY(MEDIASUBTYPE_YUY2,
  • 0x32595559, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38,
    0x9b, 0x71)
  • // 55595659-0000-0010-8000-00AA00389B71 'YVYU' ==
    MEDIASUBTYPE_YVYU
  • OUR_GUID_ENTRY(MEDIASUBTYPE_YVYU,
  • 0x55595659, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38,
    0x9b, 0x71)
  • // 59565955-0000-0010-8000-00AA00389B71 'UYVY' ==
    MEDIASUBTYPE_UYVY
  • OUR_GUID_ENTRY(MEDIASUBTYPE_UYVY,
  • 0x59565955, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38,
    0x9b, 0x71)
  • // 31313259-0000-0010-8000-00AA00389B71 'Y211' ==
    MEDIASUBTYPE_Y211
  • OUR_GUID_ENTRY(MEDIASUBTYPE_Y211,
  • 0x31313259, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38,
    0x9b, 0x71)
  • // 32315659-0000-0010-8000-00AA00389B71 'YV12' ==
    MEDIASUBTYPE_YV12
  • OUR_GUID_ENTRY(MEDIASUBTYPE_YV12,
  • 0x32315659, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38,
    0x9b, 0x71)
  • // 36313259-0000-0010-8000-00AA00389B71 'YV16' ==
    MEDIASUBTYPE_YV16
  • OUR_GUID_ENTRY(MEDIASUBTYPE_YV16,
  • 0x36315659, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38,
    0x9b, 0x71)
  • // 56595549-0000-0010-8000-00AA00389B71 'IUYV' ==
    MEDIASUBTYPE_IUYV
  • OUR_GUID_ENTRY(MEDIASUBTYPE_IUYV,
  • 0x56595549, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38,
    0x9b, 0x71)
  • // 3231564E-0000-0010-8000-00AA00389B71 'NV12' ==
    MEDIASUBTYPE_NV12
  • OUR_GUID_ENTRY(MEDIASUBTYPE_NV12,
  • 0x3231564E, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38,
    0x9b, 0x71)
  • // 30323449-0000-0010-8000-00AA00389B71 'I420' ==
    MEDIASUBTYPE_I420
  • OUR_GUID_ENTRY(MEDIASUBTYPE_I420,
  • 0x30323449, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38,
    0x9b, 0x71)
  • // 56555949-0000-0010-8000-00AA00389B71 'IYUV' ==
    MEDIASUBTYPE_IYUV
  • OUR_GUID_ENTRY(MEDIASUBTYPE_IYUV,
  • 0x56555949, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38,
    0x9b, 0x71)

 

http://blogs.msdn.com/medmedia/archive/2007/06/11/the-video-renderer-connection-process.aspx

【上篇】
【下篇】

抱歉!评论已关闭.