日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

海思平台OSD的实现(1)

發布時間:2024/3/12 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 海思平台OSD的实现(1) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

  • 一、海思平臺OSD理論學習
    • 1、OSD概述
    • 2、海思OSD的4種類型
    • 3、4種OSD類型各自支持的模塊和功能
    • 4、海思OSD的幾個重要概念
    • 5、海思平臺OSD使用方法
    • 6、海思平臺OSD的API和關鍵數據結構
  • 二、OSD實驗演示和代碼框架分析
    • 1、OSD實驗演示
    • 2、OSD代碼框架分析
  • 三、OSD代碼實現分析
    • 1、SAMPLE_RGN_CreateVideoRegion()所做的事
    • 2、前景和背景透明
    • 3、RGN(region)通道屬性分析
    • 4、RGN(region)內容填充
    • 5、動態刷新BMP
    • 6、小結——整體函數調用層次

一、海思平臺OSD理論學習

本部分內容的學習重點參考《HiMPP IPC V2.0 媒體處理軟件開發參考.pdf》

鏈接:https://pan.baidu.com/s/1R5KwdQxVPTXCNJUMCQCFJA 提取碼:onoh --來自百度網盤超級會員V5的分享

1、OSD概述

??OSD是on-screen display的簡稱,指屏幕菜單式調節方式。它通過顯示在屏幕上的功能菜單達到調整各項參數的目的,不但調整方便,而且調整的內容也比以上的兩種方式多,增加了失真、會聚、色溫、消磁等高級調整內容。像以前顯示器出現的網紋干擾、屏幕視窗不正、磁化等需要送維修廠商維修的故障,舉手之間便可解決。

??另外在OSD選項里還可以調整顯示的位置、無動作關閉顯示的時間。OSD核心是利用字符發生芯片在顯示器的屏幕上顯示需要的字符。

??技術方式是:與圖像實時同步附加或改變圖像中某些像素的顏色,使之組合成人類可以在圖像中辨識的數據。以固定或不固定的方式,改變某個特定的OSD控制暫存器,即可達到動態的效果。如:在熒幕上產生由左向右移動的OSD字形,只要將控制左右位置的OSD控制暫存器依序填入由小變大或由大變小的數值,OSD輸出字形自然隨更改的數值而做左右移動。

2、海思OSD的4種類型

? Overlay:視頻疊加區域,其中區域支持位圖的加載、背景色更新等功能。? OverlayEx:擴展視頻疊加區域,功能與 Overlay 類似,支持位圖加載、背景色 更新等。? Cover:視頻遮擋區域,其中區域支持純色塊遮擋。? CoverEx:擴展視頻遮擋區域,功能與 Cover 類似,支持純色塊遮擋。? OverlayEx/ CoverEx,分別相對于 Overlay/Cover,功能上類似,但是會引入額 外的系統帶寬, OverlayEx/ CoverEx 由 VGS 疊加到圖像上 , OverlayEx/ CoverEx 區域越大,占用 VGS 的性能就越大,當 VGS 性能不足時,會導致幀 率降低。建議只有當 Overlay/Cover 不支持,或者數量無法滿足需求時,再使 用。VGS是視頻圖形子系統,全稱為Video Graphics Sub-System。支持對一幅輸入圖像進行處理, 如進行縮放、格式轉換、解壓等處理。正常開發過程中,我們是不需要管vgs這個模塊的,但是當我們在性能不是很充裕的時候, 為了節約芯片性能,我們需要用vgs來替代vpss的功能。具體的做法是將vpss組的屬性能設置成flase的都設置成false,那么在vpss性能不夠時 就會自動用VGA來替代VPSS

3、4種OSD類型各自支持的模塊和功能



Argb:透明度、紅、綠、藍
alpha:透明度

4、海思OSD的幾個重要概念

