1 引言
开发完善的机顶盒产品,友好的用户界面是其中不可或缺的一部分。它使用户对机顶盒系统的设置和操作变得简单而形象。osd(on screen display——现场显示显示信息)提供一种在电视节目图像上叠加输出图形及文字的一种操作,通过软件编程可以提供一套图形函数接口,以便进一步根据不同应用需要进行图形用户界面(gui)的开发。
2 硬件系统
机顶盒硬件系统结构如图1所示。系统由含解复用硬件单元的cpu,视频解码模块,音频解码模块、视频编码输出单元、音频d/a转换单元、高频头单元、 tuner(调谐器)、qam解调器、存储系统(包括系统dram, flash rom, eeprom、视频解码sdram)、jtag接口、遥控和前面板控制芯片等组成。

图1 机顶盒硬件系统结构图
从卫星、有线和地面来的视频节目信号被接收后,先由高频头进行解调,解调输出的ts流送至解复用芯片,该芯片对送来的ts流进行解复用,并将当前有效的音 频和视频数据包分别送往音频和视频解码芯片进行音频和视频解码。解码芯片对送来的音、视频数据进行解码后经输出单元输出。
3 软件系统
机顶盒软件系统采用了分层体系结构进行描述和实现。这样,一旦硬件模块发生变化,软件的实现只需修改和硬件相关的固件层,中间层和应用层可以保持不变,可大大节省编程时间,提高代码的重用率。保证了软件的实现在硬件模块,主要是微处理芯片发生变动时,软件只需最小的修改和维护。机顶盒软件系统的分层模型如图2所示。

图2 机顶盒软件系统的分层模型
固件层主要有硬件bios和实时内核,完成对硬件设备的最低层的封装。驱动层对各系统设备进行了进一步的封装,为flash、eeprom、智能卡、前面 版、以及高频头等设备提供驱动程序、图形引擎等。中间件层对驱动进行封装,为应用层提供所需各个功能的具体实现。使应用程序独立于操作系统和硬件平台,从而将应用的开发变得更加简捷,使产品的开放性和可移植性更强。中间件层主要有信道控制、解复用控制、解码控制、网络控制等模块、人机接口。与机顶盒有关的 上层功能的实现在应用层完成。
4 基于osd的gui设计
gui的基本功能是向应用程序层提供图形和文字显示的api以及图形元素的组织机制。系统中gui的设计和实现建立在osd的基础上。
机顶盒软件系统的设计是在hmd2003硬件环境和软件开发包下进行,并以keil uvision2 c51作为开发和调试工具。
4.1 osd图形引擎模块
虽然hmd2003的osd单元从硬件上提供了对osd的支持,但如果每次输出osd数据时都对底层的硬件进行操作,其操作过程将非常繁琐,并且容易出 错。系统的osd模块采用分层设计的思想,并结合hmd2003硬件特性进行设计。整个osd模块实现函数分三层:硬件层、api层、应用层。osd图形库分层结构如图3所示。在用户应用程序与底层的osd硬件之间增加了osd图形库,它提供了功能完备的api函数,其目的是为了屏蔽底层的硬件细节,便于上层应用的开发。该结构使最终的菜单设计只涉及一些应用层函数,不仅可以在所提供的函数包上做出完善的osd界面,也很容易在驱动层的基础上进行二次开发,做出适合自己的一些api层函数。

