Telechips 8902 & WinCE6.0 平台下 overlay 使用冲突现象的分析

最近在分析播放视频(mkv 格式)引起显示异常的问题。
平台为: WinCE6.0;CPU 为 Telechips8902.
发现在主菜单/设置/多媒体类型选择等界面会出现问题;但在导航界面不会出现问题。所以分析问题的原因与主菜单等界面的显示方式有关,查看代码发现主菜单等界面使用 overlay 显示。
由于视频显示也采用 overlay 方式(怀疑 mkv 格式视频的显示比其它格式显示多使用一层 overlay 表面),可能是因为 overlay 表面使用冲突引起主菜单等显示异常的问题。需要分析视频显示的实现过程与 UI 的实现过程来确认是否是此原因?
UI 代码中 overlay 的实现是通过 IOCtrl 来实现的,没有通过系统标准的 overlay 访问接口。

Telechips 8902 共 2 层 overlay surface,视频播放使用一层(YUV);UI 的显示采用 IOCtrl 直接通过 OS 写屏操作,经测试发现使用一层 overlay(RGB) surface;此时如果视频播放的视频文件格式需要需要通过 overlay 显示 SUB-TITLE 时,与 UI 显示使用的 overlay 表面资源冲突。这样导致了如上问题的产生。

为了排除 UI 实现对上述结果的影响,采用 DirectDraw 示例工程 mosquito 与视频一起运行,看是否可以重现上述问题:
先运行 mosquito,界面出现蚊子飞的动画效果。此时,再运行 Telechips 的示例工程 TCMovieManager。先选择一首没有字幕的视频播放,发现视频与  mosquito 的效果(蚊子飞的动画)同时存在。此时将视频切换到带有字幕的视频,开始视频播放后,发现 mosquito 的效果(蚊子飞的动画)消失。这样就重现了 UI 界面与视频冲突的现象!

此问题,单独从应用层来分析比较难解决。
个人建议的方法:
(1)从 OS 入手,修改视频播放时对字幕(SUB-TITLE)的处理,字幕(SUB-TITLE)要不不显示、要不显示在视频 overlay 层上;
(2)考虑不再实现视频后台播放的功能。