(1)區域層次
??區域層次表示區域的疊加級別,層次值越大,表示區域的顯示級別越高。當發生重疊時,層次值大的將會覆蓋層次值小的。如果是同一級別,則根據區域疊加的,先后順序,后疊加的將顯示在上層。將多個區域疊加到 VPSS 的同一 GROUP時,要求每個區域的層次值不能與疊加到該 GROUP 的其他區域層次值相同,否則區域層次值相同的多個區域中,只能將最后一個疊加的區域疊加到 VPSS 的GROUP 上。將多個層次值相同的區域疊加到同一個 VENC 的通道上時,沒有此限制,都能疊加成功。

(2)位圖填充(針對 Overlay 和 OverlayEx 有效)
??位圖填充是指將位圖的內存值填充到區域內存空間中,位圖將會從區域的左上角開始填充

??當位圖小于區域時,只能填充一部分內存,剩余部分保持原有值;位
圖大小等于區域時,將剛好全部填充;當位圖大于區域時,位圖只能將自身和區
域一樣大小的內存信息填充到區域中。

??位圖填充支持兩種實現方式:其一、用戶通過HI_MPI_RGN_SetBitMap 接口將位圖數據拷貝至內部顯示畫布;其二、用戶通過 HI_MPI_RGN_GetCanvasInfo 獲取內部備份顯示畫布的地址,直接對該地址數據進行更新,然后調用HI_MPI_RGN_UpdateCanvas 接口將備份顯示畫布更新為待顯示畫布,達到實現更新位圖數據的目的。

(3)區域公共屬性
??用戶創建一個區域時,需要設置該屬性信息,它包含公共的資源信息。例如,Overlay 包含像素格式,大小和背景色。

(4)通道顯示屬性
??通道顯示屬性表明區域在某通道的顯示特征。例如, Overlay 的通道顯示屬性包含顯示位置,層次,前景 Alpha,背景 Alpha,還有編碼用到的 QP 信息。當通道顯示屬性中的區域是否顯示(bShow)為 TRUE 時,表示顯示在該通道中;反之,表示在該通道中存在,但處于隱藏狀態。

(5)區域反色
??當區域疊加到視頻上顯示時,如果視頻背景與疊加區域的亮度色度相近,往往會導致背景與區域很難進行區分。區域反色功能即針對這種場景,自適應背景的變化,對區域的亮度色度進行調整,實現區域清晰可見

??區域反色功能支持實現方式如下:通過 VPSS 提供的區域亮度和統計功能。用戶可實時獲取視頻序列中每個待疊加區域背景的亮度統計,然后利用 TDE 的 ROP功能,對區域進行手動的反色處理,最后通過 VPSS 將該反色后的區域疊加到視頻上。

(6)區域QP保護
??當區域疊加到視頻上進行壓縮編碼時,為了保證疊加區域的清晰度不因為數據壓縮而變模糊,可以單獨設定疊加區域部分的壓縮特性,即設定 QP 保護功能參數。 QP 保護功能是 Overlay 特有的功能,且僅針對 H.264/H.265 類型編碼通道有效,對其它類型無效。

5、海思平臺OSD使用方法

(1)用戶填充區域屬性并創建區域

(2)將該區域指定到具體通道中(如 VENC)

??以上步驟完成區域的創建和使用。用戶還可以通過以下操作來控制區域屬性以及在某通道的通道顯示屬性.

(3)通過 HI_MPI_RGN_GetAttr、 HI_MPI_RGN_SetAttr 獲取和設置區域屬性

(4)通過 HI_MPI_RGN_SetBitMap(僅針對 Overlay)設置區域的位圖信息

(5)通過 HI_MPI_RGN_GetDisplayAttr 和 HI_MPI_RGN_SetDisplayAttr 獲取和設置區域在某通道(如 VENC 通道)的通道顯示屬性。

(6)最后用戶可以將該區域從通道中撤出(非必須操作),再銷毀區域

6、海思平臺OSD的API和關鍵數據結構

