所谓的OSD其实就是在视频图像上叠加一些字符信息,比如时间,地点,通道号等, 在图像上叠加OSD通常有两种方式: 一种是在前端嵌入式设备上,在图像数据上叠加OSD, 这样客户端这边只需解码显示数据即可。另一种是PC客户端在接收到前端设备图像,解码之后,进行叠加。这两种都是比较常见的方式。 OSD具有字符型(Font-Based)和位图型(Bit-Map)两种类型。 字符型OSD:为了节约显示缓存,早期及低成本的解决方案中使用字符型OSD发生器,其原理是将OSD中显示内容按照特定的格式(12×18、12×16等)进行分割成块,例如数字0-9、字母a-z、常用的亮度、对比度符号等,并把这些内容固化在ROM或Flash中,在显示缓存中仅存放对应的索引号,这样的“字典”结构可以大幅度减少显示缓存的需求。 位图OSD:通过对最终显示内容上特定区域的每个像素点进行改变,直接将OSD信息叠加到最终的显示画面上,其按像素进行控制的方式可以保证具有多色及足够的表现能力。 最近做一个网络播放器, 有在播放器实时叠加OSD这个需求,正好借这个机会研究了一下位
int posAx=0, posAy=0;int posDx=0 ,posDy=0;int nBKColor = 0;for(i = 0; i < m_OSDHeigth; i++)
{ for(j = 0; j < m_OSDWidth; j++)
{ if( j+_dwStrPosX>=_VideoWidth || i+_dwStrPosY>=_VideoHeight ) continue; // 找到字符 X if( m_palpha[i*m_OSDWidth + j] )// 找到x映射在在源图像上的13*13 背景块
{
posAx = _dwStrPosX+j - 3; // 计算背景色块 A的坐标 if ( posAx<0 )
posAx=0;
posAy = _dwStrPosY+i -3; if ( posAy<0 )
posAy =0;
posDx = _dwStrPosX+j + 3; // 计算背景色块 点D的坐标 if ( posDx >_VideoWidth)
posDx =_VideoWidth;
posDy = _dwStrPosY+i +3; if ( posDy >_VideoHeight)
posDy =_VideoHeight; // / 计算背景色块 长,宽 int height_ = posDy-posAy; int width_ = posDx-posAx;
UINT16* pTempDesY = (UINT16*)dest_buf + posAx + posAy*_VideoWidth; int nTemp = 0; for ( m=0; m< height_; m++ )//height
{ for ( n=0; n<width_;n++ )
{
nTemp += ( (*pTempDesY) >>2 );
pTempDesY++;
}
pTempDesY = (UINT16*)dest_buf + posAx + posAy*_VideoWidth + m*_VideoWidth;
}
// 计算Y 的平均值
nBKColor = nTemp/(height_*width_); if ( nBKColor >128 ) *pY = 0; else
*pY = ( 255<<2);
}
pDesY++;
pY++;
}//j
pDesY = ((UINT16*)dest_buf + _dwStrPosX + _dwStrPosY*_VideoWidth) + i*_VideoWidth;
}//i
效果图: