原来使用的是direct draw播放的视频,但是direct draw中不能调整图像的亮度、色度等,再加上directx的文档上说direct draw以后会淡出市场,不会再更新了,而是建议使用direct3d来代替direct draw,所以就要改为direct3d来播放视频了所使用的代码是在自己编写的SDK中,纯c++,使用vc6.0的编译环境这里的代码从很多地方来,整体框架是参考directx的文档,其它的很多细节从网上获取,包含很多的参数。
下面是我的使用direct3d的过程:注:
1. 中间用到的 gTestDirectxError() 函数可以不管,它只是我用来查看在失败时,返回的错误号码
2. 由于这里的行号都是我把代码拷贝过来后添加的,比较麻烦。所以对于后面说不到的部分,不添加行号
3. RME_开关的是我自己定义返回值一、包含头文件:
#include "d3dx9.h"
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")// 释放direct对像
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }二、定义节点:
1 struct CUSTOMVERTEX
2 {
3  D3DXVECTOR3 position; // The position
4  D3DCOLOR color;    // The color
5 #ifndef SHOW_HOW_TO_USE_TCI
6  FLOAT tu, tv;   // The texture coordinates
7 #endif
8 };
9 #ifdef SHOW_HOW_TO_USE_TCI
10 #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)
11 #else
12//#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1) // 偏红
13 #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE) // 只有底色,即暗红色
14 //#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE) // 乱图像
15 #endif这部分代码从directx文档上来,其中的13、14行是我加的,是为了测试。注意第13行,后面会用到三、定义direct3d的对像:
16 LPDIRECT3D9 m_pDirect3D9;
17 LPDIRECT3DDEVICE9 m_pDirect3DDevice;18 LPDIRECT3DSURFACE9 m_pDirect3DSurfaceRender;
19 LPDIRECT3DTEXTURE9 m_pDirect3DTexture;
20 LPDIRECT3DVERTEXBUFFER9 m_pDirect3DVertexBuffer;四、释放对像的方法:
void ReleaseDirect3D()
{
SAFE_RELEASE(m_pD3DFont);
SAFE_RELEASE(m_pD3DSprite);
SAFE_RELEASE(m_pDirect3DVertexBuffer);
SAFE_RELEASE(m_pDirect3DTexture);
SAFE_RELEASE(m_pDirect3DSurfaceRender);
SAFE_RELEASE(m_pDirect3DDevice);
SAFE_RELEASE(m_pDirect3D9);
}五、初始化direct3d对像:
unsigned long InitDirect3D( HWND hwnd )
{
21 ReleaseDirect3D(); // 创建Direct3D物件,这是所有Direct3D的入口
22 m_pDirect3D9 = Direct3DCreate9( D3D_SDK_VERSION );
23 if ( m_pDirect3D9 == NULL )
{
24 return RME_UNKNOWN_ALL;
} HRESULT lRet; // 检查是否支持后台渲染和窗口的显示
25 D3DDISPLAYMODE d3dDisplayMode;
26 lRet = m_pDirect3D9->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3dDisplayMode );
27 if ( FAILED(lRet) )
{
28 return RME_UNKNOWN_ALL;
} // 创建Direct3D设备
29 D3DPRESENT_PARAMETERS d3dpp;
long l1 = 0; //Flags:必需为lockable,否则材质的lock不能成功
30 ZeroMemory( &d3dpp, sizeof(d3dpp) );
31 d3dpp.Windowed = TRUE;
32 d3dpp.hDeviceWindow = hwnd;
33 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
34 d3dpp.BackBufferFormat = d3dDisplayMode.Format;
35 d3dpp.EnableAutoDepthStencil = FALSE;
36 d3dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;37 lRet = m_pDirect3D9->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, NULL,
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &m_pDirect3DDevice );
38 if ( FAILED(lRet) )
{
gTestDirectxError( lRet ); return RME_UNKNOWN_ALL;
} // 设置渲染设备的属性
39 m_pDirect3DDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); // 设备Alpha Blending 的顶点
40 m_pDirect3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
41 m_pDirect3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
42 m_pDirect3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );43 m_pDirect3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
44 m_pDirect3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
45 m_pDirect3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
46 m_pDirect3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); // 创建sprite
47 lRet = D3DXCreateSprite( m_pDirect3DDevice, &m_pD3DSprite ); // 创建字体
48 lRet = D3DXCreateFont( m_pDirect3DDevice, -12, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, 
                         OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, 
                         TEXT("Arial"), &m_pD3DFont ); // 创建材质操作体
