视频处理之OSD

欲观原文,请君移步

OSD简介

OSD,on-screen display的简称,即屏幕菜单式调节方式。一般我们按一下Menu键后屏幕弹出的显示器各项调节项目信息的矩形菜单,比如调亮度,色调,饱和度等信息,这个显示这个菜单的功能就是视频行业的OSD。

基于FPGA的OSD设计与实现

1 Xilinx OSD IP功能

  • 支持最多8个layer
  • 背景颜色可编程
  • 位置,大小,颜色,透明度(alpha)可编程
  • 支持RGB和YUV视频流

2 硬件结构框图

硬件平台是基于xilinx xc7z035芯片开发的,关键模块框图如下图1所示。

  • 一个时序产生模块Video Timing Controller(在本次实验中采用1080P标准时序)

  • 首先PL端将视频流通过VDMA读出,输出接口为AXI4-Stream的数据流

  • 然后视频流进入OSD IP(OSD输入输出也是AXI4-Stream接口)

  • 最后OSD输出数据流与1080P时序同时送入到AXI4-Stream to Video Out模块,输出为HDMI接口

图1
图1

下面小编会详细介绍OSD IP的例化与使用

3 OSD PL端

如果在使用OSD IP过程中出现如下错误,请在xilinx官网上申请OSD的License,这里不再详述如何申请License。

首先在Block Design中加入Video On Screen Display,打开后会看到如下图2。

(1) 勾选AXI-Lite Interface:PS端通过AXI-Lite进行配置该IP

(2) Video Format选择RGB

(3) Layers选择2

(4) Layer Configuration:LAYER0选择外部视频流,也就是实时视频,LAYER1选择Internal,PS端可以控制进行图文叠加

图2
图2

点击Screen Layout Options,如图3所示

(1) Background size(选择背景大小)里宽度输入1920,高度输入1080

(2) Background color输入背景颜色,这里选择黑色,可以通过axi-lite来控制

(3) layer0因为选择的是外部视频流,所以比如设置为外部视频流分辨率,输错了,可能无法正常使用,小编已经遇到过了,本文使用1920x1080外部视频流

(4) layer1因为选择的是内部图像控制器,所以无所谓设置什么,可以通过axi-lite控制,所以选择默认即可

图3
图3

点击LAYER 1 Options出现图4界面:因为是内部图像控制器,所以可以进行一些配置,比如颜色多少,字符数目,比特像素等等,这里小编选择的是默认。

图4
图4

配置完OSD IP后,将其AXI-lite挂在总线上即可,然后保存Block Design即可。

注:点开Address Editor,一定要确定该IP被分配地址空间,如果没有,点击一下自动分配(小编遇到的问题就是这个ip地址空间在unmap里,导致后续PS端OSD IP无法初始化)。

图4
图4

4 OSD PS端

下面就是常规操作include bitstream导出SDK,其实就是生成hdf文件,硬件信息。然后就launch SDk。如图4所示,可以看到hdf文件里都有什么。

图4
图4

新建一个design_top的空工程,如图5所示,在design_top_bsp下面可以看到system.mss文件,在红框中找到OSD IP。

图5
图5

点击import examples,出现如图6所示,勾选对话框后选择OK(不会玩IP先整个example)。

图6
图6

打开XosdSelfTestExample.c即可看到该例子程序是怎么个处理流程(图7为main函数,图8为使用流程)小编称之为PS端IP使用三步法

  • 第一步先进行lookup该IP

  • 第二步就是初始化该IP

  • 第三步就是使用IP

图7
图7
图8
图8

运行一下,结果如图9所示,可以看到UART会打印OSD成功信息。

图9
图9

OSD 实例

闲话不说,上面经过了OSD example,小编也作为一个PS端初学者来玩一玩。

尴尬的是经常在写c代码的时候想着写begin…end,真是verilog写习惯了,思想难以改变,原来是花括弧啊{}

初始化模块如下

在初始化后必须将该模块进行复位,然后,否则该IP启动不了。