附部分 mosquito 的源代码,主要包括 overlay 层格式与初始化:

  1 /* 
  2  * Telechips 8902 支持 2 层 overlay 
  3  * 只能创建一层 YUYV 的 overlay (可以再创建一层 RGB overlay) 
  4  * RGB 模式可以创建多个,模式与顺序没有不影响创建 
  5 */  
  6 static DDPIXELFORMAT ddpfOverlayFormats[] = {  
  7     //{sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y','U','Y','V'),0,0,0,0,0},  // YUYV - Leo.Zheng Telechips 8902 可以支持  
  8     //{sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U','Y','V','Y'),0,0,0,0,0},  // UYVY - Leo.Zheng Telechips 8902:Create No.1 surface return: 0x88760218  
  9     // {sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16,  0x7C00, 0x03e0, 0x001F, 0},        // 16-bit RGB 5:5:5  
 10     {sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16,  0xF800, 0x07e0, 0x001F, 0},        // 16-bit RGB 5:6:5  
 11 };  
 12   
 13 #define PF_TABLE_SIZE (sizeof(ddpfOverlayFormats) / sizeof(ddpfOverlayFormats[0]))  
 14   
 15   
 16   
 17 //-----------------------------------------------------------------------------  
 18 // Name: InitApp()  
 19 // Desc: Do work required for every instance of the application:  
 20 //          Create the window, initialize data  
 21 //-----------------------------------------------------------------------------  
 22 static HRESULT InitApp(HINSTANCE hInstance, int nCmdShow)  
 23 {  
 24     HWND                        hWnd;  
 25     WNDCLASS                    wc;  
 26     DDSURFACEDESC               ddsd;  
 27     DDCAPS                      ddcaps;  
 28     HRESULT                     hRet;  
 29     DWORD                       dwUpdateFlags = 0;  
 30     DDOVERLAYFX                 ovfx;  
 31     DEVMODE                     DevMode;  
 32   
 33     // Check for rotation support by getting the rotation angles supported.  
 34     memset(&DevMode, 0, sizeof(DevMode));  
 35     DevMode.dmSize = sizeof(DevMode);  
 36     DevMode.dmFields = DM_DISPLAYQUERYORIENTATION;  
 37     if(DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettingsEx(NULL, &DevMode, NULL, CDS_TEST, NULL))  
 38     {  
 39         g_RotationAngles = DevMode.dmDisplayOrientation;  
 40     }  
 41     else  
 42     {  
 43         OutputDebugString(L"MOSQUITO: Device does not support any rotation modes. Rotation disabled.");  
 44         g_RotationAngles = -1;  
 45     }  
 46   
 47     // Get the current rotation angle.  
 48     memset(&DevMode, 0, sizeof (DevMode));  
 49     DevMode.dmSize = sizeof (DevMode);  
 50     DevMode.dmFields = DM_DISPLAYORIENTATION;  
 51     if (DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettingsEx(NULL, &DevMode, NULL, CDS_TEST, NULL))  
 52     {  
 53         g_CurrentAngle = DevMode.dmDisplayOrientation;  
 54     }  
 55     else  
 56     {  
 57         OutputDebugString(L"MOSQUITO: Unable to read current rotation. Rotation disabled.");  
 58         g_CurrentAngle = -1;  
 59     }  
 60   
 61     // Set up and register window class.  
 62     ......  
 63   
 64     // Create the main DirectDraw object  
 65     hRet = DirectDrawCreate(NULL, &g_pDD, NULL);  
 66     if(hRet != DD_OK)  
 67         return InitFail(hWnd, hRet, TEXT("DirectDrawCreate FAILED"));  
 68   
 69     // Get normal mode.  
 70     hRet = g_pDD->SetCooperativeLevel(hWnd, DDSCL_NORMAL);  
 71     if (hRet != DD_OK)  
 72         return InitFail(hWnd, hRet, TEXT("SetCooperativeLevel FAILED"));  
 73   
 74     // Get a primary surface interface pointer (only needed for init.)  
 75     memset(&ddsd, 0, sizeof(ddsd));  
 76     ddsd.dwSize = sizeof(ddsd);  
 77     ddsd.dwFlags = DDSD_CAPS;  
 78     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;  
 79     hRet = g_pDD->CreateSurface(&ddsd, &g_pDDSPrimary, NULL);  
 80     if (hRet != DD_OK)  
 81         return InitFail(hWnd, hRet, TEXT("CreateSurface FAILED"));  
 82   
 83     // See if we can support overlays.  
 84     memset(&ddcaps, 0, sizeof(ddcaps));  
 85     ddcaps.dwSize = sizeof(ddcaps);  
 86     hRet = g_pDD->GetCaps(&ddcaps, NULL);  
 87     if (hRet != DD_OK)  
 88         return InitFail(hWnd, hRet, TEXT("GetCaps FAILED"));  
 89   
 90     if (ddcaps.dwOverlayCaps == 0)  
 91         return InitFail(hWnd, hRet, TEXT("Overlays are not supported in hardware!"));  
 92     /* // Leo.Zheng Add 
 93     if(!(capsDrv.dwCaps & DDCAPS_OVERLAY)) 
 94         return FALSE; 
 95     */  
 96   
 97     // Get alignment info to compute our overlay surface size.  
 98     rs.left = 0;  
 99     rs.top = 0;  
100     rs.right = BUG_WIDTH;  
101     rs.bottom = BUG_HEIGHT;  
102     if (ddcaps.dwAlignSizeSrc != 0)  
103         rs.right += rs.right % ddcaps.dwAlignSizeSrc;  
104       
105     // Create the overlay flipping surface. We will attempt the pixel formats  
106     // in our table one at a time until we find one that jives.  
107     int i = 0;  
108     memset(&ddsd, 0, sizeof(ddsd));  
109     ddsd.dwSize = sizeof(ddsd);  
110     ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_FLIP;  
111     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_BACKBUFFERCOUNT | DDSD_PIXELFORMAT;  
112     ddsd.dwWidth = rs.right;  
113     ddsd.dwHeight = rs.bottom;  
114     ddsd.dwBackBufferCount = 1;  
115     do  
116     {   // Leo.Zheng MStar 2521 只创建 16-bit RGB 5:6:5 成功; 创建 16-bit RGB 5:5:5 失败.  
117         ddsd.ddpfPixelFormat = ddpfOverlayFormats[i];  
118         hRet = g_pDD->CreateSurface(&ddsd, &g_pDDSOverlay, NULL);            // Leo.Zheng 此处调用后引起使用 IOCtrl 显示在 LCD 上的消失  
119         RETAILMSG(1,(L"[mosquito]Create No.%d surface return: 0x%X\r\n",i + 1,hRet));  
120     }while(hRet != DD_OK && (++i < PF_TABLE_SIZE));  
121     if(hRet != DD_OK)  
122         return InitFail(hWnd, hRet, TEXT("Unable to create overlay surface!"));  
123   
124     // Load the images.  
125     if (LoadBugImages() != DD_OK)  
126         return InitFail(hWnd, hRet, TEXT("Unable to load images to overlay surface!"));  
127   
128     // Finish setting up the overlay.  
129     int StretchFactor1000 = ddcaps.dwMinOverlayStretch > 1000 ? ddcaps.dwMinOverlayStretch : 1000;  
130   
131     rd.left=0;   
132     rd.top=0;  
133     // Adding 999 takes care of integer truncation problems.  
134     rd.right  = (rs.right * StretchFactor1000 + 999) / 1000;  
135     rd.bottom = rs.bottom * StretchFactor1000 / 1000;  
136     if (ddcaps.dwAlignSizeDest != 0)  
137         rd.right = (int)((rd.right + ddcaps.dwAlignSizeDest - 1)/ ddcaps.dwAlignSizeDest) * ddcaps.dwAlignSizeDest;  
138   
139     // Set the flags we'll send to UpdateOverlay  
140     dwUpdateFlags = DDOVER_SHOW;  
141     // dwUpdateFlags = DDOVER_SHOW | DDOVER_DDFX;           // Leo.Zheng DDOVER_DDFX WinCE 不支持  
142   
143     // Does the overlay hardware support source color keying?  
144     // If so, we can hide the black background around the image.  
145     // This probably won't work with YUV formats  
146     memset(&ovfx, 0, sizeof(ovfx));  
147     ovfx.dwSize = sizeof(ovfx);  
148     if (ddcaps.dwOverlayCaps & DDOVERLAYCAPS_CKEYSRC)           // MStar2521 不支持 color key  
149     {  
150         dwUpdateFlags |= DDOVER_KEYSRCOVERRIDE;  
151   
152         // Create an overlay FX structure so we can specify a source color key.  
153         // This information is ignored if the DDOVER_SRCKEYOVERRIDE flag   
154         // isn't set.  
155         ovfx.dckSrcColorkey.dwColorSpaceLowValue=0; // black as the color key  
156         ovfx.dckSrcColorkey.dwColorSpaceHighValue=0;  
157     }  
158     else  
159     {  
160         RETAILMSG(1,(L"[mosquito]cannot support color key: 0x%X(0x%x)\r\n",ddcaps.dwOverlayCaps,DDOVERLAYCAPS_CKEYSRC));  
161     }  
162   
163     // Update the overlay parameters.  
164     hRet = g_pDDSOverlay->UpdateOverlay(&rs, g_pDDSPrimary, &rd, dwUpdateFlags, &ovfx);  
165     if (hRet != DD_OK)  
166     {  
167         // 在 MStar 2521 设备上运行第二个此程序实例时出错。  
168         // 在 TeleChips 8902 设备上运行第三个此程序实例时出错。  
169         return InitFail(hWnd, hRet, TEXT("Unable to show overlay surface: 0x%x!"),hRet);  
170     }  
171   
172     // Set a bunch of position and velocity module vars.  
173     g_nOverlayXPos = 0;  
174     g_nOverlayYPos = 0;  
175     g_nOverlayXVel = RANDOM_VELOCITY();  
176     g_nOverlayYVel = RANDOM_VELOCITY();  
177     g_nOverlayWidth = rd.right - rd.left;  
178     g_nOverlayHeight = rd.bottom - rd.top;  
179       
180     // Set the "destination position alignment" global so we won't have to  
181     // keep calling GetCaps() everytime we move the overlay surface.  
182     g_dwOverlayXPositionAlignment = ddcaps.dwAlignBoundaryDest;  
183   
184     // Create a timer to flip the pages.  
185     if (TIMER_ID != SetTimer(hWnd, TIMER_ID, TIMER_RATE, NULL))  
186         return InitFail(hWnd, hRet, TEXT("SetTimer FAILED"));  
187   
188     return DD_OK;  
189 }  

 

posted @ 2016-02-21 16:03  91program  阅读(445)  评论(0编辑  收藏  举报