图3 osd图形库分层结构
hmd2003的开发包提供osd驱动层的画点、线、填充矩形、填充圆、汉字及英文显示等功能,并结合其硬件特性提供了一些功能更强的驱动函数如初始化区 域,关闭区域、初始化字库、拉幕、闭幕、区域拷备功能。这些函数也可以直接被应用程序调用。
4.2 封装基本图形显示的api
在设备驱动层中基本的图形函数包括点、线、矩形、填充等基本操作。在gui中将这些基本图形函数封装成api。主要实现了以下绘制基本图形的api:
(1) 画点
画点函数如下:
boolean gdi_ drawdot(unsigned int x, unsigned int y, unsigned char region_ no, unsigned char color);
参数 依次为所画点x坐标、y坐标、点所在的屏幕区域(一般将屏幕分为上下两个region,上部为电视节目区,界面菜单等都在这个区域显示;下部为信息显示 区,显示各个参数的信息)及所画点的颜色。
该函数的封装过程如下:
boolean gdi _drawdot (unsigned int x, unsigned int y, unsigned char region_no, unsigned char color)
{/*控制画点所在的屏幕区域*/
if(region_ no>2)
{
return(graph_ error);
}
/*控制点的颜色范围,分为4色和16色两种模式*/
if(osd_getcolormode(region_no)=4)
{
if(color>0x03)
return(graph_ error);
}
else
{if(color>0x0f)
return(graph_ error);
}
/*判断所画的点是否在指定的区域范围之内*/
if(x>graph_mesg[region no].region_ width)||(y>graph_ mesg[region_ no].region_height))
{
return(graph_error);
/*dot is not within osd area*/
}
/*现在点都在指定osd范围内,属于合法点*/
osd_dot(x, y, region_ no, color);
return(graph_ok);
}
(2) 画线
画线函数如下:
boolean gdi_ drawline(unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1,unsigned char region no,unsigned char color);
参数依次为线的起始点x,y坐标,结束点的x,y坐标,线所在的区域,以及线的颜色。该函数可以画直线或者斜线,该函数封装过程中同画点一样要控制画线所 在的屏幕区域,控制线的颜色范围,判断所画的直线是否在指定的区域范围之内。然后根据参数将直线分为点、水平线、垂直线和斜线处理。
(3) 画矩形
画矩形函数如下:
boolean gdi_ drawrectangle(unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1,unsigned char line_ width, unsigned char region_ no, unsigned char color);
参数分别为矩形左上角x,y坐标,右下角x,y坐标,线宽,所属区域,以及线的颜色。
(4) 画填充矩形。
画填充矩形函数如下:
boolean gdi_drawfilledrectangle(unsigned int x0, unsigned inty0, unsigned int x1, unsigned int yl,unsigned char region_no, unsigned char color);
参数分别为矩形左上角x,y坐标,右下角x,y坐标,所属区域,填充颜色。
(5) 画圆及填充圆
画圆及填充圆函数分别声明如下:
boolean gdi_drawcircle(unsigned int x, unsigned int y, unsigned int r, unsigned char region_no, unsigned char color);
boolean gdi_ drawfilledcircle(unsigned int x, unsigned int y, unsigned int r, unsigned char region_ no, unsigned charcolor);
参数为圆心的x,y坐标,半径大小,所属区域,及颜色。
4.3 封装控件元素的api
数字机顶盒的基本控制目标包括:ts流选择、节目管理、模拟量控制等,这样osd菜单系统通常要实现菜单、对话框、按钮、文本框、列表框、进度条、状态条等图形控件。
在本系统的osd中,控件结构都从一种统一结构出发进行构建,这也是借鉴c++中面向对象设计方法中的主类和派生类的思路。这样的设计方法使控件元素的显 示和管理能够方便的联系起来,程序结构也更加清晰。
(1) 菜单(menu)
标准menu由许多小单元组成,一个小单元代表一个可选项,同时menu还应支持对这些选项的索引、排序和删除等操作。
函数:menu_3dwindow(u8 region_no,u16 w_ posx,u16 w_posy,u16 w_width,u16 w_height, char*title)
功能:在指定区域,指定位置显示指定宽度、高度的菜单。并在菜单顶端显示该菜单的名称。
regionee no:该菜单显示的区域;
w_posx,w_posy:菜单显示的横坐标、纵坐标;
w_width,w_hight:菜单的宽度、高度;
*title:菜单名字符串的起始地址;
(2) 对话框(textbox)
主要用于用户输人数据或文字,支持一般的行编辑功能;
函数:menu_3ddialogbox(u8 region_no,u16 x, u16 y,u16 box_width,u16 box_height,char *title)
功能:在指定区域,指定位置显示指定宽度、高度的对话框。并在菜单顶端显示该对话框的名称。
region_no:该对话框显示的区域;
w_posx,w_posy:对话框显示的横坐标、纵坐标;
w_width,w_hight:对话框的宽度、高度;
*title::对话框名字符串的起始地址;
(3) 按钮(button)
主要用于用户选择和确定操作,一般只支持选中操作;
函数:menu_button(u16 x,u16 y,u16 but ton_width,u16 button_height,u8 se