int OsdInit(int DeviceID)
{
    int Status;
    /* Initialize the OSD instance */
    OsdCfgPtr = XOSD_LookupConfig(DeviceID);
    Status = XOSD_CfgInitialize(&Osd, OsdCfgPtr,OsdCfgPtr->BaseAddress);
    if (Status != XST_SUCCESS)      return 1;
    /* Reset the devices */
    XOSD_Reset(&Osd);
    /* Enable the OSD device and tell it to pick up the register changes    */
    XOSD_Enable(&Osd);
    XOSD_RegUpdateEnable(&Osd);
    return 0;
}

配置模块

这里需要注意的是把BANKIndex输入为1,否则会进行字符填写方式就需要改变,不符合操作习惯XOSD_LoadCharacterSetBank(&Osd, Gcindex, 1, (u32 *)Font);

void Graphics_setting(u8 Gcindex,u8 LayerPriority,u32 ColorData[],u32 *TextData)
{
    int width = 1920;
    int height = 1080;
    int LayerAlphaValue = 0xFF;
    int LayerGlobalAlphaEnable = 0;
    XOSD_SetLayerAlpha(&Osd, Gcindex, LayerGlobalAlphaEnable,LayerAlphaValue);
    XOSD_SetLayerPriority(&Osd, Gcindex, LayerPriority);
    XOSD_SetLayerDimension(&Osd, Gcindex, 00, width, height);
    XOSD_EnableLayer(&Osd, Gcindex);
    /* Load color, font and text and set the active banks */
    XOSD_LoadColorLUTBank(&Osd, Gcindex, 0, ColorData);
    //set BankIndex is 1(fit our keyboard)
    XOSD_LoadCharacterSetBank(&Osd, Gcindex, 1, (u32 *)Font);
    XOSD_LoadTextBank(&Osd, Gcindex, 0, (u32 *)TextData);
    XOSD_SetActiveBank(&Osd, Gcindex, 0000);
}

图文叠加模块

void OsdDrawText(int Gcindex,int x_pos, int y_pos, int color, int string_index, int text_size)
{
    u32 Instruction[XOSD_INS_SIZE];
    u16 ObjType = XOSD_INS_OPCODE_BOXTXT; /* A text string  XOSD_INS_OPCODE_TXT*/
    u8 ObjSize = (text_size<<4); /* Text Scale factor (1x, 2x, 4x, 8x)  */
    u16 XStart = x_pos; /* Horizontal start pixel of the text   */
    u16 YStart = y_pos; /* Vertical start line of the text */
    u16 XEnd = x_pos; /* Horizontal end pixel of the text (not  used) */
    u16 YEnd = y_pos; /* Vertical end line of the text (must be same as YStart) */
    u8 TextIndex = string_index; /* Index of Text String */
    u8 ColorIndex = color; /* Color used to draw text */


    XOSD_CreateInstruction(&Osd, Instruction, Gcindex,ObjType, ObjSize, XStart, YStart, XEnd, YEnd,TextIndex, ColorIndex);
    XOSD_LoadInstructionList(&Osd, Gcindex, 0, Instruction, 1);
    return;
}

实现结果

前面只给出了两个图层,工程退不回去了,目前工程实现的是叠加8个图层(1个视频,7个内部图像控制器)。

参考链接

百度网盘源码以及参考文档链接如下

OSD简介

OSD,on-screen display的简称,即屏幕菜单式调节方式。一般我们按一下Menu键后屏幕弹出的显示器各项调节项目信息的矩形菜单,比如调亮度,色调,饱和度等信息,这个显示这个菜单的功能就是视频行业的OSD。

基于FPGA的OSD设计与实现

1 Xilinx OSD IP功能

  • 支持最多8个layer
  • 背景颜色可编程
  • 位置,大小,颜色,透明度(alpha)可编程
  • 支持RGB和YUV视频流

2 硬件结构框图