區域管理模塊主要提供區域資源的控制管理功能,包括區域的創建、銷毀,獲取與設 置區域屬性,獲取與設置區域的通道顯示屬性等。 該功能模塊提供以下 MPI:HI_MPI_RGN_Create:創建區域。HI_MPI_RGN_Destroy:銷毀區域。HI_MPI_RGN_GetAttr:獲取區域屬性HI_MPI_RGN_SetAttr:設置區域屬性。HI_MPI_RGN_SetBitMap:設置區域位圖。HI_MPI_RGN_SetAttachField:設置區域要疊加到的幀/場標志。HI_MPI_RGN_GetAttachField:獲取區域要疊加到的幀/場標志。HI_MPI_RGN_AttachToChn:將區域疊加到通道上。HI_MPI_RGN_DetachFromChn:將區域從通道中撤出。HI_MPI_RGN_SetDisplayAttr:設置區域的通道顯示屬性。HI_MPI_RGN_GetDisplayAttr:獲取區域的通道顯示屬性。HI_MPI_RGN_GetCanvasInfo:獲取區域畫布信息。HI_MPI_RGN_UpdateCanvas:更新區域畫布信息。以上API具體參數及使用方法和一些關鍵數據結構參考:《HiMPP IPC V2.0 媒體處理軟件開發參考.pdf》


二、OSD實驗演示和代碼框架分析

1、OSD實驗演示


在畫面中添加了四個水印。

2、OSD代碼框架分析

使用SourceInsight軟件創建工程,分析源碼。源碼鏈接如下:

鏈接:https://pan.baidu.com/s/1fV8TqpLtbH6YljoNKPRV3Q 提取碼:67pc --來自百度網盤超級會員V5的分享

以sample_venc.c文件為重點進行分心,main主函數也在該文件。

main()SAMPLE_VENC_720P_CLASSIC()SAMPLE_RGN_CreateVideoRegion();HH_OSD_Init(); //實現靜態內容HH_OSD_All_Refresh();//實現動態內容


??只要綁定好,剩下的工作都是自動的,因為海思的mpp框架都已經實現好了,內部開啟了多個線程進行工作。

三、OSD代碼實現分析

1、SAMPLE_RGN_CreateVideoRegion()所做的事

執行該函數所產生的效果:

(1)函數調用關系