49 lRet = m_pDirect3DDevice->CreateTexture( lWidth, lHeight, 1, D3DUSAGE_SOFTWAREPROCESSING,
D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &m_pDirect3DTexture, NULL );
50 if ( FAILED(lRet) )
{
gTestDirectxError( lRet );
Trace( TEXT("创建材质库失败!返回值:0x%08X\n"), lRet );
return RME_UNKNOWN_ALL;
} // 创建节点操作库
51 lRet = m_pDirect3DDevice->CreateVertexBuffer( 4 * sizeof(CUSTOMVERTEX),
0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &m_pDirect3DVertexBuffer, NULL );
52 if ( FAILED(lRet) )
{
gTestDirectxError( lRet );
return RME_UNKNOWN_ALL;
} // 填充节点
53 CUSTOMVERTEX *pVertex;
54 lRet = m_pDirect3DVertexBuffer->Lock( 0, 4 * sizeof(CUSTOMVERTEX), (void**)&pVertex, 0 );
55 if ( FAILED(lRet) )
{
gTestDirectxError( lRet );
return RME_UNKNOWN_ALL;
}
56 float fUnit = 1.f;
57 float fGets = 0.5f;
58 pVertex[0].position = D3DXVECTOR3( -fUnit, fUnit, 1.f );
59 pVertex[0].tu = 0.0;
60 pVertex[0].tv = 0.0;
61 pVertex[0].color = 0x00ffffff; //0x00cfd0ef;
62 pVertex[1].position = D3DXVECTOR3( fUnit, fUnit, 1.f );
63 pVertex[1].tu = fGets;
64 pVertex[1].tv = 0.0;
65 pVertex[1].color = 0x00ffffff; //0x00cfd0ef;
66 pVertex[2].position = D3DXVECTOR3( -fUnit, -fUnit, 1.f );
67 pVertex[2].tu = 0.0;
68 pVertex[2].tv = fGets;
69 pVertex[2].color = 0x00ffffff; //0x00cfd0ef;
70 pVertex[3].position = D3DXVECTOR3( fUnit, -fUnit, 1.f );
71 pVertex[3].tu = fGets;
72 pVertex[3].tv = fGets;
73 pVertex[3].color = 0x00ffffff;
74 m_pDirect3DVertexBuffer->Unlock(); return RME_SUCCESS;
}六、在播放每一帧时,调用下面的方法画图像:
void PlayUYVYFrame2(char *Videodata, int toltal_ch, int ch)
{
75 if ( m_pDirect3DDevice == NULL )
return; // 这一句好象要不要其效果都是一样的,所以暂时先不要。
76 m_pDirect3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
D3DCOLOR_XRGB(255,255,255), 1.0f, 0 );77 if ( FAILED(m_pDirect3DDevice->BeginScene()) )
{
return;
} LRESULT lRet;
78 lRet = m_pDirect3DDevice->SetTexture( 0, m_pDirect3DTexture );79 D3DLOCKED_RECT d3dLock;
RECT rc;
static long lCounter;
TCHAR szTitle[32];80 lRet = m_pDirect3DTexture->LockRect( 0, &d3dLock, 0, 0 );
81 if ( SUCCEEDED(lRet) )
{
82 // 拷贝图像数据到材质库中
memcpy( d3dLock.pBits, Videodata, m_lVideoHeight * m_lVideoWidth * 2 ); // 写字,这部分先不管它
83 if ( m_pD3DSprite && m_pD3DFont )
{
84 if ( SUCCEEDED(m_pD3DSprite->Begin( D3DXSPRITE_ALPHABLEND | D3DXSPRITE_SORT_TEXTURE )) )
{
sprintf( szTitle, "counter:%d", lCounter++ );
SetRect( &rc, 5, 5, 100, 20 );
85 lRet = m_pD3DFont->DrawText( m_pD3DSprite, szTitle, lstrlen(szTitle),
&rc, DT_NOCLIP | DT_BOTTOM, D3DXCOLOR( 0.0f, 0.0f, 0.0f, 0.0f ) );
m_pD3DSprite->End();
}
}
86 m_pDirect3DTexture->UnlockRect( 0 );
}87 m_pDirect3DDevice->SetStreamSource( 0, m_pDirect3DVertexBuffer,
0, sizeof(CUSTOMVERTEX) );
88 m_pDirect3DDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
89 m_pDirect3DDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );90 m_pDirect3DDevice->EndScene();
91 m_pDirect3DDevice->Present( NULL, NULL, NULL, NULL );
}现象描述:
开始的定义中,使用directx文档中的定义(第12行),可以显示出图像,但是图像在暗的地方会偏暗红,在亮的地方会偏绿,整体上偏暗红色
为了测试,使用第13行的定义,则不会显示出图像,这时可以看到背景的颜色是暗红色,但在第61、65、69、73行指定的都是白色!实际的播放效果请参考附件的图片请各位帮个大忙,thx a lot...

解决方案 »

  1.   

    没看代码,不过你说的暗红,应该是yuv格式的转换不对
      

  2.   

    12//#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ &brvbarD3DFVF_DIFFUSE &brvbarD3DFVF_TEX1) 顶点色和纹理色
    13 #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ &brvbarD3DFVF_DIFFUSE) 顶点色
    14 //#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW &brvbarD3DFVF_DIFFUSE) 顶点色屏幕2D绘图去看下D3D的FVF设置吧~~`
      

  3.   

    D3DXYZ默认的坐标系统用户区中心是 (0,0) 而rhw的左上角是 (0,0)
    D3DXYZ默认的非光照的,而D3DFVF_XYZRHW默认就是高洛夫的光照模式。
    使用D3DFVF_XYZRHW时渲染前要关闭灯光, 见下面代码~~
    g_pd3dDevice->SetRenderState(D3DRS_LIGHTING,FALSE);
      

  4.   

    我把源代码上传了,在
    http://download.csdn.net/source/555673
    请大家帮帮忙,有解决的给我留个言或者发邮件,谢谢!
      

  5.   

    #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)
    struct CUSTOMVERTEX
    {
    FLOAT x, y, z, rhw; // The transformed position for the vertex.
    DWORD color;   // The vertex color.
    FLOAT tu, tv; //texture position
    };//g_Vertices 等价于你的顶点填充时用的 pVertex
    CUSTOMVERTEX g_Vertices[] =
    {
    {   0.0f,   0.0f, 0.0f, 1.0f, D3DCOLOR_XRGB(255, 255, 255), 0.0f, 0.0f }, // x, y, z, rhw, color
    { 250.0f,   0.0f, 0.0f, 1.0f, D3DCOLOR_XRGB(255, 255, 255), 1.0f, 0.0f},
    {   0.0f, 250.0f, 0.0f, 1.0f, D3DCOLOR_XRGB(255, 255, 255), 0.0f, 1.0f},
    { 250.0f, 250.0f, 0.0f, 1.0f, D3DCOLOR_XRGB(255, 255, 255), 1.0f, 1.0f},
    };
    用上面这些替代你相应的部分,搞定!
      

  6.   


    我试了一下,和原来的完全一样,在http://download.csdn.net/source/555673下载后,按照这个方法进行修改,你试一试
      

  7.   

    按照16楼 dux003 的方法,我把它修改了,重新上传,位置:
    http://download.csdn.net/source/576314
      

  8.   

    你的YUV文件有问题,文件长度明显不是宽或者高的整数倍
    另外你创建Texture的时候设置的数据格式可能也有问题,你设置的是RGB格式的,那里必须与你文件数据的真实格式一致,否则需要手动转换
    RGB和YUV格式的具体说明可以参见http://www.fourcc.org/
    顶点填充的时候,tu、tv是归一化的值,范围为0.0到1.0, (0.0, 0.0)表示原始画面的左上角,(1.0, 1.0)表示原始画面的右下角,若设成(0.5, 0.5)则只能显示YUV数据的左上角的1/4图案
    我在你的基础上改了一下,显示我自己的数据,已经正常了。如果你需要,请告诉我你的邮箱
      

  9.   

    to dux003:是不是说,在初始化Direct3D时,其图片的宽度和高度,都要指定正确?在directx的文档上说,其宽度和高度可以为0
    使用我提供的yuv数据,能否显示出来正常的图像?
    我修改
    //m_directx.InitDirect3D( GetSafeHwnd(), 352, 288 );
    m_directx.InitDirect3D( GetSafeHwnd(), 720, 576 );
    显示我的图片,发现上面一部分是正常的,正面大部分是不正常的是我的yuv格式和direct3d的格式不匹配造成的吗?
      

  10.   

    图片的宽度和高度以及像素格式是要正确指定的
    DX根据宽度和像素格式确定pitch的值,也就是每一行的字节数,再根据高确定每一帧总的内存大小
    格式指定不对时,除了显示图像不对外,还可能导致崩溃你的问题应该是yuv格式不对,而且数据也有问题,文件大小明显不是高或宽的整数倍
      

  11.   

    非常感谢dux003!
    终于搞定了!在
    lRet = m_pDirect3DDevice->CreateTexture( lWidth, lHeight, 1, D3DUSAGE_SOFTWAREPROCESSING,
    /*D3DFMT_X8R8G8B8*/D3DFMT_UYVY/*/D3DFMT_YUY2/**/,
    /*D3DPOOL_SYSTEMMEM/*D3DPOOL_SCRATCH/*/D3DPOOL_MANAGED/*D3DPOOL_DEFAULT*/,
    &m_pDirect3DTexture, NULL );
    中,第5个参数原来使用D3DFMT_YUY2,是不行的,把它改为D3DFMT_UYVY就好了!dx文档看起来有些晕,参数太多了,想搞通是不大容易啊