硬件平台是基于xilinx xc7z035芯片开发的,关键模块框图如下图1所示。

  • 一个时序产生模块Video Timing Controller(在本次实验中采用1080P标准时序)

  • 首先PL端将视频流通过VDMA读出,输出接口为AXI4-Stream的数据流

  • 然后视频流进入OSD IP(OSD输入输出也是AXI4-Stream接口)

  • 最后OSD输出数据流与1080P时序同时送入到AXI4-Stream to Video Out模块,输出为HDMI接口

图1
图1

下面小编会详细介绍OSD IP的例化与使用

3 OSD PL端

如果在使用OSD IP过程中出现如下错误,请在xilinx官网上申请OSD的License,这里不再详述如何申请License。

首先在Block Design中加入Video On Screen Display,打开后会看到如下图2。

(1) 勾选AXI-Lite Interface:PS端通过AXI-Lite进行配置该IP

(2) Video Format选择RGB

(3) Layers选择2

(4) Layer Configuration:LAYER0选择外部视频流,也就是实时视频,LAYER1选择Internal,PS端可以控制进行图文叠加

图2
图2

点击Screen Layout Options,如图3所示

(1) Background size(选择背景大小)里宽度输入1920,高度输入1080

(2) Background color输入背景颜色,这里选择黑色,可以通过axi-lite来控制

(3) layer0因为选择的是外部视频流,所以比如设置为外部视频流分辨率,输错了,可能无法正常使用,小编已经遇到过了,本文使用1920x1080外部视频流

(4) layer1因为选择的是内部图像控制器,所以无所谓设置什么,可以通过axi-lite控制,所以选择默认即可

图3
图3

点击LAYER 1 Options出现图4界面:因为是内部图像控制器,所以可以进行一些配置,比如颜色多少,字符数目,比特像素等等,这里小编选择的是默认。

图4
图4

配置完OSD IP后,将其AXI-lite挂在总线上即可,然后保存Block Design即可。

注:点开Address Editor,一定要确定该IP被分配地址空间,如果没有,点击一下自动分配(小编遇到的问题就是这个ip地址空间在unmap里,导致后续PS端OSD IP无法初始化)。

图4
图4

4 OSD PS端

下面就是常规操作include bitstream导出SDK,其实就是生成hdf文件,硬件信息。然后就launch SDk。如图4所示,可以看到hdf文件里都有什么。

图4
图4

新建一个design_top的空工程,如图5所示,在design_top_bsp下面可以看到system.mss文件,在红框中找到OSD IP。

图5
图5

点击import examples,出现如图6所示,勾选对话框后选择OK(不会玩IP先整个example)。

图6
图6

打开XosdSelfTestExample.c即可看到该例子程序是怎么个处理流程(图7为main函数,图8为使用流程)小编称之为PS端IP使用三步法

  • 第一步先进行lookup该IP

  • 第二步就是初始化该IP

  • 第三步就是使用IP

图7
图7
图8
图8

运行一下,结果如图9所示,可以看到UART会打印OSD成功信息。

图9
图9

OSD 实例

闲话不说,上面经过了OSD example,小编也作为一个PS端初学者来玩一玩。

尴尬的是经常在写c代码的时候想着写begin…end,真是verilog写习惯了,思想难以改变,原来是花括弧啊{}

初始化模块如下

在初始化后必须将该模块进行复位,然后,否则该IP启动不了。

int OsdInit(int DeviceID)
{
    int Status;
    /* Initialize the OSD instance */
    OsdCfgPtr = XOSD_LookupConfig(DeviceID);
    Status = XOSD_CfgInitialize(&Osd, OsdCfgPtr,OsdCfgPtr->BaseAddress);
    if (Status != XST_SUCCESS)      return 1;
    /* Reset the devices */
    XOSD_Reset(&Osd);
    /* Enable the OSD device and tell it to pick up the register changes    */
    XOSD_Enable(&Osd);
    XOSD_RegUpdateEnable(&Osd);
    return 0;
}

配置模块

这里需要注意的是把BANKIndex输入为1,否则会进行字符填写方式就需要改变,不符合操作习惯XOSD_LoadCharacterSetBank(&Osd, Gcindex, 1, (u32 *)Font);