SAMPLE_RGN_CreateVideoRegionSAMPLE_RGN_CreateOverlayForVencHI_MPI_RGN_Create 創建區域HI_MPI_RGN_AttachToChn 將區域疊加到通道上SAMPLE_RGN_AddSAMPLE_RGN_CreateOverlayForVencpthread_create(&osd_ThreadId, NULL, SAMPLE_RGN_AddVideoTimestamp, NULL);SAMPLE_RGN_AddVideoTimestamp HI_S32 SAMPLE_RGN_CreateVideoRegion(HI_VOID) {HI_U32 u32ChnId = 0;RGN_HANDLE Handle = 0;//下面定義的四個變量均與OSD有關HI_U32 coordinate_x = 0;//描述坐標的變量HI_U32 coordinate_y = 0;HI_U32 region_with = 0;//區域的寬HI_U32 region_height = 0;//區域的高u32ChnId = VENC_RECORD_CHNID;//使用的通道的id,venc的通道0region_with = 480;// 320 *3 / 2,3表示使用圖像的bpp,顯存是argb1555,2個字節,故除二region_height = 320;// 320coordinate_x = 0;coordinate_y = 720 - 320;Handle = VENC_RECORD_LOGO_OSD_HANDLE;//RGN:表示region,即區域SAMPLE_RGN_CreateOverlayForVenc(u32ChnId, Handle, coordinate_x, coordinate_y, region_with, region_height);SAMPLE_RGN_Add( Handle, VENC_RECORD_LOGO_OSD_HANDLE);//上邊執行的兩個函數實現了一個左下角的區域靜態畫面//下邊的內容實現了一個右下角的動態畫面Handle = VENC_RECORD_TIME_OSD_HANDLE;//區域句柄號。必須是未使用的 Handle 號//取值范圍: [0, RGN_HANDLE_MAX)。//24bit的bmp圖片,一個像素點就是三字節。一個字節8bitregion_with = 544; //18個字體14*32+4*16+16=528, 預留16像素空間 region_height = 24; coordinate_x = 1280-16-260;//根據需求調整位置coordinate_y = 720 - 24-12;//下面預留12像素空間SAMPLE_RGN_CreateOverlayForVenc(u32ChnId, Handle, coordinate_x, coordinate_y, region_with, region_height);pthread_t osd_ThreadId = 0;pthread_create(&osd_ThreadId, NULL, SAMPLE_RGN_AddVideoTimestamp, NULL);//因為在SAMPLE_RGN_AddVideoTimestamp//中有while(1),如果不開啟一個線程,程序將會卡在這里return HI_SUCCESS; }

(2)RGN(region,區域)畫布尺寸計算:以像素為單位。原始圖像是bpp24的,每個像素3字節。而畫布的圖像是ARGB1555的,所以每個像素是2字節。所以畫布每一行的像素數是圖像寬度*3/2 。

(3)整個圖像的坐標系是左上角是(0,0)點,寬度方向是x,高度方向是y

2、前景和背景透明

(1)所謂前景foreground,就是圖片中顯示的內容部分;所謂背景background,就是圖片中沒有內容的部分。

(2)前景和背景的透明度范圍都是0-128,其中0代表全透明,128代表全不透明

(3)前景和背景透明度可以同時設置,各自起作用,互不影響。

(4)stRgnAttr.unAttr.stOverlay.u32BgColor是RGN的畫布(canvas,等同于LCD顯示時的顯存fb)的背景顏色。也就是畫布中沒有被填充的部分默認顯示的顏色。

3、RGN(region)通道屬性分析

HI_S32 SAMPLE_RGN_CreateOverlayForVenc(HI_U32 u32ChnId, RGN_HANDLE Handle, HI_U32 u32X, HI_U32 u32Y, HI_U32 u32Width, HI_U32 u32Height) {//printf("u32X = %d u32Y = %d \n",u32X,u32Y);HI_S32 s32Ret = 0;MPP_CHN_S stChn;RGN_ATTR_S stRgnAttr;RGN_CHN_ATTR_S stChnAttr;/* Add cover to vpss group */stChn.enModId = HI_ID_VENC;stChn.s32DevId = 0;stChn.s32ChnId = u32ChnId/*0*/;stRgnAttr.enType = OVERLAY_RGN;stRgnAttr.unAttr.stOverlay.enPixelFmt = PIXEL_FORMAT_RGB_1555;//像素格式stRgnAttr.unAttr.stOverlay.stSize.u32Width = u32Width; //16x, value=bmp's Widthx3/2stRgnAttr.unAttr.stOverlay.stSize.u32Height = u32Height; //16x//stRgnAttr.unAttr.stOverlay.u32CanvasNum = 4; //Max:6stRgnAttr.unAttr.stOverlay.u32BgColor = 0xffffffff;//背景色s32Ret = HI_MPI_RGN_Create(Handle, &stRgnAttr);if (s32Ret != HI_SUCCESS){printf("--@@_1 HI_MPI_RGN_Create failed! s32Ret: 0x%x.\n", s32Ret);return s32Ret;}// 以下的內容是進行通道屬性的設置stChnAttr.bShow = HI_TRUE ; //region是否顯示stChnAttr.enType = OVERLAY_RGN;//OSD類型stChnAttr.unChnAttr.stOverlayChn.stPoint.s32X = u32X; //區域的X坐標stChnAttr.unChnAttr.stOverlayChn.stPoint.s32Y = u32Y; //區域的y坐標stChnAttr.unChnAttr.stOverlayChn.u32BgAlpha = 0; //背景透明度,透明度范圍0-128stChnAttr.unChnAttr.stOverlayChn.u32FgAlpha = 128;//前景透明度stChnAttr.unChnAttr.stOverlayChn.u32Layer = 4 /*7 Handle*/;//區域層次// below para must keepstChnAttr.unChnAttr.stOverlayChn.stQpInfo.bAbsQp = HI_FALSE ;//是否開啟qp區域保護stChnAttr.unChnAttr.stOverlayChn.stQpInfo.s32Qp = 0;stChnAttr.unChnAttr.stOverlayChn.stQpInfo.bQpDisable = HI_FALSE ;// 區域反色功能相關的stChnAttr.unChnAttr.stOverlayChn.stInvertColor.stInvColArea.u32Height = 48/*16 * (Handle % 2 + 1)*/;stChnAttr.unChnAttr.stOverlayChn.stInvertColor.stInvColArea.u32Width = 48/*16 * (Handle % 2 + 1)*/;stChnAttr.unChnAttr.stOverlayChn.stInvertColor.u32LumThresh = 128;stChnAttr.unChnAttr.stOverlayChn.stInvertColor.enChgMod = LESSTHAN_LUM_THRESH;stChnAttr.unChnAttr.stOverlayChn.stInvertColor.bInvColEn = HI_FALSE ;s32Ret = HI_MPI_RGN_AttachToChn(Handle, &stChn, &stChnAttr);//將區域疊加到通道上if (s32Ret != HI_SUCCESS){printf("HI_MPI_RGN_AttachToChn failed! s32Ret: 0x%x.\n", s32Ret);return s32Ret;}return HI_SUCCESS; }

4、RGN(region)內容填充

HI_S32 SAMPLE_RGN_Add(unsigned int Handle,int Type) {//printf("-------------------%s add rgn %d --------------------\n",__func__,Type);HI_S32 s32Ret = HI_SUCCESS;RGN_ATTR_S stRgnAttrSet;RGN_CANVAS_INFO_S stCanvasInfo;BITMAP_S stBitmap;SIZE_S stSize;/* Photo logo */s32Ret = HI_MPI_RGN_GetAttr(Handle/*VencOsdHandle*/, &stRgnAttrSet);//獲取區域屬性if (HI_SUCCESS != s32Ret){printf("HI_MPI_RGN_GetAttr failed! s32Ret: 0x%x.\n", s32Ret);return s32Ret;}s32Ret = HI_MPI_RGN_GetCanvasInfo(Handle/*VencOsdHandle*/, &stCanvasInfo);//獲取區域畫布信息if (HI_SUCCESS != s32Ret){printf("HI_MPI_RGN_GetCanvasInfo failed! s32Ret: 0x%x.\n", s32Ret);return s32Ret;}stBitmap.pData = (void*)stCanvasInfo.u32VirtAddr;//位圖數據stSize.u32Width = stCanvasInfo.stSize.u32Width;//位圖寬度stSize.u32Height = stCanvasInfo.stSize.u32Height;//位圖高度s32Ret = SAMPLE_RGN_UpdateCanvas(Type, &stBitmap, HI_TRUE , 0x0000, &stSize, stCanvasInfo.u32Stride,stRgnAttrSet.unAttr.stOverlayEx.enPixelFmt);if (HI_SUCCESS != s32Ret)//將要顯示的內容丟到備份的內存中,等待使用{printf("SAMPLE_RGN_UpdateCanvas failed! s32Ret: 0x%x.\n", s32Ret);return s32Ret;}s32Ret = HI_MPI_RGN_UpdateCanvas(Handle/*VencOsdHandle*/);//更新區域畫布信息if (HI_SUCCESS != s32Ret)//將備份內存中的數據直接刷到畫布去顯示{printf("HI_MPI_RGN_UpdateCanvas failed! s32Ret: 0x%x.\n", s32Ret);return s32Ret;}return HI_SUCCESS; }

(1)程序中會有一個RGB888向ARGB1555轉的過程。
(2)BMP圖片中存儲圖像的像素順序,和RGN的canvas里像素順序是不同的。

這部分內容涉及到了bmp圖片的解析以及如何顯示,若是之前未了解過該方面的知識,可參考我的《BMP圖片顯示原理》

5、動態刷新BMP


??將上圖中這些帶有數字的圖片不斷切換顯示,形成數字變化的效果。

HI_VOID* SAMPLE_RGN_AddVideoTimestamp(HI_VOID* p)//真正網絡攝像機一般會從服務器獲取時間而非本地 {HI_S32 s32Ret = HI_SUCCESS;time_t timep;struct tm *pLocalTime;HI_U8 seconds = 80;RGN_HANDLE Handle;Handle = VENC_RECORD_TIME_OSD_HANDLE;while (1){time(&timep);pLocalTime = localtime(&timep);//轉換成當前時間if (seconds == pLocalTime->tm_sec){usleep(150*1000);//增加循環的時間,屏幕上的內容是每過一秒刷新一次的continue;} else {seconds = pLocalTime->tm_sec;}s32Ret = SAMPLE_RGN_Add( Handle, VENC_RECORD_TIME_OSD_HANDLE);//關鍵在這if (HI_SUCCESS != s32Ret){printf("SAMPLE_RGN_Add line %d failed! s32Ret: 0x%x.\n",__LINE__, s32Ret);break;}}pthread_detach(pthread_self());//分離線程return 0; }

總結:左下角的就是單bmp圖片OSD,靜態的;右下角是多BMP圖片組合,且動態刷新顯示。

6、小結——整體函數調用層次

SAMPLE_RGN_CreateVideoRegionSAMPLE_RGN_CreateOverlayForVencHI_MPI_RGN_Create //創建一個區域HI_MPI_RGN_AttachToChn //將區域疊加到通道上SAMPLE_RGN_AddHI_MPI_RGN_GetAttr //獲取區域屬性HI_MPI_RGN_GetCanvasInfo //獲取區域畫布信息SAMPLE_RGN_UpdateCanvas //將要顯示的內容丟到備份的內存中,等待使用SAMPLE_RGN_CreateSurfaceByCanvas //解析BMP數據,創建要顯示的內容SAMPLE_RGN_LoadCanvasEx 加載數據SAMPLE_RGN_LoadBMPCanvas_Logo//獲取要顯示的logo數據GetBmpInfo //得到bmp圖片的信息mallocfseekfreadOSD_MAKECOLOR_U16 //RGB888向ARGB1555轉的過程 HI_MPI_RGN_UpdateCanvas //更新區域畫布信息SAMPLE_RGN_CreateOverlayForVencpthread_create(&osd_ThreadId, NULL, SAMPLE_RGN_AddVideoTimestamp, NULL);SAMPLE_RGN_AddVideoTimestampSAMPLE_RGN_AddHI_MPI_RGN_GetAttr //獲取區域屬性HI_MPI_RGN_GetCanvasInfo //獲取區域畫布信息SAMPLE_RGN_UpdateCanvas //將要顯示的內容丟到備份的內存中,等待使用SAMPLE_RGN_CreateSurfaceByCanvas //解析BMP數據,創建要顯示的內容SAMPLE_RGN_LoadCanvasEx //加載數據SAMPLE_RGN_LoadBMPCanvas_TimeSmap//通過動態刷新bmp圖片顯示時間

注:本文章參考了《朱老師物聯網大講堂》課程筆記,并結合了自己的實際開發經歷以及網上他人的技術文章,綜合整理得到。如有侵權,聯系刪除!水平有限,歡迎各位在評論區交流。

總結

以上是生活随笔為你收集整理的海思平台OSD的实现(1)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。