void Graphics_setting(u8 Gcindex,u8 LayerPriority,u32 ColorData[],u32 *TextData)
{
    int width = 1920;
    int height = 1080;
    int LayerAlphaValue = 0xFF;
    int LayerGlobalAlphaEnable = 0;
    XOSD_SetLayerAlpha(&Osd, Gcindex, LayerGlobalAlphaEnable,LayerAlphaValue);
    XOSD_SetLayerPriority(&Osd, Gcindex, LayerPriority);
    XOSD_SetLayerDimension(&Osd, Gcindex, 00, width, height);
    XOSD_EnableLayer(&Osd, Gcindex);
    /* Load color, font and text and set the active banks */
    XOSD_LoadColorLUTBank(&Osd, Gcindex, 0, ColorData);
    //set BankIndex is 1(fit our keyboard)
    XOSD_LoadCharacterSetBank(&Osd, Gcindex, 1, (u32 *)Font);
    XOSD_LoadTextBank(&Osd, Gcindex, 0, (u32 *)TextData);
    XOSD_SetActiveBank(&Osd, Gcindex, 0000);
}

图文叠加模块

void OsdDrawText(int Gcindex,int x_pos, int y_pos, int color, int string_index, int text_size)
{
    u32 Instruction[XOSD_INS_SIZE];
    u16 ObjType = XOSD_INS_OPCODE_BOXTXT; /* A text string  XOSD_INS_OPCODE_TXT*/
    u8 ObjSize = (text_size<<4); /* Text Scale factor (1x, 2x, 4x, 8x)  */
    u16 XStart = x_pos; /* Horizontal start pixel of the text   */
    u16 YStart = y_pos; /* Vertical start line of the text */
    u16 XEnd = x_pos; /* Horizontal end pixel of the text (not  used) */
    u16 YEnd = y_pos; /* Vertical end line of the text (must be same as YStart) */
    u8 TextIndex = string_index; /* Index of Text String */
    u8 ColorIndex = color; /* Color used to draw text */


    XOSD_CreateInstruction(&Osd, Instruction, Gcindex,ObjType, ObjSize, XStart, YStart, XEnd, YEnd,TextIndex, ColorIndex);
    XOSD_LoadInstructionList(&Osd, Gcindex, 0, Instruction, 1);
    return;
}

实现结果

前面只给出了两个图层,工程退不回去了,目前工程实现的是叠加8个图层(1个视频,7个内部图像控制器)。

参考链接

百度网盘源码以及参考文档链接如下

  • 8
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
FPGA OSD视频是一种基于可编程逻辑器件(FPGA)的图像显示技术。OSD是英文"On-Screen Display"的缩写,指的是将相关信息叠加在视频画面上显示给用户的功能。 使用FPGA实现OSD视频具有以下优势: 首先,FPGA具有高度灵活的配置能力和强大的并行计算能力。这使得FPGA能够实时处理和叠加大量的图像信息,包括文字、图标、刻度等各种元素,并将其准确地显示在视频画面上。因此,FPGA OSD视频可以提供高质量和高性能的显示效果。 其次,FPGA可以根据需求进行定制化开发。使用FPGA实现OSD视频,可以根据具体的应用场景和需求进行灵活的设计和配置。用户可以自定义文字、图标的颜色、大小、位置等属性,以及实时更新显示内容。这种灵活性使得FPGA OSD视频能够适应不同的应用要求,如监控系统、航空航天等。 此外,FPGA还具有低功耗和实时性能优势。相比于传统的软件OSD实现方式,FPGA OSD视频利用硬件并行计算的特性,可以实时地叠加信息并输出到视频画面上,且功耗较低。这使得FPGA OSD视频在要求低延迟和实时性能的场景中具有重要的应用价值。 总的来说,FPGA OSD视频是一种基于FPGA的图像显示技术,通过灵活的配置和强大的并行计算能力,可以实现高质量、高性能的信息叠加显示。这种技术在监控系统、航空航天等领域具有重要的应用潜力。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值